mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-28 19:06:52 +03:00
* Run ONNX models on a Mac's Neural Engine through lighter's plugin provider lighter's lighter.sh/ane device places an ONNX Runtime plugin execution provider in the container. When it is present, the ONNX session setup registers it once and opens sessions on its Neural Engine device, the same place CUDA, ROCm and OpenVINO are chosen, so the onnx detector (and any model that is not pinned to the CPU) runs there with no configuration. The hardware probe reports it as an onnx unit. * docs: hardware decode on an Apple Silicon Mac under lighter A community section on the video decoding page: lighter's lighter.sh/video device, hwaccel_args -c:v h264_v4l2m2m, and why the Raspberry Pi presets decode a single-stream camera in software. The detector docs link to it. * docs: set the lighter decoder per camera when codecs are mixed * docs: the ONNX detector on a Mac's Neural Engine under lighter * Format the Neural Engine provider setup * Fall back to the default providers when the Neural Engine cannot load a model * Apple Silicon ffmpeg presets for lighter's media engine, recommended when it is present
157 lines
6.1 KiB
Python
157 lines
6.1 KiB
Python
import unittest
|
|
|
|
from frigate.config import FrigateConfig
|
|
from frigate.config.camera.ffmpeg import FFMPEG_INPUT_ARGS_DEFAULT
|
|
from frigate.ffmpeg_presets import parse_preset_input
|
|
|
|
|
|
class TestFfmpegPresets(unittest.TestCase):
|
|
def setUp(self):
|
|
self.default_ffmpeg = {
|
|
"mqtt": {"host": "mqtt"},
|
|
"cameras": {
|
|
"back": {
|
|
"ffmpeg": {
|
|
"inputs": [
|
|
{
|
|
"path": "rtsp://10.0.0.1:554/video",
|
|
"roles": ["detect"],
|
|
}
|
|
],
|
|
"output_args": {
|
|
"detect": "-f rawvideo -pix_fmt yuv420p",
|
|
"record": "-f segment -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c copy -an",
|
|
},
|
|
},
|
|
"detect": {
|
|
"height": 1080,
|
|
"width": 1920,
|
|
"fps": 5,
|
|
},
|
|
"record": {
|
|
"enabled": True,
|
|
},
|
|
"name": "back",
|
|
}
|
|
},
|
|
}
|
|
|
|
def test_default_ffmpeg(self):
|
|
FrigateConfig(**self.default_ffmpeg)
|
|
|
|
def test_ffmpeg_hwaccel_preset(self):
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["hwaccel_args"] = (
|
|
"preset-rpi-64-h264"
|
|
)
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
assert "preset-rpi-64-h264" not in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
assert "-c:v:1 h264_v4l2m2m" in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
|
|
def test_ffmpeg_hwaccel_apple_preset_decodes_every_stream(self):
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["hwaccel_args"] = (
|
|
"preset-apple-silicon-h265"
|
|
)
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
cmd = " ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
assert "-c:v hevc_v4l2m2m" in cmd
|
|
assert "-c:v:1" not in cmd
|
|
assert "scale=1920:1080" in cmd
|
|
|
|
def test_ffmpeg_hwaccel_not_preset(self):
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["hwaccel_args"] = (
|
|
"-other-hwaccel args"
|
|
)
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
assert "-other-hwaccel args" in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
|
|
def test_ffmpeg_hwaccel_scale_preset(self):
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["hwaccel_args"] = (
|
|
"preset-nvidia-h264"
|
|
)
|
|
self.default_ffmpeg["cameras"]["back"]["detect"] = {
|
|
"height": 1920,
|
|
"width": 2560,
|
|
"fps": 10,
|
|
}
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
assert "preset-nvidia-h264" not in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
assert "fps=10,scale_cuda=w=2560:h=1920,hwdownload,format=nv12" in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
|
|
def test_default_ffmpeg_input_arg_preset(self):
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["input_args"] = (
|
|
"preset-rtsp-generic"
|
|
)
|
|
frigate_preset_config = FrigateConfig(**self.default_ffmpeg)
|
|
assert (
|
|
# Ignore global and user_agent args in comparison
|
|
frigate_preset_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
|
|
== frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
|
|
)
|
|
|
|
def test_ffmpeg_input_preset(self):
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["input_args"] = (
|
|
"preset-rtmp-generic"
|
|
)
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
assert "preset-rtmp-generic" not in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
assert (" ".join(parse_preset_input("preset-rtmp-generic", 5))) in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
|
|
def test_ffmpeg_input_args_as_string(self):
|
|
# Strip user_agent args here to avoid handling quoting issues
|
|
defaultArgsList = parse_preset_input(FFMPEG_INPUT_ARGS_DEFAULT, 5)[2::]
|
|
argsString = " ".join(defaultArgsList) + ' -some "arg with space"'
|
|
argsList = defaultArgsList + ["-some", "arg with space"]
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["input_args"] = argsString
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
assert set(argsList).issubset(
|
|
frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"]
|
|
)
|
|
|
|
def test_ffmpeg_input_not_preset(self):
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["input_args"] = "-some inputs"
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
assert "-some inputs" in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
|
|
def test_ffmpeg_output_record_preset(self):
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"]["record"] = (
|
|
"preset-record-generic-audio-aac"
|
|
)
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
assert "preset-record-generic-audio-aac" not in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
assert "-c:v copy -c:a aac" in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
|
|
def test_ffmpeg_output_record_not_preset(self):
|
|
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"]["record"] = (
|
|
"-some output -segment_time 10"
|
|
)
|
|
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
|
assert "-some output" in (
|
|
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main(verbosity=2)
|