diff --git a/web/src/components/player/HlsVideoPlayer.tsx b/web/src/components/player/HlsVideoPlayer.tsx index 6d6df7268..0ede0ea3c 100644 --- a/web/src/components/player/HlsVideoPlayer.tsx +++ b/web/src/components/player/HlsVideoPlayer.tsx @@ -42,6 +42,7 @@ type HlsVideoPlayerProps = { onClipEnded?: () => void; onPlayerLoaded?: () => void; onTimeUpdate?: (time: number) => void; + onPlaying?: () => void; }; export default function HlsVideoPlayer({ className, @@ -51,6 +52,7 @@ export default function HlsVideoPlayer({ onClipEnded, onPlayerLoaded, onTimeUpdate, + onPlaying, }: HlsVideoPlayerProps) { // playback @@ -183,6 +185,7 @@ export default function HlsVideoPlayer({ setMobileCtrlTimeout(setTimeout(() => setControls(false), 4000)); } }} + onPlaying={onPlaying} onPause={() => { setIsPlaying(false); diff --git a/web/src/components/player/PreviewPlayer.tsx b/web/src/components/player/PreviewPlayer.tsx index 9206f7e9b..2539faaa2 100644 --- a/web/src/components/player/PreviewPlayer.tsx +++ b/web/src/components/player/PreviewPlayer.tsx @@ -272,26 +272,25 @@ class PreviewVideoController extends PreviewController { } if (this.timeToSeek) { - if ( - Math.round(this.previewRef.current.currentTime + this.preview.start) != - Math.round(this.timeToSeek) - ) { - if (isAndroid) { - const currentTs = - this.previewRef.current.currentTime + this.preview.start; - const diff = this.timeToSeek - currentTs; + const diff = + Math.round(this.timeToSeek) - + Math.round(this.previewRef.current.currentTime + this.preview.start); + if (Math.abs(diff) > 1) { + let seekTime; + if (isAndroid) { if (diff < 30) { - this.previewRef.current.currentTime = - this.previewRef.current.currentTime + diff / 2; + seekTime = Math.round( + this.previewRef.current.currentTime + diff / 2, + ); } else { - this.previewRef.current.currentTime = - this.timeToSeek - this.preview.start; + seekTime = Math.round(this.timeToSeek - this.preview.start); } } else { - this.previewRef.current.currentTime = - this.timeToSeek - this.preview.start; + seekTime = this.timeToSeek - this.preview.start; } + + this.previewRef.current.currentTime = seekTime; } else { this.seeking = false; this.timeToSeek = undefined; diff --git a/web/src/components/player/dynamic/DynamicVideoController.ts b/web/src/components/player/dynamic/DynamicVideoController.ts index 2b3956db7..d30976447 100644 --- a/web/src/components/player/dynamic/DynamicVideoController.ts +++ b/web/src/components/player/dynamic/DynamicVideoController.ts @@ -81,13 +81,27 @@ export class DynamicVideoController { this.playerController.currentTime = seekSeconds; if (play) { - this.playerController.play(); + this.waitAndPlay(); } else { this.playerController.pause(); } } } + waitAndPlay() { + return new Promise((resolve) => { + const onSeekedHandler = () => { + this.playerController.removeEventListener("seeked", onSeekedHandler); + this.playerController.play(); + resolve(undefined); + }; + + this.playerController.addEventListener("seeked", onSeekedHandler, { + once: true, + }); + }); + } + seekToTimelineItem(timeline: Timeline) { this.playerController.pause(); this.seekToTimestamp(timeline.timestamp + this.annotationOffset); diff --git a/web/src/components/player/dynamic/DynamicVideoPlayer.tsx b/web/src/components/player/dynamic/DynamicVideoPlayer.tsx index da169a838..3c656a4a7 100644 --- a/web/src/components/player/dynamic/DynamicVideoPlayer.tsx +++ b/web/src/components/player/dynamic/DynamicVideoPlayer.tsx @@ -90,12 +90,19 @@ export default function DynamicVideoPlayer({ // initial state + const [isLoading, setIsLoading] = useState(false); const [source, setSource] = useState( `${apiHost}vod/${camera}/start/${timeRange.start}/end/${timeRange.end}/master.m3u8`, ); // start at correct time + useEffect(() => { + if (isScrubbing) { + setIsLoading(true); + } + }, [isScrubbing]); + const onPlayerLoaded = useCallback(() => { if (!controller || !startTimestamp) { return; @@ -140,6 +147,7 @@ export default function DynamicVideoPlayer({ setSource( `${apiHost}vod/${camera}/start/${timeRange.start}/end/${timeRange.end}/master.m3u8`, ); + setIsLoading(true); controller.newPlayback({ recordings: recordings ?? [], @@ -151,14 +159,17 @@ export default function DynamicVideoPlayer({ return (