diff --git a/frigate/config.py b/frigate/config.py index f3e760b6a..85685e8e9 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -269,6 +269,9 @@ class DetectConfig(FrigateBaseModel): default_factory=StationaryConfig, title="Stationary objects config.", ) + annotation_offset: int = Field( + default=0, title="Milliseconds to offset detect annotations by." + ) class FilterConfig(FrigateBaseModel): diff --git a/web/src/components/TimelineSummary.jsx b/web/src/components/TimelineSummary.jsx index 8e5af9654..7a16bb1aa 100644 --- a/web/src/components/TimelineSummary.jsx +++ b/web/src/components/TimelineSummary.jsx @@ -5,7 +5,7 @@ import { formatUnixTimestampToDateTime } from '../utils/dateUtil'; import PlayIcon from '../icons/Play'; import ExitIcon from '../icons/Exit'; import { Zone } from '../icons/Zone'; -import { useState } from 'preact/hooks'; +import { useMemo, useState } from 'preact/hooks'; import Button from './Button'; export default function TimelineSummary({ event, onFrameSelected }) { @@ -18,6 +18,14 @@ export default function TimelineSummary({ event, onFrameSelected }) { const { data: config } = useSWR('config'); + const annotationOffset = useMemo(() => { + if (!config) { + return 0; + } + + return (config.cameras[event.camera]?.detect?.annotation_offset || 0) / 1000; + }, [config, event]); + const [timeIndex, setTimeIndex] = useState(-1); const recordingParams = { @@ -53,7 +61,7 @@ export default function TimelineSummary({ event, onFrameSelected }) { const onSelectMoment = async (index) => { setTimeIndex(index); - onFrameSelected(eventTimeline[index], getSeekSeconds(eventTimeline[index].timestamp)); + onFrameSelected(eventTimeline[index], getSeekSeconds(eventTimeline[index].timestamp + annotationOffset)); }; if (!eventTimeline || !config) {