diff --git a/frigate/http.py b/frigate/http.py index 0c263cbe1..cac6a3a93 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -1859,6 +1859,7 @@ def recordings(camera_name): Recordings.segment_size, Recordings.motion, Recordings.objects, + Recordings.duration, ) .where( Recordings.camera == camera_name, diff --git a/frigate/util/services.py b/frigate/util/services.py index 8c96cd0ee..41a7323d3 100644 --- a/frigate/util/services.py +++ b/frigate/util/services.py @@ -378,7 +378,7 @@ def auto_detect_hwaccel() -> str: try: cuda = False vaapi = False - resp = requests.get("http://192.168.50.106:1984/api/ffmpeg/hardware", timeout=3) + resp = requests.get("http://127.0.0.1:1984/api/ffmpeg/hardware", timeout=3) if resp.status_code == 200: data: dict[str, list[dict[str, str]]] = resp.json() diff --git a/web/src/types/record.ts b/web/src/types/record.ts index 7be7edb8a..a6979aea8 100644 --- a/web/src/types/record.ts +++ b/web/src/types/record.ts @@ -5,6 +5,7 @@ type Recording = { end_time: number; path: string; segment_size: number; + duration: number; motion: number; objects: number; dBFS: number; @@ -17,6 +18,7 @@ type RecordingSegment = { motion: number; objects: number; segment_size: number; + duration: number; }; type RecordingActivity = { diff --git a/web/src/views/history/DesktopTimelineView.tsx b/web/src/views/history/DesktopTimelineView.tsx index 3dc1f25b1..e7acb76c0 100644 --- a/web/src/views/history/DesktopTimelineView.tsx +++ b/web/src/views/history/DesktopTimelineView.tsx @@ -45,7 +45,7 @@ export default function DesktopTimelineView({ const [seeking, setSeeking] = useState(false); const [timeToSeek, setTimeToSeek] = useState(undefined); - const [timelineTime, setTimelineTime] = useState( + const [playerTime, setPlayerTime] = useState( initialPlayback.timelineItems.length > 0 ? initialPlayback.timelineItems[0].timestamp - initialPlayback.range.start : 0 @@ -121,6 +121,28 @@ export default function DesktopTimelineView({ [annotationOffset, recordings, playerRef] ); + const timelineTime = useMemo(() => { + if (scrubbing) { + return playerTime; + } else { + // take a player time in seconds and convert to timestamp in timeline + let timestamp = 0; + let totalTime = 0; + (recordings || []).every((segment) => { + if (totalTime + segment.duration > playerTime) { + // segment is here + timestamp = segment.start_time + (playerTime - totalTime); + return false; + } else { + totalTime += segment.duration; + return true; + } + }); + + return timestamp; + } + }, [playerTime]); + // handle scrolling to initial timeline item useEffect(() => { if (initialScrollRef.current != null) { @@ -151,10 +173,11 @@ export default function DesktopTimelineView({ return; } - setTimelineTime( + setPlayerTime( selectedPlayback.timelineItems.length > 0 - ? selectedPlayback.timelineItems[0].timestamp - : selectedPlayback.range.start + ? selectedPlayback.timelineItems[0].timestamp - + selectedPlayback.range.start + : 0 ); playerRef.current.src({ @@ -269,7 +292,7 @@ export default function DesktopTimelineView({ } player.on("playing", () => onSelectItem(undefined)); player.on("timeupdate", () => { - setTimelineTime(Math.floor(player.currentTime() || 0)); + setPlayerTime(Math.floor(player.currentTime() || 0)); }); }} onDispose={() => { @@ -348,9 +371,7 @@ export default function DesktopTimelineView({ isSelected ? [ { - time: new Date( - (timeline.range.start + timelineTime) * 1000 - ), + time: new Date(timelineTime * 1000), id: "playback", }, ] @@ -370,7 +391,7 @@ export default function DesktopTimelineView({ const seekTimestamp = data.time.getTime() / 1000; const seekTime = seekTimestamp - timeline.relevantPreview.start; - setTimelineTime(seekTimestamp - timeline.range.start); + setPlayerTime(seekTimestamp - timeline.range.start); setTimeToSeek(Math.round(seekTime)); }} timechangedHandler={(data) => {