From 2172ac43ff020d0c2229ff731b12dcf25d387551 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Sun, 3 Mar 2024 16:43:06 -0700 Subject: [PATCH] Add preview only mode to make loading more efficeint --- .../components/player/DynamicVideoPlayer.tsx | 108 ++++++++++-------- web/src/pages/Events.tsx | 4 +- web/src/views/events/EventView.tsx | 9 +- ...topRecordingView.tsx => RecordingView.tsx} | 6 +- 4 files changed, 70 insertions(+), 57 deletions(-) rename web/src/views/events/{DesktopRecordingView.tsx => RecordingView.tsx} (97%) diff --git a/web/src/components/player/DynamicVideoPlayer.tsx b/web/src/components/player/DynamicVideoPlayer.tsx index e747a6eae..4b669d360 100644 --- a/web/src/components/player/DynamicVideoPlayer.tsx +++ b/web/src/components/player/DynamicVideoPlayer.tsx @@ -28,7 +28,7 @@ type DynamicVideoPlayerProps = { camera: string; timeRange: { start: number; end: number }; cameraPreviews: Preview[]; - defaultMode?: PlayerMode; + previewOnly?: boolean; onControllerReady?: (controller: DynamicVideoController) => void; }; export default function DynamicVideoPlayer({ @@ -36,7 +36,7 @@ export default function DynamicVideoPlayer({ camera, timeRange, cameraPreviews, - defaultMode = "playback", + previewOnly = false, onControllerReady, }: DynamicVideoPlayerProps) { const apiHost = useApiHost(); @@ -64,7 +64,7 @@ export default function DynamicVideoPlayer({ const playerRef = useRef(undefined); const previewRef = useRef(undefined); - const [isScrubbing, setIsScrubbing] = useState(defaultMode == "scrubbing"); + const [isScrubbing, setIsScrubbing] = useState(previewOnly); const [hasPreview, setHasPreview] = useState(false); const [focusedItem, setFocusedItem] = useState( undefined, @@ -78,11 +78,11 @@ export default function DynamicVideoPlayer({ playerRef, previewRef, (config.cameras[camera]?.detect?.annotation_offset || 0) / 1000, - defaultMode, + previewOnly ? "scrubbing" : "playback", setIsScrubbing, setFocusedItem, ); - }, [camera, config, defaultMode]); + }, [camera, config, previewOnly]); // keyboard control @@ -178,12 +178,12 @@ export default function DynamicVideoPlayer({ }; }, [timeRange]); const { data: recordings } = useSWR( - [`${camera}/recordings`, recordingParams], + previewOnly ? null : [`${camera}/recordings`, recordingParams], { revalidateOnFocus: false }, ); useEffect(() => { - if (!controller || !recordings) { + if (!controller || (!previewOnly && !recordings)) { return; } @@ -204,7 +204,7 @@ export default function DynamicVideoPlayer({ setHasPreview(preview != undefined); controller.newPlayback({ - recordings, + recordings: recordings ?? [], playbackUri, preview, }); @@ -219,49 +219,53 @@ export default function DynamicVideoPlayer({ return (
-
- { - playerRef.current = player; - player.on("playing", () => setFocusedItem(undefined)); - player.on("timeupdate", () => { - controller.updateProgress(player.currentTime() || 0); - }); - player.on("ended", () => controller.fireClipChangeEvent("forward")); - - if (onControllerReady) { - onControllerReady(controller); - } - }} - onDispose={() => { - playerRef.current = undefined; - }} + {!previewOnly && ( +
- {config && focusedItem && ( - - )} - -
+ { + playerRef.current = player; + player.on("playing", () => setFocusedItem(undefined)); + player.on("timeupdate", () => { + controller.updateProgress(player.currentTime() || 0); + }); + player.on("ended", () => + controller.fireClipChangeEvent("forward"), + ); + + if (onControllerReady) { + onControllerReady(controller); + } + }} + onDispose={() => { + playerRef.current = undefined; + }} + > + {config && focusedItem && ( + + )} + +
+ )}
@@ -281,6 +285,10 @@ export default function DynamicVideoPlayer({ player.pause(); player.on("seeked", () => controller.finishedSeeking()); player.on("loadeddata", () => controller.previewReady()); + + if (previewOnly && onControllerReady) { + onControllerReady(controller); + } }} onDispose={() => { previewRef.current = undefined; diff --git a/web/src/pages/Events.tsx b/web/src/pages/Events.tsx index faece1026..3d601e290 100644 --- a/web/src/pages/Events.tsx +++ b/web/src/pages/Events.tsx @@ -5,8 +5,8 @@ import useOverlayState from "@/hooks/use-overlay-state"; import { FrigateConfig } from "@/types/frigateConfig"; import { Preview } from "@/types/preview"; import { ReviewFilter, ReviewSegment, ReviewSeverity } from "@/types/review"; -import DesktopRecordingView from "@/views/events/DesktopRecordingView"; import EventView from "@/views/events/EventView"; +import RecordingView from "@/views/events/RecordingView"; import axios from "axios"; import { useCallback, useMemo, useState } from "react"; import useSWR from "swr"; @@ -220,7 +220,7 @@ export default function Events() { if (selectedData) { return ( - { videoPlayersRef.current[camera.name] = controller; setPlayerReady(true); diff --git a/web/src/views/events/DesktopRecordingView.tsx b/web/src/views/events/RecordingView.tsx similarity index 97% rename from web/src/views/events/DesktopRecordingView.tsx rename to web/src/views/events/RecordingView.tsx index 2f646e7bf..a120ebb00 100644 --- a/web/src/views/events/DesktopRecordingView.tsx +++ b/web/src/views/events/RecordingView.tsx @@ -10,16 +10,16 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { IoMdArrowRoundBack } from "react-icons/io"; import { useNavigate } from "react-router-dom"; -type DesktopRecordingViewProps = { +type RecordingViewProps = { selectedReview: ReviewSegment; reviewItems: ReviewSegment[]; relevantPreviews?: Preview[]; }; -export default function DesktopRecordingView({ +export default function RecordingView({ selectedReview, reviewItems, relevantPreviews, -}: DesktopRecordingViewProps) { +}: RecordingViewProps) { const navigate = useNavigate(); const contentRef = useRef(null);