forked from Github/frigate
Motion review playback optimizations (#10659)
* handle motion timestamps with ranges * check for overlaps when checking segment for events * rename motion color vars to significant_motion for consistency * safelist significant_motion * rename vars for clarity and use timeout instead of interval
This commit is contained in:
@@ -4,8 +4,6 @@ import {
|
||||
useMotionActivity,
|
||||
} from "@/api/ws";
|
||||
import { CameraConfig } from "@/types/frigateConfig";
|
||||
import { MotionData, ReviewSegment } from "@/types/review";
|
||||
import { TimeRange } from "@/types/timeline";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
|
||||
type useCameraActivityReturn = {
|
||||
@@ -68,57 +66,3 @@ export function useCameraActivity(
|
||||
: false,
|
||||
};
|
||||
}
|
||||
|
||||
export function useCameraMotionTimestamps(
|
||||
timeRange: TimeRange,
|
||||
motionOnly: boolean,
|
||||
events: ReviewSegment[],
|
||||
motion: MotionData[],
|
||||
) {
|
||||
const timestamps = useMemo(() => {
|
||||
const seekableTimestamps = [];
|
||||
let lastEventIdx = 0;
|
||||
let lastMotionIdx = 0;
|
||||
|
||||
for (let i = timeRange.after; i <= timeRange.before; i += 0.5) {
|
||||
if (!motionOnly) {
|
||||
seekableTimestamps.push(i);
|
||||
} else {
|
||||
const relevantEventIdx = events.findIndex((seg, segIdx) => {
|
||||
if (segIdx < lastEventIdx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return seg.start_time <= i && seg.end_time >= i;
|
||||
});
|
||||
|
||||
if (relevantEventIdx != -1) {
|
||||
lastEventIdx = relevantEventIdx;
|
||||
continue;
|
||||
}
|
||||
|
||||
const relevantMotionIdx = motion.findIndex((mot, motIdx) => {
|
||||
if (motIdx < lastMotionIdx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mot.start_time <= i && mot.start_time + 15 >= i;
|
||||
});
|
||||
|
||||
if (relevantMotionIdx == -1 || motion[relevantMotionIdx].motion == 0) {
|
||||
if (relevantMotionIdx != -1) {
|
||||
lastMotionIdx = relevantMotionIdx;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
seekableTimestamps.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
return seekableTimestamps;
|
||||
}, [timeRange, motionOnly, events, motion]);
|
||||
|
||||
return timestamps;
|
||||
}
|
||||
|
||||
@@ -368,27 +368,10 @@ function useDraggableElement({
|
||||
|
||||
const alignedSegmentTime = alignStartDateToTimeline(draggableElementTime);
|
||||
|
||||
let segmentElement = timelineRef.current.querySelector(
|
||||
const segmentElement = timelineRef.current.querySelector(
|
||||
`[data-segment-id="${alignedSegmentTime}"]`,
|
||||
);
|
||||
|
||||
if (!segmentElement) {
|
||||
// segment not found, maybe we collapsed over a collapsible segment
|
||||
let searchTime = alignedSegmentTime;
|
||||
while (searchTime >= timelineStartAligned - timelineDuration) {
|
||||
// Decrement currentTime by segmentDuration
|
||||
searchTime -= segmentDuration;
|
||||
segmentElement = timelineRef.current.querySelector(
|
||||
`[data-segment-id="${searchTime}"]`,
|
||||
);
|
||||
|
||||
if (segmentElement) {
|
||||
// segmentElement found
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (segmentElement) {
|
||||
const timelineRect = timelineRef.current.getBoundingClientRect();
|
||||
const timelineTopAbsolute = timelineRect.top;
|
||||
@@ -422,6 +405,37 @@ function useDraggableElement({
|
||||
segments,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (timelineRef.current && draggableElementTime && timelineCollapsed) {
|
||||
const alignedSegmentTime = alignStartDateToTimeline(draggableElementTime);
|
||||
|
||||
let segmentElement = timelineRef.current.querySelector(
|
||||
`[data-segment-id="${alignedSegmentTime}"]`,
|
||||
);
|
||||
|
||||
if (!segmentElement) {
|
||||
// segment not found, maybe we collapsed over a collapsible segment
|
||||
let searchTime = alignedSegmentTime;
|
||||
while (searchTime >= timelineStartAligned - timelineDuration) {
|
||||
searchTime -= segmentDuration;
|
||||
segmentElement = timelineRef.current.querySelector(
|
||||
`[data-segment-id="${searchTime}"]`,
|
||||
);
|
||||
|
||||
if (segmentElement) {
|
||||
// found, set time
|
||||
if (setDraggableElementTime) {
|
||||
setDraggableElementTime(searchTime);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// we know that these deps are correct
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [timelineCollapsed]);
|
||||
|
||||
return { handleMouseDown, handleMouseUp, handleMouseMove };
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export const useMotionSegmentUtils = (
|
||||
|
||||
const interpolateMotionAudioData = useCallback(
|
||||
(value: number, newMax: number): number => {
|
||||
return Math.ceil((Math.abs(value) / 100.0) * newMax) || 1;
|
||||
return Math.ceil((Math.abs(value) / 100.0) * newMax) || 0;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user