mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-05-03 12:07:40 +03:00
frontend live transcription
This commit is contained in:
parent
b9627cbff6
commit
53dc069c6d
@ -41,6 +41,11 @@ export interface CameraConfig {
|
|||||||
min_volume: number;
|
min_volume: number;
|
||||||
num_threads: number;
|
num_threads: number;
|
||||||
};
|
};
|
||||||
|
audio_transcription: {
|
||||||
|
enabled: boolean;
|
||||||
|
enabled_in_config: boolean;
|
||||||
|
live_enabled: boolean;
|
||||||
|
};
|
||||||
best_image_timeout: number;
|
best_image_timeout: number;
|
||||||
birdseye: {
|
birdseye: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@ -296,6 +301,10 @@ export interface FrigateConfig {
|
|||||||
num_threads: number;
|
num_threads: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
audio_transcription: {
|
||||||
|
enabled: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
birdseye: BirdseyeConfig;
|
birdseye: BirdseyeConfig;
|
||||||
|
|
||||||
cameras: {
|
cameras: {
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
useAudioState,
|
useAudioState,
|
||||||
|
useAudioTranscriptionState,
|
||||||
useAutotrackingState,
|
useAutotrackingState,
|
||||||
useDetectState,
|
useDetectState,
|
||||||
useEnabledState,
|
useEnabledState,
|
||||||
usePtzCommand,
|
usePtzCommand,
|
||||||
useRecordingsState,
|
useRecordingsState,
|
||||||
useSnapshotsState,
|
useSnapshotsState,
|
||||||
|
useTrackedObjectUpdate,
|
||||||
} from "@/api/ws";
|
} from "@/api/ws";
|
||||||
import CameraFeatureToggle from "@/components/dynamic/CameraFeatureToggle";
|
import CameraFeatureToggle from "@/components/dynamic/CameraFeatureToggle";
|
||||||
import FilterSwitch from "@/components/filter/FilterSwitch";
|
import FilterSwitch from "@/components/filter/FilterSwitch";
|
||||||
@ -90,6 +92,8 @@ import {
|
|||||||
LuX,
|
LuX,
|
||||||
} from "react-icons/lu";
|
} from "react-icons/lu";
|
||||||
import {
|
import {
|
||||||
|
MdClosedCaption,
|
||||||
|
MdClosedCaptionDisabled,
|
||||||
MdNoPhotography,
|
MdNoPhotography,
|
||||||
MdOutlineRestartAlt,
|
MdOutlineRestartAlt,
|
||||||
MdPersonOff,
|
MdPersonOff,
|
||||||
@ -196,6 +200,33 @@ export default function LiveCameraView({
|
|||||||
const { payload: enabledState } = useEnabledState(camera.name);
|
const { payload: enabledState } = useEnabledState(camera.name);
|
||||||
const cameraEnabled = enabledState === "ON";
|
const cameraEnabled = enabledState === "ON";
|
||||||
|
|
||||||
|
// for audio transcriptions
|
||||||
|
|
||||||
|
const { payload: audioTranscriptionState, send: sendTranscription } =
|
||||||
|
useAudioTranscriptionState(camera.name);
|
||||||
|
const { payload: wsUpdate } = useTrackedObjectUpdate();
|
||||||
|
const transcriptionRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
wsUpdate &&
|
||||||
|
wsUpdate.type == "transcription" &&
|
||||||
|
wsUpdate.camera == camera.name
|
||||||
|
) {
|
||||||
|
if (transcriptionRef.current) {
|
||||||
|
transcriptionRef.current.scrollTop =
|
||||||
|
transcriptionRef.current.scrollHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [wsUpdate, camera.name]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
// disable transcriptions when unmounting
|
||||||
|
if (audioTranscriptionState == "ON") sendTranscription("OFF");
|
||||||
|
};
|
||||||
|
}, [audioTranscriptionState, sendTranscription]);
|
||||||
|
|
||||||
// click overlay for ptzs
|
// click overlay for ptzs
|
||||||
|
|
||||||
const [clickOverlay, setClickOverlay] = useState(false);
|
const [clickOverlay, setClickOverlay] = useState(false);
|
||||||
@ -566,6 +597,9 @@ export default function LiveCameraView({
|
|||||||
autotrackingEnabled={
|
autotrackingEnabled={
|
||||||
camera.onvif.autotracking.enabled_in_config
|
camera.onvif.autotracking.enabled_in_config
|
||||||
}
|
}
|
||||||
|
transcriptionEnabled={
|
||||||
|
camera.audio_transcription.enabled_in_config
|
||||||
|
}
|
||||||
fullscreen={fullscreen}
|
fullscreen={fullscreen}
|
||||||
streamName={streamName ?? ""}
|
streamName={streamName ?? ""}
|
||||||
setStreamName={setStreamName}
|
setStreamName={setStreamName}
|
||||||
@ -625,6 +659,19 @@ export default function LiveCameraView({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</TransformComponent>
|
</TransformComponent>
|
||||||
|
{camera?.audio?.enabled_in_config &&
|
||||||
|
audioTranscriptionState == "ON" &&
|
||||||
|
wsUpdate &&
|
||||||
|
wsUpdate.type === "transcription" &&
|
||||||
|
wsUpdate.camera === camera.name &&
|
||||||
|
wsUpdate.text !== "" && (
|
||||||
|
<div
|
||||||
|
ref={transcriptionRef}
|
||||||
|
className="text-md scrollbar-container absolute bottom-4 left-1/2 max-h-[15vh] w-[75%] -translate-x-1/2 overflow-y-auto rounded-lg bg-black/70 p-2 text-white md:w-[50%]"
|
||||||
|
>
|
||||||
|
{wsUpdate.text}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{camera.onvif.host != "" && (
|
{camera.onvif.host != "" && (
|
||||||
@ -983,6 +1030,7 @@ type FrigateCameraFeaturesProps = {
|
|||||||
recordingEnabled: boolean;
|
recordingEnabled: boolean;
|
||||||
audioDetectEnabled: boolean;
|
audioDetectEnabled: boolean;
|
||||||
autotrackingEnabled: boolean;
|
autotrackingEnabled: boolean;
|
||||||
|
transcriptionEnabled: boolean;
|
||||||
fullscreen: boolean;
|
fullscreen: boolean;
|
||||||
streamName: string;
|
streamName: string;
|
||||||
setStreamName?: (value: string | undefined) => void;
|
setStreamName?: (value: string | undefined) => void;
|
||||||
@ -1002,6 +1050,7 @@ function FrigateCameraFeatures({
|
|||||||
recordingEnabled,
|
recordingEnabled,
|
||||||
audioDetectEnabled,
|
audioDetectEnabled,
|
||||||
autotrackingEnabled,
|
autotrackingEnabled,
|
||||||
|
transcriptionEnabled,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
streamName,
|
streamName,
|
||||||
setStreamName,
|
setStreamName,
|
||||||
@ -1033,6 +1082,8 @@ function FrigateCameraFeatures({
|
|||||||
const { payload: audioState, send: sendAudio } = useAudioState(camera.name);
|
const { payload: audioState, send: sendAudio } = useAudioState(camera.name);
|
||||||
const { payload: autotrackingState, send: sendAutotracking } =
|
const { payload: autotrackingState, send: sendAutotracking } =
|
||||||
useAutotrackingState(camera.name);
|
useAutotrackingState(camera.name);
|
||||||
|
const { payload: transcriptionState, send: sendTranscription } =
|
||||||
|
useAudioTranscriptionState(camera.name);
|
||||||
|
|
||||||
// roles
|
// roles
|
||||||
|
|
||||||
@ -1196,6 +1247,27 @@ function FrigateCameraFeatures({
|
|||||||
disabled={!cameraEnabled}
|
disabled={!cameraEnabled}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{audioDetectEnabled && transcriptionEnabled && (
|
||||||
|
<CameraFeatureToggle
|
||||||
|
className="p-2 md:p-0"
|
||||||
|
variant={fullscreen ? "overlay" : "primary"}
|
||||||
|
Icon={
|
||||||
|
transcriptionState == "ON"
|
||||||
|
? MdClosedCaption
|
||||||
|
: MdClosedCaptionDisabled
|
||||||
|
}
|
||||||
|
isActive={transcriptionState == "ON"}
|
||||||
|
title={
|
||||||
|
transcriptionState == "ON"
|
||||||
|
? t("transcription.disable")
|
||||||
|
: t("transcription.enable")
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
sendTranscription(transcriptionState == "ON" ? "OFF" : "ON")
|
||||||
|
}
|
||||||
|
disabled={!cameraEnabled || audioState == "OFF"}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{autotrackingEnabled && (
|
{autotrackingEnabled && (
|
||||||
<CameraFeatureToggle
|
<CameraFeatureToggle
|
||||||
className="p-2 md:p-0"
|
className="p-2 md:p-0"
|
||||||
@ -1558,6 +1630,16 @@ function FrigateCameraFeatures({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{audioDetectEnabled && transcriptionEnabled && (
|
||||||
|
<FilterSwitch
|
||||||
|
label={t("cameraSettings.transcription")}
|
||||||
|
disabled={audioState == "OFF"}
|
||||||
|
isChecked={transcriptionState == "ON"}
|
||||||
|
onCheckedChange={() =>
|
||||||
|
sendTranscription(transcriptionState == "ON" ? "OFF" : "ON")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{autotrackingEnabled && (
|
{autotrackingEnabled && (
|
||||||
<FilterSwitch
|
<FilterSwitch
|
||||||
label={t("cameraSettings.autotracking")}
|
label={t("cameraSettings.autotracking")}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user