forked from Github/frigate
Motion timeline data (#10245)
* Refactor activity api to send motion and audio data * Prepare for using motion data timeline * Get working * reduce to 0 * fix * Formatting * fix typing * add motion data to timelines and allow motion cameas to be selectable * Fix tests * cleanup * Fix not loading preview when changing hours
This commit is contained in:
@@ -240,22 +240,37 @@ export default function Events() {
|
||||
|
||||
// selected items
|
||||
|
||||
const selectedData = useMemo(() => {
|
||||
const selectedReviewData = useMemo(() => {
|
||||
if (!config) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!selectedReviewId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!reviewPages) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!selectedReviewId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const allCameras = reviewFilter?.cameras ?? Object.keys(config.cameras);
|
||||
|
||||
const allReviews = reviewPages.flat();
|
||||
|
||||
if (selectedReviewId.startsWith("motion")) {
|
||||
const motionData = selectedReviewId.split(",");
|
||||
// format is motion,camera,start_time
|
||||
return {
|
||||
camera: motionData[1],
|
||||
severity: "significant_motion" as ReviewSeverity,
|
||||
start_time: parseFloat(motionData[2]),
|
||||
allCameras: allCameras,
|
||||
cameraSegments: allReviews.filter((seg) =>
|
||||
allCameras.includes(seg.camera),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
const selectedReview = allReviews.find(
|
||||
(item) => item.id == selectedReviewId,
|
||||
);
|
||||
@@ -265,7 +280,9 @@ export default function Events() {
|
||||
}
|
||||
|
||||
return {
|
||||
selected: selectedReview,
|
||||
camera: selectedReview.camera,
|
||||
severity: selectedReview.severity,
|
||||
start_time: selectedReview.start_time,
|
||||
allCameras: allCameras,
|
||||
cameraSegments: allReviews.filter((seg) =>
|
||||
allCameras.includes(seg.camera),
|
||||
@@ -280,12 +297,14 @@ export default function Events() {
|
||||
return <ActivityIndicator />;
|
||||
}
|
||||
|
||||
if (selectedData) {
|
||||
if (selectedReviewData) {
|
||||
if (isMobile) {
|
||||
return (
|
||||
<MobileRecordingView
|
||||
reviewItems={selectedData.cameraSegments}
|
||||
selectedReview={selectedData.selected}
|
||||
reviewItems={selectedReviewData.cameraSegments}
|
||||
startCamera={selectedReviewData.camera}
|
||||
startTime={selectedReviewData.start_time}
|
||||
severity={selectedReviewData.severity}
|
||||
relevantPreviews={allPreviews}
|
||||
/>
|
||||
);
|
||||
@@ -293,11 +312,11 @@ export default function Events() {
|
||||
|
||||
return (
|
||||
<DesktopRecordingView
|
||||
startCamera={selectedData.selected.camera}
|
||||
startTime={selectedData.selected.start_time}
|
||||
allCameras={selectedData.allCameras}
|
||||
severity={selectedData.selected.severity}
|
||||
reviewItems={selectedData.cameraSegments}
|
||||
startCamera={selectedReviewData.camera}
|
||||
startTime={selectedReviewData.start_time}
|
||||
allCameras={selectedReviewData.allCameras}
|
||||
severity={selectedReviewData.severity}
|
||||
reviewItems={selectedReviewData.cameraSegments}
|
||||
allPreviews={allPreviews}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -4,7 +4,12 @@ import useSWR from "swr";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
import EventReviewTimeline from "@/components/timeline/EventReviewTimeline";
|
||||
import { ReviewData, ReviewSegment, ReviewSeverity } from "@/types/review";
|
||||
import {
|
||||
MotionData,
|
||||
ReviewData,
|
||||
ReviewSegment,
|
||||
ReviewSeverity,
|
||||
} from "@/types/review";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import CameraActivityIndicator from "@/components/indicators/CameraActivityIndicator";
|
||||
import MotionReviewTimeline from "@/components/timeline/MotionReviewTimeline";
|
||||
@@ -53,14 +58,7 @@ function ColorSwatch({ name, value }: { name: string; value: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
export type MockMotionData = {
|
||||
start_time: number;
|
||||
end_time: number;
|
||||
motionValue: number;
|
||||
audioValue: number;
|
||||
};
|
||||
|
||||
function generateRandomMotionAudioData(): MockMotionData[] {
|
||||
function generateRandomMotionAudioData(): MotionData[] {
|
||||
const now = new Date();
|
||||
const endTime = now.getTime() / 1000;
|
||||
const startTime = endTime - 24 * 60 * 60; // 24 hours ago
|
||||
@@ -72,14 +70,12 @@ function generateRandomMotionAudioData(): MockMotionData[] {
|
||||
startTimestamp < endTime;
|
||||
startTimestamp += interval
|
||||
) {
|
||||
const endTimestamp = startTimestamp + interval;
|
||||
const motionValue = Math.floor(Math.random() * 101); // Random number between 0 and 100
|
||||
const audioValue = Math.random() * -100; // Random negative value between -100 and 0
|
||||
const motion = Math.floor(Math.random() * 101); // Random number between 0 and 100
|
||||
const audio = Math.random() * -100; // Random negative value between -100 and 0
|
||||
data.push({
|
||||
start_time: startTimestamp,
|
||||
end_time: endTimestamp,
|
||||
motionValue,
|
||||
audioValue,
|
||||
motion,
|
||||
audio,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -126,7 +122,7 @@ function UIPlayground() {
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const [mockEvents, setMockEvents] = useState<ReviewSegment[]>([]);
|
||||
const [mockMotionData, setMockMotionData] = useState<MockMotionData[]>([]);
|
||||
const [mockMotionData, setMockMotionData] = useState<MotionData[]>([]);
|
||||
const [handlebarTime, setHandlebarTime] = useState(
|
||||
Math.floor(Date.now() / 1000) - 15 * 60,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user