diff --git a/web/src/api/ws.tsx b/web/src/api/ws.tsx index 0cef235a0..8ebc01727 100644 --- a/web/src/api/ws.tsx +++ b/web/src/api/ws.tsx @@ -10,6 +10,7 @@ import { ToggleableSetting, TrackedObjectUpdateReturnType, TriggerStatus, + FrigateAudioDetections, } from "@/types/ws"; import { FrigateStats } from "@/types/stats"; import { createContainer } from "react-tracked"; @@ -341,6 +342,13 @@ export function useFrigateEvents(): { payload: FrigateEvent } { return { payload: JSON.parse(payload as string) }; } +export function useAudioDetections(): { payload: FrigateAudioDetections } { + const { + value: { payload }, + } = useWs("audio_detections", ""); + return { payload: JSON.parse(payload as string) }; +} + export function useFrigateReviews(): FrigateReview { const { value: { payload }, diff --git a/web/src/hooks/use-camera-activity.ts b/web/src/hooks/use-camera-activity.ts index baec4e228..328811a9d 100644 --- a/web/src/hooks/use-camera-activity.ts +++ b/web/src/hooks/use-camera-activity.ts @@ -1,4 +1,5 @@ import { + useAudioDetections, useEnabledState, useFrigateEvents, useInitialCameraState, @@ -8,7 +9,7 @@ import { CameraConfig, FrigateConfig } from "@/types/frigateConfig"; import { MotionData, ReviewSegment } from "@/types/review"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useTimelineUtils } from "./use-timeline-utils"; -import { ObjectType } from "@/types/ws"; +import { AudioDetection, ObjectType } from "@/types/ws"; import useDeepMemo from "./use-deep-memo"; import { isEqual } from "lodash"; import { useAutoFrigateStats } from "./use-stats"; @@ -20,6 +21,7 @@ type useCameraActivityReturn = { activeTracking: boolean; activeMotion: boolean; objects: ObjectType[]; + audio_detections: AudioDetection[]; offline: boolean; }; @@ -38,6 +40,9 @@ export function useCameraActivity( return getAttributeLabels(config); }, [config]); const [objects, setObjects] = useState([]); + const [audioDetections, setAudioDetections] = useState< + AudioDetection[] | undefined + >([]); // init camera activity @@ -51,6 +56,15 @@ export function useCameraActivity( } }, [updatedCameraState, camera]); + const { payload: updatedAudioState } = useAudioDetections(); + const memoizedAudioState = useDeepMemo(updatedAudioState); + + useEffect(() => { + if (memoizedAudioState) { + setAudioDetections(memoizedAudioState[camera.name]); + } + }, [memoizedAudioState, camera]); + // handle camera activity const hasActiveObjects = useMemo( @@ -160,6 +174,7 @@ export function useCameraActivity( : updatedCameraState?.motion === true : false, objects: isCameraEnabled ? (objects ?? []) : [], + audio_detections: isCameraEnabled ? (audioDetections ?? []) : [], offline, }; } diff --git a/web/src/types/ws.ts b/web/src/types/ws.ts index f2e45bda4..3a464a275 100644 --- a/web/src/types/ws.ts +++ b/web/src/types/ws.ts @@ -51,6 +51,12 @@ export type ObjectType = { sub_label: string; }; +export type AudioDetection = { + id: string; + label: string; + score: number; +}; + export interface FrigateCameraState { config: { enabled: boolean; @@ -69,6 +75,10 @@ export interface FrigateCameraState { }; motion: boolean; objects: ObjectType[]; + audio_detections: AudioDetection[]; +} +export interface FrigateAudioDetections { + [camera: string]: AudioDetection[]; } export type ModelState =