From fba967c74be0b6aa5bc630ae2c3eb7d070ab8761 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Tue, 10 Nov 2026 07:57:21 -0600 Subject: [PATCH] fix annotation offset seeking in tracking details (#24936) The VOD manifest used to find the keyframe-snapped clip start was built from the live annotation offset while the playing clip used the offset from when the event opened. Each offset step fetched a manifest for a different clip, so the seek mapping drifted: the video jumped forward about one GOP every second of offset and flickered while each new manifest loaded. The manifest now uses the same stable source offset as the playlist --- web/src/components/overlay/detail/TrackingDetails.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/web/src/components/overlay/detail/TrackingDetails.tsx b/web/src/components/overlay/detail/TrackingDetails.tsx index f9e6193299..21066471fe 100644 --- a/web/src/components/overlay/detail/TrackingDetails.tsx +++ b/web/src/components/overlay/detail/TrackingDetails.tsx @@ -150,17 +150,18 @@ export function TrackingDetails({ // Fetch the VOD manifest JSON to get the actual clipFrom after keyframe // snapping. The backend may snap clipFrom backwards to a keyframe, making - // the video start earlier than the requested time. + // the video start earlier than the requested time. Uses sourceOffsetRef so + // the manifest describes the same clip as videoSource. const vodManifestUrl = useMemo(() => { if (!event.camera) return null; - const startTime = - event.start_time + annotationOffset / 1000 - REVIEW_PADDING; + const sourceOffset = sourceOffsetRef.current; + const startTime = event.start_time + sourceOffset / 1000 - REVIEW_PADDING; const endTime = (event.end_time ?? Date.now() / 1000) + - annotationOffset / 1000 + + sourceOffset / 1000 + REVIEW_PADDING; return `vod/clip/${event.camera}/start/${startTime}/end/${endTime}`; - }, [event, annotationOffset]); + }, [event]); const { data: vodManifest } = useSWR(vodManifestUrl, null, { revalidateOnFocus: false,