chore: video section issues
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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 };
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user