blakeblackshear.frigate/frigate/test/test_config.py

1651 lines
56 KiB
Python
Raw Normal View History

import json
import os
2021-06-24 07:45:27 +02:00
import unittest
from unittest.mock import patch
2021-06-24 07:45:27 +02:00
import numpy as np
from pydantic import ValidationError
from frigate.config import BirdseyeModeEnum, FrigateConfig
from frigate.const import MODEL_CACHE_DIR
from frigate.detectors import DetectorTypeEnum
from frigate.plus import PlusApi
from frigate.util.builtin import deep_merge, load_config_with_no_duplicates
2020-11-01 13:17:44 +01:00
2021-02-17 14:23:32 +01:00
2021-06-24 07:45:27 +02:00
class TestConfig(unittest.TestCase):
2020-11-03 15:15:58 +01:00
def setUp(self):
self.minimal = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2020-11-29 22:55:53 +01:00
]
2020-11-03 15:15:58 +01:00
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2020-11-03 15:15:58 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-11-03 15:15:58 +01:00
}
2021-02-17 14:23:32 +01:00
self.plus_model_info = {
"id": "e63b7345cc83a84ed79dedfc99c16616",
"name": "SSDLite Mobiledet",
"description": "Fine tuned model",
"trainDate": "2023-04-28T23:22:01.262Z",
"type": "ssd",
"supportedDetectors": ["edgetpu"],
"width": 320,
"height": 320,
"inputShape": "nhwc",
"pixelFormat": "rgb",
"labelMap": {
"0": "amazon",
"1": "car",
"2": "cat",
"3": "deer",
"4": "dog",
"5": "face",
"6": "fedex",
"7": "license_plate",
"8": "package",
"9": "person",
"10": "ups",
},
}
if not os.path.exists(MODEL_CACHE_DIR) and not os.path.islink(MODEL_CACHE_DIR):
os.makedirs(MODEL_CACHE_DIR)
2021-06-24 07:45:27 +02:00
def test_config_class(self):
frigate_config = FrigateConfig(**self.minimal)
assert self.minimal == frigate_config.model_dump(exclude_unset=True)
2020-11-01 13:17:44 +01:00
runtime_config = frigate_config.runtime_config()
2021-08-28 15:16:25 +02:00
assert "cpu" in runtime_config.detectors.keys()
assert runtime_config.detectors["cpu"].type == DetectorTypeEnum.cpu
assert runtime_config.detectors["cpu"].model.width == 320
@patch("frigate.detectors.detector_config.load_labels")
def test_detector_custom_model_path(self, mock_labels):
mock_labels.return_value = {}
config = {
"detectors": {
"cpu": {
"type": "cpu",
"model": {"path": "/cpu_model.tflite"},
},
"edgetpu": {
"type": "edgetpu",
"model": {"path": "/edgetpu_model.tflite"},
},
"openvino": {
"type": "openvino",
},
},
# needs to be a file that will exist, doesnt matter what
"model": {"path": "/etc/hosts", "width": 512},
}
frigate_config = FrigateConfig(**(deep_merge(config, self.minimal)))
runtime_config = frigate_config.runtime_config()
assert "cpu" in runtime_config.detectors.keys()
assert "edgetpu" in runtime_config.detectors.keys()
assert "openvino" in runtime_config.detectors.keys()
assert runtime_config.detectors["cpu"].type == DetectorTypeEnum.cpu
assert runtime_config.detectors["edgetpu"].type == DetectorTypeEnum.edgetpu
assert runtime_config.detectors["openvino"].type == DetectorTypeEnum.openvino
assert runtime_config.detectors["cpu"].num_threads == 3
assert runtime_config.detectors["edgetpu"].device is None
assert runtime_config.detectors["openvino"].device is None
assert runtime_config.model.path == "/etc/hosts"
assert runtime_config.detectors["cpu"].model.path == "/cpu_model.tflite"
assert runtime_config.detectors["edgetpu"].model.path == "/edgetpu_model.tflite"
assert runtime_config.detectors["openvino"].model.path == "/etc/hosts"
2021-06-24 07:45:27 +02:00
def test_invalid_mqtt_config(self):
config = {
"mqtt": {"host": "mqtt", "user": "test"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-06-24 07:45:27 +02:00
}
},
}
self.assertRaises(ValidationError, lambda: FrigateConfig(**config))
2021-02-17 14:23:32 +01:00
2020-11-03 15:15:58 +01:00
def test_inherit_tracked_objects(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"objects": {"track": ["person", "dog"]},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2020-11-29 22:55:53 +01:00
]
2020-11-03 15:15:58 +01:00
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2020-11-03 15:15:58 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-11-03 15:15:58 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
assert "dog" in runtime_config.cameras["back"].objects.track
2021-02-17 14:23:32 +01:00
def test_override_birdseye(self):
config = {
"mqtt": {"host": "mqtt"},
2022-04-16 15:44:04 +02:00
"birdseye": {"enabled": True, "mode": "continuous"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2022-04-16 15:44:04 +02:00
"birdseye": {"enabled": False, "mode": "motion"},
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert not runtime_config.cameras["back"].birdseye.enabled
assert runtime_config.cameras["back"].birdseye.mode is BirdseyeModeEnum.motion
2022-04-16 15:44:04 +02:00
def test_override_birdseye_non_inheritable(self):
config = {
"mqtt": {"host": "mqtt"},
"birdseye": {"enabled": True, "mode": "continuous", "height": 1920},
"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.model_dump(exclude_unset=True)
2022-04-16 15:44:04 +02:00
runtime_config = frigate_config.runtime_config()
2022-04-16 15:44:04 +02:00
assert runtime_config.cameras["back"].birdseye.enabled
def test_inherit_birdseye(self):
config = {
"mqtt": {"host": "mqtt"},
2022-04-16 15:44:04 +02:00
"birdseye": {"enabled": True, "mode": "continuous"},
"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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].birdseye.enabled
2022-04-16 15:44:04 +02:00
assert (
runtime_config.cameras["back"].birdseye.mode is BirdseyeModeEnum.continuous
)
2020-11-03 15:15:58 +01:00
def test_override_tracked_objects(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"objects": {"track": ["person", "dog"]},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2020-11-29 22:55:53 +01:00
]
2020-11-03 15:15:58 +01:00
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-02-17 14:23:32 +01:00
"objects": {"track": ["cat"]},
2020-11-03 15:15:58 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-11-03 15:15:58 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
assert "cat" in runtime_config.cameras["back"].objects.track
2021-02-17 14:23:32 +01:00
2020-11-03 15:15:58 +01:00
def test_default_object_filters(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"objects": {"track": ["person", "dog"]},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2020-11-29 22:55:53 +01:00
]
2020-11-03 15:15:58 +01:00
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2020-11-03 15:15:58 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-11-03 15:15:58 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
assert "dog" in runtime_config.cameras["back"].objects.filters
2021-02-17 14:23:32 +01:00
2020-11-03 15:15:58 +01:00
def test_inherit_object_filters(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"objects": {
"track": ["person", "dog"],
"filters": {"dog": {"threshold": 0.7}},
2020-11-03 15:15:58 +01:00
},
2021-02-17 14:23:32 +01:00
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2020-11-29 22:55:53 +01:00
]
2020-11-03 15:15:58 +01:00
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2020-11-03 15:15:58 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-11-03 15:15:58 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
assert "dog" in runtime_config.cameras["back"].objects.filters
assert runtime_config.cameras["back"].objects.filters["dog"].threshold == 0.7
2021-02-17 14:23:32 +01:00
2020-11-03 15:15:58 +01:00
def test_override_object_filters(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2020-11-29 22:55:53 +01:00
]
2020-11-03 15:15:58 +01:00
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-02-17 14:23:32 +01:00
"objects": {
"track": ["person", "dog"],
"filters": {"dog": {"threshold": 0.7}},
},
2020-11-03 15:15:58 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-11-03 15:15:58 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
assert "dog" in runtime_config.cameras["back"].objects.filters
assert runtime_config.cameras["back"].objects.filters["dog"].threshold == 0.7
2021-02-17 14:23:32 +01:00
2021-02-06 13:30:26 +01:00
def test_global_object_mask(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"objects": {"track": ["person", "dog"]},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2021-02-06 13:30:26 +01:00
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-02-17 14:23:32 +01:00
"objects": {
"mask": "0,0,1,1,0,1",
"filters": {"dog": {"mask": "1,1,1,1,1,1"}},
},
2021-02-06 13:30:26 +01:00
}
2021-02-17 14:23:32 +01:00
},
2021-02-06 13:30:26 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
back_camera = runtime_config.cameras["back"]
assert "dog" in back_camera.objects.filters
assert len(back_camera.objects.filters["dog"].raw_mask) == 2
assert len(back_camera.objects.filters["person"].raw_mask) == 1
2021-02-17 14:23:32 +01:00
def test_motion_mask_relative_matches_explicit(self):
config = {
"mqtt": {"host": "mqtt"},
"record": {
"events": {"retain": {"default": 20, "objects": {"person": 30}}}
},
"cameras": {
"explicit": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 400,
"width": 800,
"fps": 5,
},
"motion": {
"mask": [
"0,0,200,100,600,300,800,400",
]
},
},
"relative": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 400,
"width": 800,
"fps": 5,
},
"motion": {
"mask": [
"0.0,0.0,0.25,0.25,0.75,0.75,1.0,1.0",
]
},
},
},
}
frigate_config = FrigateConfig(**config).runtime_config()
assert np.array_equal(
frigate_config.cameras["explicit"].motion.mask,
frigate_config.cameras["relative"].motion.mask,
)
2021-07-10 03:21:35 +02:00
def test_default_input_args(self):
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-07-10 03:21:35 +02:00
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-07-10 03:21:35 +02:00
runtime_config = frigate_config.runtime_config()
2021-07-10 03:21:35 +02:00
assert "-rtsp_transport" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
2021-02-05 14:22:33 +01:00
def test_ffmpeg_params_global(self):
2020-11-03 15:15:58 +01:00
config = {
"ffmpeg": {"input_args": "-re"},
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2020-11-29 22:55:53 +01:00
]
2020-11-03 15:15:58 +01:00
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-02-17 14:23:32 +01:00
"objects": {
"track": ["person", "dog"],
"filters": {"dog": {"threshold": 0.7}},
},
2020-11-01 13:17:44 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-11-01 13:17:44 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
assert "-re" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
2021-02-05 14:22:33 +01:00
def test_ffmpeg_params_camera(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"ffmpeg": {"input_args": ["test"]},
2021-02-17 14:23:32 +01:00
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2021-02-05 14:22:33 +01:00
],
2021-02-17 14:23:32 +01:00
"input_args": ["-re"],
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-02-17 14:23:32 +01:00
"objects": {
"track": ["person", "dog"],
"filters": {"dog": {"threshold": 0.7}},
2021-02-05 14:22:33 +01:00
},
}
2021-02-17 14:23:32 +01:00
},
2021-02-05 14:22:33 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
assert "-re" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
assert "test" not in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
2021-02-05 14:22:33 +01:00
def test_ffmpeg_params_input(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"ffmpeg": {"input_args": ["test2"]},
2021-02-17 14:23:32 +01:00
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
"input_args": "-re test",
2021-02-17 14:23:32 +01:00
}
],
"input_args": "test3",
2021-02-05 14:22:33 +01:00
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-02-17 14:23:32 +01:00
"objects": {
"track": ["person", "dog"],
"filters": {"dog": {"threshold": 0.7}},
},
2021-02-05 14:22:33 +01:00
}
2021-02-17 14:23:32 +01:00
},
2021-02-05 14:22:33 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
assert "-re" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
assert "test" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
assert "test2" not in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
assert "test3" not in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
2021-02-17 14:23:32 +01:00
2020-12-23 14:16:37 +01:00
def test_inherit_clips_retention(self):
2020-11-23 15:25:46 +01:00
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
2021-08-15 15:30:27 +02:00
"record": {
"events": {"retain": {"default": 20, "objects": {"person": 30}}}
},
2021-02-17 14:23:32 +01:00
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2020-11-29 22:55:53 +01:00
]
2020-11-23 15:25:46 +01:00
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2020-11-23 15:25:46 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-11-23 15:25:46 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-08-15 15:30:27 +02:00
assert (
runtime_config.cameras["back"].record.events.retain.objects["person"] == 30
)
2021-02-17 14:23:32 +01:00
2020-11-29 22:55:53 +01:00
def test_roles_listed_twice_throws_error(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
2021-08-15 15:30:27 +02:00
"record": {
"events": {"retain": {"default": 20, "objects": {"person": 30}}}
},
2021-02-17 14:23:32 +01:00
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]},
{"path": "rtsp://10.0.0.1:554/video2", "roles": ["detect"]},
2020-11-29 22:55:53 +01:00
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2020-11-29 22:55:53 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-11-29 22:55:53 +01:00
}
2021-06-24 07:45:27 +02:00
self.assertRaises(ValidationError, lambda: FrigateConfig(**config))
2021-02-17 14:23:32 +01:00
def test_zone_matching_camera_name_throws_error(self):
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
2021-08-15 15:30:27 +02:00
"record": {
"events": {"retain": {"default": 20, "objects": {"person": 30}}}
},
2021-02-17 14:23:32 +01:00
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-02-17 14:23:32 +01:00
"zones": {"back": {"coordinates": "1,1,1,1,1,1"}},
}
2021-02-17 14:23:32 +01:00
},
}
2021-06-24 07:45:27 +02:00
self.assertRaises(ValidationError, lambda: FrigateConfig(**config))
def test_zone_assigns_color_and_contour(self):
config = {
"mqtt": {"host": "mqtt"},
2021-08-15 15:30:27 +02:00
"record": {
"events": {"retain": {"default": 20, "objects": {"person": 30}}}
},
2021-06-24 07:45:27 +02:00
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-06-24 07:45:27 +02:00
"zones": {"test": {"coordinates": "1,1,1,1,1,1"}},
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
assert isinstance(
runtime_config.cameras["back"].zones["test"].contour, np.ndarray
)
assert runtime_config.cameras["back"].zones["test"].color != (0, 0, 0)
2021-02-17 14:23:32 +01:00
def test_zone_relative_matches_explicit(self):
config = {
"mqtt": {"host": "mqtt"},
"record": {
"events": {"retain": {"default": 20, "objects": {"person": 30}}}
},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 400,
"width": 800,
"fps": 5,
},
"zones": {
"explicit": {
"coordinates": "0,0,200,100,600,300,800,400",
},
"relative": {
"coordinates": "0.0,0.0,0.25,0.25,0.75,0.75,1.0,1.0",
},
},
}
},
}
frigate_config = FrigateConfig(**config).runtime_config()
assert np.array_equal(
frigate_config.cameras["back"].zones["explicit"].contour,
frigate_config.cameras["back"].zones["relative"].contour,
)
2020-12-23 14:16:37 +01:00
def test_clips_should_default_to_global_objects(self):
2020-12-04 13:59:03 +01:00
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
2021-08-15 15:30:27 +02:00
"record": {
"events": {"retain": {"default": 20, "objects": {"person": 30}}}
},
2021-02-17 14:23:32 +01:00
"objects": {"track": ["person", "dog"]},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
2020-12-04 13:59:03 +01:00
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
"record": {"events": {}},
2020-12-04 13:59:03 +01:00
}
2021-02-17 14:23:32 +01:00
},
2020-12-04 13:59:03 +01:00
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
back_camera = runtime_config.cameras["back"]
2021-08-15 15:30:27 +02:00
assert back_camera.record.events.objects is None
assert back_camera.record.events.retain.objects["person"] == 30
2021-02-17 14:23:32 +01:00
def test_role_assigned_but_not_enabled(self):
2021-06-24 07:45:27 +02:00
config = {
2021-02-17 14:23:32 +01:00
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
2021-02-17 14:23:32 +01:00
},
{"path": "rtsp://10.0.0.1:554/record", "roles": ["record"]},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
}
2021-02-17 14:23:32 +01:00
},
}
2021-06-24 07:45:27 +02:00
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-24 07:45:27 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-24 07:45:27 +02:00
ffmpeg_cmds = runtime_config.cameras["back"].ffmpeg_cmds
2021-02-17 14:23:32 +01:00
assert len(ffmpeg_cmds) == 1
assert "clips" not in ffmpeg_cmds[0]["roles"]
2021-06-26 20:18:06 +02:00
def test_max_disappeared_default(self):
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"enabled": True,
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-06-26 20:18:06 +02:00
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-06-26 20:18:06 +02:00
runtime_config = frigate_config.runtime_config()
2021-06-26 20:18:06 +02:00
assert runtime_config.cameras["back"].detect.max_disappeared == 5 * 5
2021-07-01 14:47:22 +02:00
def test_motion_frame_height_wont_go_below_120(self):
2021-07-01 14:33:53 +02:00
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-07-01 14:33:53 +02:00
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-07-01 14:33:53 +02:00
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].motion.frame_height == 100
2021-07-01 14:47:22 +02:00
def test_motion_contour_area_dynamic(self):
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-07-01 14:47:22 +02:00
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-07-01 14:47:22 +02:00
runtime_config = frigate_config.runtime_config()
assert round(runtime_config.cameras["back"].motion.contour_area) == 10
2021-07-01 14:33:53 +02:00
def test_merge_labelmap(self):
config = {
"mqtt": {"host": "mqtt"},
"model": {"labelmap": {7: "truck"}},
"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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.model.merged_labelmap[7] == "truck"
def test_default_labelmap_empty(self):
config = {
"mqtt": {"host": "mqtt"},
"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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.model.merged_labelmap[0] == "person"
def test_default_labelmap(self):
config = {
"mqtt": {"host": "mqtt"},
"model": {"width": 320, "height": 320},
"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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.model.merged_labelmap[0] == "person"
def test_plus_labelmap(self):
with open("/config/model_cache/test", "w") as f:
json.dump(self.plus_model_info, f)
with open("/config/model_cache/test.json", "w") as f:
json.dump(self.plus_model_info, f)
config = {
"mqtt": {"host": "mqtt"},
"model": {"path": "plus://test"},
"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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config(PlusApi())
assert runtime_config.model.merged_labelmap[0] == "amazon"
2021-08-28 15:16:25 +02:00
def test_fails_on_invalid_role(self):
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
{
"path": "rtsp://10.0.0.1:554/video2",
"roles": ["clips"],
2021-08-28 15:16:25 +02:00
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
}
},
}
self.assertRaises(ValidationError, lambda: FrigateConfig(**config))
def test_fails_on_missing_role(self):
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
{
"path": "rtsp://10.0.0.1:554/video2",
"roles": ["record"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
"audio": {"enabled": True},
}
},
}
frigate_config = FrigateConfig(**config)
self.assertRaises(ValueError, lambda: frigate_config.runtime_config())
2021-10-24 20:33:13 +02:00
def test_works_on_missing_role_multiple_cams(self):
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
{
"path": "rtsp://10.0.0.1:554/video2",
"roles": ["record"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
},
"cam2": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
{
"path": "rtsp://10.0.0.1:554/video2",
"roles": ["record"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
},
},
}
frigate_config = FrigateConfig(**config)
frigate_config.runtime_config()
2021-10-24 20:33:13 +02:00
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.model_dump(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"],
},
]
},
"detect": {
"height": 720,
"width": 1280,
"fps": 5,
},
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(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.model_dump(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
def test_global_snapshots(self):
config = {
"mqtt": {"host": "mqtt"},
"snapshots": {"enabled": True},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
"snapshots": {
"height": 100,
},
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].snapshots.enabled
assert runtime_config.cameras["back"].snapshots.height == 100
def test_default_snapshots(self):
config = {
"mqtt": {"host": "mqtt"},
"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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].snapshots.bounding_box
assert runtime_config.cameras["back"].snapshots.quality == 70
def test_global_snapshots_merge(self):
config = {
"mqtt": {"host": "mqtt"},
"snapshots": {"bounding_box": False, "height": 300},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
"snapshots": {
"height": 150,
"enabled": True,
},
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].snapshots.bounding_box is False
assert runtime_config.cameras["back"].snapshots.height == 150
assert runtime_config.cameras["back"].snapshots.enabled
Add go2rtc and add restream role / live source (#4082) * Pull go2rtc dependency * Add go2rtc to local services and add to s6 * Add relay controller for go2rtc * Add restream role * Add restream role * Add restream to nginx * Add camera live source config * Disable RTMP by default and use restream * Use go2rtc for camera config * Fix go2rtc move * Start restream on frigate start * Send restream to camera level * Fix restream * Make sure jsmpeg works as expected * Make view rspect live size config * Tweak player options to fit live view * Adjust VideoPlayer to accept live option which disables irrelevant controls * Add multiple options from restream live view * Add base for webrtc option * Setup specific restream modules * Make mp4 the default streaming for now * Expose 8554 for rtsp relay from go2rtc * Formatting * Update docs to suggest new restream method. * Update docs to reflect restream role * Update docs to reflect restream role * Add webrtc player * Improvements to webRTC * Support webrtc * Cleanup * Adjust rtmp test and add restream test * Fix tests * Add restream tests * Add live view docs and show different options * Small docs tweak * Support all stream types * Update to beta 9 of go2rtc * Formatting * Make jsmpeg the default * Support wss if made from https * Support wss if made from https * Use onEffect * Set url outside onEffect * Fix passed deps * Update docs about required host mode * Try memo instead * Close websocket on changing camera * Formatting * Close pc connection * Set video source to null on cleanup * Use full path since go2rtc can't see PATH var * Adjust audio codec to enable browser audio by default * Cleanup stream creation * Add restream tests * Format tests * Mock requests * Adjust paths * Move stream configs to restream * Remove live source * Remove live config * Use live persistence for which view to use on each camera * Fix live sizes * Only use jsmpeg sizes for jsmpeg live * Set max live size * Remove access of live config * Add selector for live view source in web view * Remove RTMP from default list of roles * Update docs * Fix tests * Fix docs for live view modes * make default undefined to avoid race condition * Wait until camera source is loaded to avoid race condition * Fix tests * Add config to go2rtc * Work with config * Set full path for config * Set to use stun * Check for mounted file * Look for frigate-go2rtc * Update docs to reflect webRTC configuration. * Add link to go2rtc config * Update docs to be more clear * Update docs to be more clear * Update format Co-authored-by: Felipe Santos <felipecassiors@gmail.com> * Update live docs * Improve bash startup script * Add option to force audio compatibility * Formatting * Fix mapping * Fix broken link * Update go2rtc version * Get go2rtc webui working * Add support for mse * Remove mp4 option * Undo changes to video player * Update docs for new live view options * Make separate path for mse * Remove unused * Remove mp4 path * Try to get go2rtc proxy working * Try to get go2rtc proxy working * Remove unused callback * Allow websocket on restrea dashboard * Make mse default stream option * Fix mse sizing * don't assume roles is defined * Remove nginx mapping to go2rtc ui Co-authored-by: Felipe Santos <felipecassiors@gmail.com> Co-authored-by: Blake Blackshear <blakeb@blakeshome.com>
2022-11-02 12:36:09 +01:00
def test_global_jsmpeg(self):
2021-09-14 03:33:00 +02:00
config = {
"mqtt": {"host": "mqtt"},
"live": {"quality": 4},
2021-09-14 03:33:00 +02:00
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-09-14 03:33:00 +02:00
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-09-14 03:33:00 +02:00
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].live.quality == 4
2021-09-14 03:33:00 +02:00
def test_default_live(self):
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-09-14 03:33:00 +02:00
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-09-14 03:33:00 +02:00
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].live.quality == 8
2021-09-14 03:33:00 +02:00
def test_global_live_merge(self):
config = {
"mqtt": {"host": "mqtt"},
"live": {"quality": 4, "height": 480},
2021-09-14 03:33:00 +02:00
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
"live": {
"quality": 7,
2021-09-14 03:33:00 +02:00
},
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
2021-09-14 03:33:00 +02:00
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].live.quality == 7
assert runtime_config.cameras["back"].live.height == 480
2021-09-14 03:33:00 +02:00
def test_global_timestamp_style(self):
config = {
"mqtt": {"host": "mqtt"},
2021-09-04 23:56:01 +02:00
"timestamp_style": {"position": "bl"},
"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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].timestamp_style.position == "bl"
def test_default_timestamp_style(self):
config = {
"mqtt": {"host": "mqtt"},
"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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].timestamp_style.position == "tl"
def test_global_timestamp_style_merge(self):
config = {
"mqtt": {"host": "mqtt"},
2021-09-04 23:56:01 +02:00
"timestamp_style": {"position": "br", "thickness": 2},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2021-09-04 23:56:01 +02:00
"timestamp_style": {"position": "bl", "thickness": 4},
}
},
}
frigate_config = FrigateConfig(**config)
assert config == frigate_config.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].timestamp_style.position == "bl"
2021-09-04 23:56:01 +02:00
assert runtime_config.cameras["back"].timestamp_style.thickness == 4
def test_allow_retain_to_be_a_decimal(self):
config = {
"mqtt": {"host": "mqtt"},
"snapshots": {"retain": {"default": 1.5}},
"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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].snapshots.retain.default == 1.5
2022-02-02 14:21:03 +01:00
def test_fails_on_bad_camera_name(self):
config = {
"mqtt": {"host": "mqtt"},
"snapshots": {"retain": {"default": 1.5}},
"cameras": {
"back camer#": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
2022-02-02 14:21:03 +01:00
}
},
}
frigate_config = FrigateConfig(**config)
self.assertRaises(
ValidationError, lambda: frigate_config.runtime_config().cameras
2022-02-02 14:21:03 +01:00
)
def test_fails_on_bad_segment_time(self):
config = {
"mqtt": {"host": "mqtt"},
"record": {"enabled": True},
"cameras": {
"back": {
"ffmpeg": {
"output_args": {
"record": "-f segment -segment_time 70 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c copy -an"
},
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
],
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
}
},
}
frigate_config = FrigateConfig(**config)
self.assertRaises(
ValueError,
lambda: frigate_config.runtime_config().ffmpeg.output_args.record,
)
def test_fails_zone_defines_untracked_object(self):
config = {
"mqtt": {"host": "mqtt"},
"objects": {"track": ["person"]},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{
"path": "rtsp://10.0.0.1:554/video",
"roles": ["detect"],
},
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
"zones": {
"steps": {
"coordinates": "0,0,0,0",
"objects": ["car", "person"],
},
},
}
},
}
frigate_config = FrigateConfig(**config)
self.assertRaises(ValueError, lambda: frigate_config.runtime_config().cameras)
def test_fails_duplicate_keys(self):
raw_config = """
cameras:
test:
ffmpeg:
inputs:
- one
- two
inputs:
- three
- four
"""
self.assertRaises(
ValueError, lambda: load_config_with_no_duplicates(raw_config)
)
def test_object_filter_ratios_work(self):
config = {
"mqtt": {"host": "mqtt"},
"objects": {
"track": ["person", "dog"],
"filters": {"dog": {"min_ratio": 0.2, "max_ratio": 10.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.model_dump(exclude_unset=True)
runtime_config = frigate_config.runtime_config()
assert "dog" in runtime_config.cameras["back"].objects.filters
assert runtime_config.cameras["back"].objects.filters["dog"].min_ratio == 0.2
assert runtime_config.cameras["back"].objects.filters["dog"].max_ratio == 10.1
def test_valid_movement_weights(self):
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
Autotracking bugfixes and zooming updates (#8103) * zoom in/out in search for lost objects * predicted box should not be empty * clean up and update zoom logic * only zoom if enabled * more cleanup * check for valid velocity when zooming * only try absolute zoom in if obj area has changed * zoom logic * don't enqueue lost object zoom if already at limit * don't disable motion boxes during ptz moves * velocity threshold based on move coefficients * fix area zoom logic * disable debug zoom * don't process objects if ptz moving * recalc with exponent * change exponent * remove lost object zooming * increase distance threshold for stationary object * increase distance threshold constant * only zoom out if nonzero * camera name in all debug logging * add camera name to debug logging * camera variable name consistency * update calibration behavior and docs * docs and better zooming * more sensible target values * docs wording * fix velocity threshold variable * zooming tweaks and remove iou for current objects * debug and docs * get valid velocity * include zero * additional debug statements * add zoom hysteresis * zoom on initial move if relative * only update target box if we actually zoom * merge dev * use getattr instead of get * increase distance threshold * reverse logic * get_camera_status after preset move to store zoom * final tweaks and docs * use constants and catch possible debug exception * adjust zoom factor exponent * don't run motion estimation when calling preset * adjust dimension threshold * use numpy for velocity estimate calcs * more numpy conversion * fix numpy shapes * numpy zeros dimension * more zoom out conditions * fix velocity bug * ensure init has been called in debug view * ensure onvif init if enabling by mqtt * change default hysteresis values * recalc relative zoom value * zoom out value * try to zoom when object isn't moving * try zoom when tracked object is not moving * don't try to zoom every time * negate zoom out condition when needed * hysteresis constants for absolute zooming * update zoom conditions * don't recalc target box on zoom only * zoom out if above area threshold * don't print zooming debug for stationary obj * revamp zooming to use area moving average * zooming tweaks and expose property * limit zoom with max target box * use calibration to determine zoom levels * zoom logic fix * docs * add tapo c200 camera * fix initial absolute zoom * small zoom logic fix * better invalid velocity checks * fix test * really fix test this time
2023-10-22 18:59:13 +02:00
"onvif": {
"autotracking": {"movement_weights": "0, 1, 1.23, 2.34, 0.50"}
},
}
},
}
frigate_config = FrigateConfig(**config)
runtime_config = frigate_config.runtime_config()
assert runtime_config.cameras["back"].onvif.autotracking.movement_weights == [
"0.0",
"1.0",
"1.23",
"2.34",
"0.5",
]
def test_fails_invalid_movement_weights(self):
config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"back": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {
"height": 1080,
"width": 1920,
"fps": 5,
},
"onvif": {"autotracking": {"movement_weights": "1.234, 2.345a"}},
}
},
}
self.assertRaises(ValueError, lambda: FrigateConfig(**config))
2020-11-01 13:17:44 +01:00
2021-02-17 14:23:32 +01:00
if __name__ == "__main__":
2021-06-24 07:45:27 +02:00
unittest.main(verbosity=2)