Live video on the AT Protocol

Merge pull request #291 from streamplace/natb/auto-resume-video

fix: retry video when we get segments

authored by

Eli Mallon and committed by
GitHub
0b0bdee9 87a26275

+24 -29
+24 -29
js/app/components/player/video-retry.tsx
··· 1 1 import { 2 - PlayerStatus, 3 2 usePlayerStore, 3 + useSegment, 4 4 useStreamplaceStore, 5 5 } from "@streamplace/components"; 6 - import React, { useEffect, useState } from "react"; 6 + import React, { useEffect } from "react"; 7 + 8 + import { useRef } from "react"; 7 9 8 10 export default function VideoRetry(props: { children: React.ReactNode }) { 9 - const [resetTime, setResetTime] = useState<number>(Date.now()); 10 - const [retryCount, setRetryCount] = useState(0); 11 + const lastSegmentRef = useRef<string | null>(null); 12 + const retryTimeoutRef = useRef<NodeJS.Timeout | null>(null); 13 + const segment = useSegment(); 11 14 12 - const status = usePlayerStore((x) => x.status); 13 - const playerEvent = usePlayerStore((x) => x.playerEvent); 14 - 15 + const offline = usePlayerStore((x) => x.offline); 15 16 const spurl = useStreamplaceStore((x) => x.url); 16 17 17 - const isPlaying = status === PlayerStatus.PLAYING; 18 - 19 18 useEffect(() => { 20 - if (isPlaying) { 21 - setRetryCount(0); 22 - return; 19 + if ( 20 + lastSegmentRef.current !== null && 21 + segment && 22 + segment.startTime !== lastSegmentRef.current && 23 + offline 24 + ) { 25 + const jitter = 500 + Math.random() * 1500; 26 + retryTimeoutRef.current = setTimeout(() => { 27 + lastSegmentRef.current = segment?.startTime; 28 + }, jitter); 23 29 } 24 - 25 - const baseDelay = 3000; // 3 seconds 26 - const maxDelay = 30000; // 30 seconds 27 - const delay = Math.min(baseDelay * Math.pow(2, retryCount), maxDelay); 28 - 29 - const handle = setTimeout(() => { 30 - // console.log(`retrying (attempt ${retryCount + 1}, delay: ${delay}ms)`); 31 - setResetTime(Date.now()); 32 - setRetryCount((prev) => prev + 1); 33 - playerEvent(spurl, new Date().toISOString(), "retry", { 34 - delay, 35 - }); 36 - }, delay); 30 + }, [offline, segment, spurl]); 37 31 38 - return () => clearTimeout(handle); 39 - }, [isPlaying, resetTime, retryCount, playerEvent]); 40 - 41 - return <React.Fragment>{props.children}</React.Fragment>; 32 + return ( 33 + <React.Fragment key={lastSegmentRef.current}> 34 + {props.children} 35 + </React.Fragment> 36 + ); 42 37 }