From fa5ec8d0193b104ca6d2e18d8128c06d0785614d Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Sat, 28 Aug 2021 08:51:29 -0500 Subject: [PATCH] cleanup global and camera detect config (fixes #1615) --- docs/docs/configuration/cameras.md | 6 +-- frigate/config.py | 23 ++++---- frigate/test/test_config.py | 85 ++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 12 deletions(-) diff --git a/docs/docs/configuration/cameras.md b/docs/docs/configuration/cameras.md index 7592a5560..b95c8caca 100644 --- a/docs/docs/configuration/cameras.md +++ b/docs/docs/configuration/cameras.md @@ -284,11 +284,11 @@ cameras: # Required: Camera level detect settings detect: - # Required: width of the frame for the input with the detect role + # Optional: width of the frame for the input with the detect role (default: shown below) width: 1280 - # Required: height of the frame for the input with the detect role + # Optional: height of the frame for the input with the detect role (default: shown below) height: 720 - # Required: desired fps for your camera for the input with the detect role + # Optional: desired fps for your camera for the input with the detect role (default: shown below) # NOTE: Recommended value of 5. Ideally, try and reduce your FPS on the camera. fps: 5 # Optional: enables detection for the camera (default: True) diff --git a/frigate/config.py b/frigate/config.py index 66035bcce..ae280b267 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -149,9 +149,11 @@ class RuntimeMotionConfig(MotionConfig): class DetectConfig(BaseModel): - height: int = Field(title="Height of the stream for the detect role.") - width: int = Field(title="Width of the stream for the detect role.") - fps: int = Field(title="Number of frames per second to process through detection.") + height: int = Field(default=720, title="Height of the stream for the detect role.") + width: int = Field(default=1280, title="Width of the stream for the detect role.") + fps: int = Field( + default=5, title="Number of frames per second to process through detection." + ) enabled: bool = Field(default=True, title="Detection Enabled.") max_disappeared: Optional[int] = Field( title="Maximum number of frames the object can dissapear before detection ends." @@ -466,7 +468,7 @@ class CameraConfig(BaseModel): default_factory=ObjectConfig, title="Object configuration." ) motion: Optional[MotionConfig] = Field(title="Motion detection configuration.") - detect: DetectConfig = Field(title="Object detection configuration.") + detect: Optional[DetectConfig] = Field(title="Object detection configuration.") timestamp_style: TimestampStyleConfig = Field( default_factory=TimestampStyleConfig, title="Timestamp style configuration." ) @@ -701,6 +703,14 @@ class FrigateConfig(BaseModel): {"name": name, **merged_config} ) + # Default detect configuration + if camera_config.detect is None: + camera_config.detect = DetectConfig() + + max_disappeared = camera_config.detect.fps * 5 + if camera_config.detect.max_disappeared is None: + camera_config.detect.max_disappeared = max_disappeared + # FFMPEG input substitution for input in camera_config.ffmpeg.inputs: input.path = input.path.format(**FRIGATE_ENV_VARS) @@ -748,11 +758,6 @@ class FrigateConfig(BaseModel): **camera_config.motion.dict(exclude_unset=True), ) - # Default detect configuration - max_disappeared = camera_config.detect.fps * 5 - if camera_config.detect.max_disappeared is None: - camera_config.detect.max_disappeared = max_disappeared - # Default live configuration if camera_config.live is None: camera_config.live = CameraLiveConfig() diff --git a/frigate/test/test_config.py b/frigate/test/test_config.py index 20cab822e..9e71e3d27 100644 --- a/frigate/test/test_config.py +++ b/frigate/test/test_config.py @@ -717,6 +717,91 @@ class TestConfig(unittest.TestCase): self.assertRaises(ValidationError, lambda: FrigateConfig(**config)) + def test_global_detect(self): + + config = { + "mqtt": {"host": "mqtt"}, + "detect": {"max_disappeared": 1}, + "cameras": { + "back": { + "ffmpeg": { + "inputs": [ + { + "path": "rtsp://10.0.0.1:554/video", + "roles": ["detect"], + }, + ] + }, + "detect": { + "height": 1080, + "width": 1920, + "fps": 5, + }, + } + }, + } + frigate_config = FrigateConfig(**config) + assert config == frigate_config.dict(exclude_unset=True) + + runtime_config = frigate_config.runtime_config + assert runtime_config.cameras["back"].detect.max_disappeared == 1 + assert runtime_config.cameras["back"].detect.height == 1080 + + def test_default_detect(self): + + config = { + "mqtt": {"host": "mqtt"}, + "cameras": { + "back": { + "ffmpeg": { + "inputs": [ + { + "path": "rtsp://10.0.0.1:554/video", + "roles": ["detect"], + }, + ] + } + } + }, + } + frigate_config = FrigateConfig(**config) + assert config == frigate_config.dict(exclude_unset=True) + + runtime_config = frigate_config.runtime_config + assert runtime_config.cameras["back"].detect.max_disappeared == 25 + assert runtime_config.cameras["back"].detect.height == 720 + + def test_global_detect_merge(self): + + config = { + "mqtt": {"host": "mqtt"}, + "detect": {"max_disappeared": 1, "height": 720}, + "cameras": { + "back": { + "ffmpeg": { + "inputs": [ + { + "path": "rtsp://10.0.0.1:554/video", + "roles": ["detect"], + }, + ] + }, + "detect": { + "height": 1080, + "width": 1920, + "fps": 5, + }, + } + }, + } + frigate_config = FrigateConfig(**config) + assert config == frigate_config.dict(exclude_unset=True) + + runtime_config = frigate_config.runtime_config + assert runtime_config.cameras["back"].detect.max_disappeared == 1 + assert runtime_config.cameras["back"].detect.height == 1080 + assert runtime_config.cameras["back"].detect.width == 1920 + if __name__ == "__main__": unittest.main(verbosity=2)