diff --git a/web/src/components/TimelineSummary.jsx b/web/src/components/TimelineSummary.jsx index edad60255..4ebf1117d 100644 --- a/web/src/components/TimelineSummary.jsx +++ b/web/src/components/TimelineSummary.jsx @@ -7,6 +7,7 @@ import ExitIcon from '../icons/Exit'; import { Zone } from '../icons/Zone'; import { useState } from 'preact/hooks'; import Button from './Button'; +import { getUnixTime } from 'date-fns'; export default function TimelineSummary({ event, onFrameSelected }) { const { data: eventTimeline } = useSWR([ @@ -20,15 +21,50 @@ export default function TimelineSummary({ event, onFrameSelected }) { const [timeIndex, setTimeIndex] = useState(-1); + const recordingParams = { + before: event.end_time || getUnixTime(), + after: event.start_time, + }; + const { data: recordings } = useSWR([`${event.camera}/recordings`, recordingParams], { revalidateOnFocus: false }); + + // calculates the seek seconds by adding up all the seconds in the segments prior to the playback time + const getSeekSeconds = (seekUnix) => { + if (!recordings) { + return 0; + } + + let seekSeconds = 0; + recordings.every((segment) => { + // if the next segment is past the desired time, stop calculating + if (segment.start_time > seekUnix) { + return false; + } + + if (segment.end_time < seekUnix) { + seekSeconds += segment.end_time - segment.start_time; + return true; + } + + seekSeconds += segment.end_time - segment.start_time - (segment.end_time - seekUnix); + return true; + }); + + return seekSeconds; + }; + const onSelectMoment = async (index) => { setTimeIndex(index); - onFrameSelected(eventTimeline[index]); + onFrameSelected(eventTimeline[index], getSeekSeconds(eventTimeline[index].timestamp)); }; if (!eventTimeline || !config) { return ; } + if (eventTimeline.length == 0) { + return
; + } + return (
diff --git a/web/src/routes/Events.jsx b/web/src/routes/Events.jsx index c676cb108..836b99ae6 100644 --- a/web/src/routes/Events.jsx +++ b/web/src/routes/Events.jsx @@ -182,14 +182,10 @@ export default function Events({ path, ...props }) { onFilter(name, items); }; - const onEventFrameSelected = (event, frame) => { - const eventDuration = event.end_time - event.start_time; - + const onEventFrameSelected = (event, frame, seekSeconds) => { if (this.player) { this.player.pause(); - const videoOffset = this.player.duration() - eventDuration; - const startTime = videoOffset + (frame.timestamp - event.start_time); - this.player.currentTime(startTime); + this.player.currentTime(seekSeconds); setEventOverlay(frame); } }; @@ -590,7 +586,7 @@ export default function Events({ path, ...props }) {
onEventFrameSelected(event, frame)} + onFrameSelected={(frame, seekSeconds) => onEventFrameSelected(event, frame, seekSeconds)} />