Allow cameras to be disabled in config (#4162)

* add option enabled for each camera in config

* Simplified If-block and removed wrong Optional

* Update Docs enabling/disabling camera in config

* correct format for option

* Disabling Camera for processes, no config changes

* Describe effects of disabled cam in documentation

* change if-logic, obsolete copy, info disabled cam

* changed color to white, added top padding in disabled camera info

* changed indentation
This commit is contained in:
banthungprong 2022-11-02 12:41:44 +01:00 committed by GitHub
parent 2a36a1b980
commit 8163afce79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 11 deletions

View File

@ -7,6 +7,8 @@ title: Cameras
Several inputs can be configured for each camera and the role of each input can be mixed and matched based on your needs. This allows you to use a lower resolution stream for object detection, but create recordings from a higher resolution stream, or vice versa. Several inputs can be configured for each camera and the role of each input can be mixed and matched based on your needs. This allows you to use a lower resolution stream for object detection, but create recordings from a higher resolution stream, or vice versa.
A camera is enabled by default but can be temporarily disabled by using `enabled: False`. Existing events and recordings can still be accessed. Live streams, recording and detecting are not working. Camera specific configurations will be used.
Each role can only be assigned to one input per camera. The options for roles are as follows: Each role can only be assigned to one input per camera. The options for roles are as follows:
| Role | Description | | Role | Description |
@ -21,6 +23,7 @@ mqtt:
host: mqtt.server.com host: mqtt.server.com
cameras: cameras:
back: back:
enabled: True
ffmpeg: ffmpeg:
inputs: inputs:
- path: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2 - path: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2

View File

@ -387,6 +387,10 @@ timestamp_style:
cameras: cameras:
# Required: name of the camera # Required: name of the camera
back: back:
# Optional: Enable/Disable the camera (default: shown below).
# If disabled: config is used but no live stream and no capture etc.
# Events/Recordings are still viewable.
enabled: True
# Required: ffmpeg settings for the camera # Required: ffmpeg settings for the camera
ffmpeg: ffmpeg:
# Required: A list of input streams for the camera. See documentation for more information. # Required: A list of input streams for the camera. See documentation for more information.

View File

@ -255,6 +255,10 @@ class FrigateApp:
def start_camera_processors(self) -> None: def start_camera_processors(self) -> None:
model_shape = (self.config.model.height, self.config.model.width) model_shape = (self.config.model.height, self.config.model.width)
for name, config in self.config.cameras.items(): for name, config in self.config.cameras.items():
if not self.config.cameras[name].enabled:
logger.info(f"Camera processor not started for disabled camera {name}")
continue
camera_process = mp.Process( camera_process = mp.Process(
target=track_camera, target=track_camera,
name=f"camera_processor:{name}", name=f"camera_processor:{name}",
@ -276,6 +280,10 @@ class FrigateApp:
def start_camera_capture_processes(self) -> None: def start_camera_capture_processes(self) -> None:
for name, config in self.config.cameras.items(): for name, config in self.config.cameras.items():
if not self.config.cameras[name].enabled:
logger.info(f"Capture process not started for disabled camera {name}")
continue
capture_process = mp.Process( capture_process = mp.Process(
target=capture_camera, target=capture_camera,
name=f"camera_capture:{name}", name=f"camera_capture:{name}",

View File

@ -541,6 +541,7 @@ class CameraUiConfig(FrigateBaseModel):
class CameraConfig(FrigateBaseModel): class CameraConfig(FrigateBaseModel):
name: Optional[str] = Field(title="Camera name.", regex="^[a-zA-Z0-9_-]+$") name: Optional[str] = Field(title="Camera name.", regex="^[a-zA-Z0-9_-]+$")
enabled: bool = Field(default=True, title="Enable camera.")
ffmpeg: CameraFfmpegConfig = Field(title="FFmpeg configuration for the camera.") ffmpeg: CameraFfmpegConfig = Field(title="FFmpeg configuration for the camera.")
best_image_timeout: int = Field( best_image_timeout: int = Field(
default=60, default=60,
@ -819,7 +820,7 @@ class FrigateConfig(FrigateBaseModel):
if config.mqtt.password: if config.mqtt.password:
config.mqtt.password = config.mqtt.password.format(**FRIGATE_ENV_VARS) config.mqtt.password = config.mqtt.password.format(**FRIGATE_ENV_VARS)
# Global config to propegate down to camera level # Global config to propagate down to camera level
global_config = config.dict( global_config = config.dict(
include={ include={
"birdseye": ..., "birdseye": ...,
@ -940,10 +941,9 @@ class FrigateConfig(FrigateBaseModel):
logger.warning( logger.warning(
f"{name}: Recording retention is configured for {camera_config.record.retain.mode} and event retention is configured for {camera_config.record.events.retain.mode}. The more restrictive retention policy will be applied." f"{name}: Recording retention is configured for {camera_config.record.retain.mode} and event retention is configured for {camera_config.record.events.retain.mode}. The more restrictive retention policy will be applied."
) )
# generage the ffmpeg commands # generate the ffmpeg commands
camera_config.create_ffmpeg_cmds() camera_config.create_ffmpeg_cmds()
config.cameras[name] = camera_config config.cameras[name] = camera_config
return config return config
@validator("cameras") @validator("cameras")

View File

@ -14,6 +14,7 @@ export default function CameraImage({ camera, onload, searchParams = '', stretch
const [{ width: availableWidth }] = useResizeObserver(containerRef); const [{ width: availableWidth }] = useResizeObserver(containerRef);
const { name } = config ? config.cameras[camera] : ''; const { name } = config ? config.cameras[camera] : '';
const enabled = config ? config.cameras[camera].enabled : 'True';
const { width, height } = config ? config.cameras[camera].detect : { width: 1, height: 1 }; const { width, height } = config ? config.cameras[camera].detect : { width: 1, height: 1 };
const aspectRatio = width / height; const aspectRatio = width / height;
@ -45,12 +46,18 @@ export default function CameraImage({ camera, onload, searchParams = '', stretch
return ( return (
<div className="relative w-full" ref={containerRef}> <div className="relative w-full" ref={containerRef}>
{
(enabled) ?
<canvas data-testid="cameraimage-canvas" height={scaledHeight} ref={canvasRef} width={scaledWidth} /> <canvas data-testid="cameraimage-canvas" height={scaledHeight} ref={canvasRef} width={scaledWidth} />
{!hasLoaded ? ( : <div class="text-center pt-6">Camera is disabled in config, no stream or snapshot available!</div>
}
{
(!hasLoaded && enabled) ? (
<div className="absolute inset-0 flex justify-center" style={`height: ${scaledHeight}px`}> <div className="absolute inset-0 flex justify-center" style={`height: ${scaledHeight}px`}>
<ActivityIndicator /> <ActivityIndicator />
</div> </div>
) : null} ) : null
</div> }
</div >
); );
} }