chore: video section issues

This commit is contained in:
2026-03-20 11:49:12 +05:30
parent 87445d757b
commit 96cc4b6f71
2 changed files with 34 additions and 17 deletions

View File

@@ -32,8 +32,9 @@ type LogAction = { type: 'ADD_LOG'; payload: DetectionLogEntry } | { type: 'CLEA
function logsReducer(state: DetectionLogEntry[], action: LogAction): DetectionLogEntry[] { function logsReducer(state: DetectionLogEntry[], action: LogAction): DetectionLogEntry[] {
switch (action.type) { switch (action.type) {
case 'ADD_LOG': case 'ADD_LOG':
if (state.length > 0 && state[0].frame === action.payload.frame) return state; // Move to top if already exists, or just add to top
return [action.payload, ...state].slice(0, MAX_LOGS); const filtered = state.filter((log) => log.frame !== action.payload.frame);
return [action.payload, ...filtered].slice(0, MAX_LOGS);
case 'CLEAR': case 'CLEAR':
return []; return [];
default: default:
@@ -87,7 +88,10 @@ export default function VideoPlayerSection({
// Custom Hooks // Custom Hooks
const gpsMap = useGpsMap(data); const gpsMap = useGpsMap(data);
const { getNearestDetections } = useFrameDetectionMap(data, detectionType); const { getNearestDetections, sortedDetectionIndices } = useFrameDetectionMap(
data,
detectionType,
);
const { getStickyCounts, sortedFrameIndices } = useCumulativeCounts(data.frames); const { getStickyCounts, sortedFrameIndices } = useCumulativeCounts(data.frames);
// Memoized video URL // Memoized video URL
@@ -119,10 +123,8 @@ export default function VideoPlayerSection({
// Frame stats // Frame stats
setCurrentFrameCounts(counts); setCurrentFrameCounts(counts);
// Logging logic (throttled/batched by frame ID) // Logging logic
if (dets && dets.length > 0 && !loggedFrames.current.has(frame)) { if (dets && dets.length > 0) {
loggedFrames.current.add(frame);
const firstDetId = dets[0].pothole_id ?? dets[0].signboard_id ?? dets[0].detection_id; const firstDetId = dets[0].pothole_id ?? dets[0].signboard_id ?? dets[0].detection_id;
const coords = gpsMap.get(firstDetId); const coords = gpsMap.get(firstDetId);
@@ -148,7 +150,7 @@ export default function VideoPlayerSection({
}); });
} }
}, },
[data.video_info.fps, getNearestDetections, getStickyCounts, gpsMap, sortedFrameIndices], [data.video_info.fps, getNearestDetections, getStickyCounts, gpsMap, sortedDetectionIndices],
); );
// Playback loop hook // Playback loop hook
@@ -173,9 +175,20 @@ export default function VideoPlayerSection({
const handleVideoSeeked = useCallback(() => { const handleVideoSeeked = useCallback(() => {
const video = videoRef.current; const video = videoRef.current;
if (!video) return; if (!video) return;
const frame = Math.round(video.currentTime * data.video_info.fps);
handleFrameUpdate(frame); const fps = data.video_info.fps || 30;
}, [data.video_info.fps, handleFrameUpdate]); const currentFrame = Math.round(video.currentTime * fps);
// Snap to the next available frame index that has detections
const nextDetectionFrame = sortedDetectionIndices.find((f) => f >= currentFrame);
if (nextDetectionFrame !== undefined && nextDetectionFrame !== currentFrame) {
video.currentTime = nextDetectionFrame / fps;
return;
}
handleFrameUpdate(currentFrame);
}, [data.video_info.fps, handleFrameUpdate, sortedDetectionIndices]);
const seekToFrame = useCallback( const seekToFrame = useCallback(
(frame: number) => { (frame: number) => {
@@ -216,7 +229,7 @@ export default function VideoPlayerSection({
onLoadedData={handleLoadedData} onLoadedData={handleLoadedData}
onEnded={handleVideoEnded} onEnded={handleVideoEnded}
onSeeked={handleVideoSeeked} onSeeked={handleVideoSeeked}
currentDetections={getNearestDetections(currentFrame, sortedFrameIndices) || []} currentDetections={getNearestDetections(currentFrame, sortedDetectionIndices) || []}
/> />
<DetectionStatsBar <DetectionStatsBar

View File

@@ -69,18 +69,22 @@ export const useFrameDetectionMap = (data: DetectionData, detectionType: string)
return map; return map;
}, [data, detectionType]); }, [data, detectionType]);
const getNearestDetections = (frame: number, sortedFrameIndices: number[], maxSkip = 3) => { const sortedDetectionIndices = useMemo(() => {
return Array.from(frameDetectionMap.keys()).sort((a, b) => a - b);
}, [frameDetectionMap]);
const getNearestDetections = (frame: number, sortedIndices: number[], maxSkip = 3) => {
const exact = frameDetectionMap.get(frame); const exact = frameDetectionMap.get(frame);
if (exact) return exact; if (exact) return exact;
let low = 0, let low = 0,
high = sortedFrameIndices.length - 1, high = sortedIndices.length - 1,
targetIndex = -1; targetIndex = -1;
while (low <= high) { while (low <= high) {
const mid = Math.floor((low + high) / 2); const mid = Math.floor((low + high) / 2);
if (sortedFrameIndices[mid] <= frame) { if (sortedIndices[mid] <= frame) {
targetIndex = sortedFrameIndices[mid]; targetIndex = sortedIndices[mid];
low = mid + 1; low = mid + 1;
} else { } else {
high = mid - 1; high = mid - 1;
@@ -92,5 +96,5 @@ export const useFrameDetectionMap = (data: DetectionData, detectionType: string)
: undefined; : undefined;
}; };
return { frameDetectionMap, getNearestDetections }; return { frameDetectionMap, getNearestDetections, sortedDetectionIndices };
}; };