mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-05 10:45:21 +03:00
Add audio icon in frontend
This commit is contained in:
parent
8444cc450d
commit
8198165fa7
@ -396,6 +396,9 @@ class AudioConfig(FrigateBaseModel):
|
|||||||
listen: List[str] = Field(
|
listen: List[str] = Field(
|
||||||
default=DEFAULT_LISTEN_AUDIO, title="Audio to listen for."
|
default=DEFAULT_LISTEN_AUDIO, title="Audio to listen for."
|
||||||
)
|
)
|
||||||
|
enabled_in_config: Optional[bool] = Field(
|
||||||
|
title="Keep track of original state of audio detection."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BirdseyeModeEnum(str, Enum):
|
class BirdseyeModeEnum(str, Enum):
|
||||||
@ -1004,8 +1007,9 @@ class FrigateConfig(FrigateBaseModel):
|
|||||||
camera_config.onvif.password = camera_config.onvif.password.format(
|
camera_config.onvif.password = camera_config.onvif.password.format(
|
||||||
**FRIGATE_ENV_VARS
|
**FRIGATE_ENV_VARS
|
||||||
)
|
)
|
||||||
# set config recording value
|
# set config pre-value
|
||||||
camera_config.record.enabled_in_config = camera_config.record.enabled
|
camera_config.record.enabled_in_config = camera_config.record.enabled
|
||||||
|
camera_config.audio.enabled_in_config = camera_config.audio.enabled
|
||||||
|
|
||||||
# Add default filters
|
# Add default filters
|
||||||
object_keys = camera_config.objects.track
|
object_keys = camera_config.objects.track
|
||||||
|
|||||||
@ -120,6 +120,15 @@ export function useSnapshotsState(camera) {
|
|||||||
return { payload, send, connected };
|
return { payload, send, connected };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useAudioState(camera) {
|
||||||
|
const {
|
||||||
|
value: { payload },
|
||||||
|
send,
|
||||||
|
connected,
|
||||||
|
} = useWs(`${camera}/audio/state`, `${camera}/audio/set`);
|
||||||
|
return { payload, send, connected };
|
||||||
|
}
|
||||||
|
|
||||||
export function usePtzCommand(camera) {
|
export function usePtzCommand(camera) {
|
||||||
const {
|
const {
|
||||||
value: { payload },
|
value: { payload },
|
||||||
|
|||||||
37
web/src/icons/Audio.jsx
Normal file
37
web/src/icons/Audio.jsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { h } from 'preact';
|
||||||
|
import { memo } from 'preact/compat';
|
||||||
|
|
||||||
|
export function Snapshot({ className = 'h-6 w-6', stroke = 'currentColor', onClick = () => {} }) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={className}
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke={stroke}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M18 30v-2a10.011 10.011 0 0010-10h2a12.013 12.013 0 01-12 12z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M18 22v-2a2.002 2.002 0 002-2h2a4.004 4.004 0 01-4 4zM10 2a9.01 9.01 0 00-9 9h2a7 7 0 0114 0 7.09 7.09 0 01-3.501 6.135l-.499.288v3.073a2.935 2.935 0 01-.9 2.151 4.182 4.182 0 01-4.633 1.03A4.092 4.092 0 015 20H3a6.116 6.116 0 003.67 5.512 5.782 5.782 0 002.314.486 6.585 6.585 0 004.478-1.888A4.94 4.94 0 0015 20.496v-1.942A9.108 9.108 0 0019 11a9.01 9.01 0 00-9-9z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M9.28 8.082A3.006 3.006 0 0113 11h2a4.979 4.979 0 00-1.884-3.911 5.041 5.041 0 00-4.281-.957 4.95 4.95 0 00-3.703 3.703 5.032 5.032 0 002.304 5.458A3.078 3.078 0 019 17.924V20h2v-2.077a5.06 5.06 0 00-2.537-4.346 3.002 3.002 0 01.817-5.494z"
|
||||||
|
/>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" fill="none" d="M0 0h32v32H0z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo(Snapshot);
|
||||||
@ -2,10 +2,11 @@ import { h, Fragment } from 'preact';
|
|||||||
import ActivityIndicator from '../components/ActivityIndicator';
|
import ActivityIndicator from '../components/ActivityIndicator';
|
||||||
import Card from '../components/Card';
|
import Card from '../components/Card';
|
||||||
import CameraImage from '../components/CameraImage';
|
import CameraImage from '../components/CameraImage';
|
||||||
|
import AudioIcon from '../icons/Audio';
|
||||||
import ClipIcon from '../icons/Clip';
|
import ClipIcon from '../icons/Clip';
|
||||||
import MotionIcon from '../icons/Motion';
|
import MotionIcon from '../icons/Motion';
|
||||||
import SnapshotIcon from '../icons/Snapshot';
|
import SnapshotIcon from '../icons/Snapshot';
|
||||||
import { useDetectState, useRecordingsState, useSnapshotsState } from '../api/ws';
|
import { useAudioState, useDetectState, useRecordingsState, useSnapshotsState } from '../api/ws';
|
||||||
import { useMemo } from 'preact/hooks';
|
import { useMemo } from 'preact/hooks';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
|
|
||||||
@ -43,6 +44,7 @@ function Camera({ name, config }) {
|
|||||||
const { payload: detectValue, send: sendDetect } = useDetectState(name);
|
const { payload: detectValue, send: sendDetect } = useDetectState(name);
|
||||||
const { payload: recordValue, send: sendRecordings } = useRecordingsState(name);
|
const { payload: recordValue, send: sendRecordings } = useRecordingsState(name);
|
||||||
const { payload: snapshotValue, send: sendSnapshots } = useSnapshotsState(name);
|
const { payload: snapshotValue, send: sendSnapshots } = useSnapshotsState(name);
|
||||||
|
const { payload: audioValue, send: sendAudio } = useAudioState(name);
|
||||||
const href = `/cameras/${name}`;
|
const href = `/cameras/${name}`;
|
||||||
const buttons = useMemo(() => {
|
const buttons = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
@ -50,10 +52,9 @@ function Camera({ name, config }) {
|
|||||||
{ name: 'Recordings', href: `/recording/${name}` },
|
{ name: 'Recordings', href: `/recording/${name}` },
|
||||||
];
|
];
|
||||||
}, [name]);
|
}, [name]);
|
||||||
const cleanName = useMemo(
|
const cleanName = useMemo(() => {
|
||||||
() => { return `${name.replaceAll('_', ' ')}` },
|
return `${name.replaceAll('_', ' ')}`;
|
||||||
[name]
|
}, [name]);
|
||||||
);
|
|
||||||
const icons = useMemo(
|
const icons = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@ -65,7 +66,9 @@ function Camera({ name, config }) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: config.record.enabled_in_config ? `Toggle recordings ${recordValue === 'ON' ? 'off' : 'on'}` : 'Recordings must be enabled in the config to be turned on in the UI.',
|
name: config.record.enabled_in_config
|
||||||
|
? `Toggle recordings ${recordValue === 'ON' ? 'off' : 'on'}`
|
||||||
|
: 'Recordings must be enabled in the config to be turned on in the UI.',
|
||||||
icon: ClipIcon,
|
icon: ClipIcon,
|
||||||
color: config.record.enabled_in_config ? (recordValue === 'ON' ? 'blue' : 'gray') : 'red',
|
color: config.record.enabled_in_config ? (recordValue === 'ON' ? 'blue' : 'gray') : 'red',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@ -82,11 +85,27 @@ function Camera({ name, config }) {
|
|||||||
sendSnapshots(snapshotValue === 'ON' ? 'OFF' : 'ON', true);
|
sendSnapshots(snapshotValue === 'ON' ? 'OFF' : 'ON', true);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
config.audio.enabled_in_config
|
||||||
|
? {
|
||||||
|
name: `Toggle audio detection ${audioValue === 'ON' ? 'off' : 'on'}`,
|
||||||
|
icon: AudioIcon,
|
||||||
|
color: audioValue === 'ON' ? 'blue' : 'gray',
|
||||||
|
onClick: () => {
|
||||||
|
sendAudio(audioValue === 'ON' ? 'OFF' : 'ON', true);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {},
|
||||||
],
|
],
|
||||||
[config, detectValue, sendDetect, recordValue, sendRecordings, snapshotValue, sendSnapshots]
|
[config, audioValue, sendAudio, detectValue, sendDetect, recordValue, sendRecordings, snapshotValue, sendSnapshots]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card buttons={buttons} href={href} header={cleanName} icons={icons} media={<CameraImage camera={name} stretch />} />
|
<Card
|
||||||
|
buttons={buttons}
|
||||||
|
href={href}
|
||||||
|
header={cleanName}
|
||||||
|
icons={icons}
|
||||||
|
media={<CameraImage camera={name} stretch />}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user