forked from Github/frigate
Remove rtmp (#8941)
* remove rtmp from python * remove rtmp from nginx * remove rtmp from docs * fix test for missing role
This commit is contained in:
committed by
Blake Blackshear
parent
696434b36d
commit
d2d1278a4d
@@ -30,7 +30,6 @@ from frigate.ffmpeg_presets import (
|
||||
parse_preset_hardware_acceleration_scale,
|
||||
parse_preset_input,
|
||||
parse_preset_output_record,
|
||||
parse_preset_output_rtmp,
|
||||
)
|
||||
from frigate.plus import PlusApi
|
||||
from frigate.util.builtin import (
|
||||
@@ -582,7 +581,6 @@ DETECT_FFMPEG_OUTPUT_ARGS_DEFAULT = [
|
||||
"-pix_fmt",
|
||||
"yuv420p",
|
||||
]
|
||||
RTMP_FFMPEG_OUTPUT_ARGS_DEFAULT = "preset-rtmp-generic"
|
||||
RECORD_FFMPEG_OUTPUT_ARGS_DEFAULT = "preset-record-generic"
|
||||
|
||||
|
||||
@@ -595,10 +593,6 @@ class FfmpegOutputArgsConfig(FrigateBaseModel):
|
||||
default=RECORD_FFMPEG_OUTPUT_ARGS_DEFAULT,
|
||||
title="Record role FFmpeg output arguments.",
|
||||
)
|
||||
rtmp: Union[str, List[str]] = Field(
|
||||
default=RTMP_FFMPEG_OUTPUT_ARGS_DEFAULT,
|
||||
title="RTMP role FFmpeg output arguments.",
|
||||
)
|
||||
|
||||
|
||||
class FfmpegConfig(FrigateBaseModel):
|
||||
@@ -624,7 +618,6 @@ class FfmpegConfig(FrigateBaseModel):
|
||||
class CameraRoleEnum(str, Enum):
|
||||
audio = "audio"
|
||||
record = "record"
|
||||
rtmp = "rtmp"
|
||||
detect = "detect"
|
||||
|
||||
|
||||
@@ -733,10 +726,6 @@ class CameraMqttConfig(FrigateBaseModel):
|
||||
)
|
||||
|
||||
|
||||
class RtmpConfig(FrigateBaseModel):
|
||||
enabled: bool = Field(default=False, title="RTMP restreaming enabled.")
|
||||
|
||||
|
||||
class CameraLiveConfig(FrigateBaseModel):
|
||||
stream_name: str = Field(default="", title="Name of restream to use as live view.")
|
||||
height: int = Field(default=720, title="Live camera view height")
|
||||
@@ -772,9 +761,6 @@ class CameraConfig(FrigateBaseModel):
|
||||
record: RecordConfig = Field(
|
||||
default_factory=RecordConfig, title="Record configuration."
|
||||
)
|
||||
rtmp: RtmpConfig = Field(
|
||||
default_factory=RtmpConfig, title="RTMP restreaming configuration."
|
||||
)
|
||||
live: CameraLiveConfig = Field(
|
||||
default_factory=CameraLiveConfig, title="Live playback settings."
|
||||
)
|
||||
@@ -819,7 +805,6 @@ class CameraConfig(FrigateBaseModel):
|
||||
|
||||
# add roles to the input if there is only one
|
||||
if len(config["ffmpeg"]["inputs"]) == 1:
|
||||
has_rtmp = "rtmp" in config["ffmpeg"]["inputs"][0].get("roles", [])
|
||||
has_audio = "audio" in config["ffmpeg"]["inputs"][0].get("roles", [])
|
||||
|
||||
config["ffmpeg"]["inputs"][0]["roles"] = [
|
||||
@@ -830,9 +815,6 @@ class CameraConfig(FrigateBaseModel):
|
||||
if has_audio:
|
||||
config["ffmpeg"]["inputs"][0]["roles"].append("audio")
|
||||
|
||||
if has_rtmp:
|
||||
config["ffmpeg"]["inputs"][0]["roles"].append("rtmp")
|
||||
|
||||
super().__init__(**config)
|
||||
|
||||
@property
|
||||
@@ -872,15 +854,7 @@ class CameraConfig(FrigateBaseModel):
|
||||
)
|
||||
|
||||
ffmpeg_output_args = scale_detect_args + ffmpeg_output_args + ["pipe:"]
|
||||
if "rtmp" in ffmpeg_input.roles and self.rtmp.enabled:
|
||||
rtmp_args = get_ffmpeg_arg_list(
|
||||
parse_preset_output_rtmp(self.ffmpeg.output_args.rtmp)
|
||||
or self.ffmpeg.output_args.rtmp
|
||||
)
|
||||
|
||||
ffmpeg_output_args = (
|
||||
rtmp_args + [f"rtmp://127.0.0.1/live/{self.name}"] + ffmpeg_output_args
|
||||
)
|
||||
if "record" in ffmpeg_input.roles and self.record.enabled:
|
||||
record_args = get_ffmpeg_arg_list(
|
||||
parse_preset_output_record(self.ffmpeg.output_args.record)
|
||||
@@ -967,11 +941,6 @@ def verify_config_roles(camera_config: CameraConfig) -> None:
|
||||
f"Camera {camera_config.name} has record enabled, but record is not assigned to an input."
|
||||
)
|
||||
|
||||
if camera_config.rtmp.enabled and "rtmp" not in assigned_roles:
|
||||
raise ValueError(
|
||||
f"Camera {camera_config.name} has rtmp enabled, but rtmp is not assigned to an input."
|
||||
)
|
||||
|
||||
if camera_config.audio.enabled and "audio" not in assigned_roles:
|
||||
raise ValueError(
|
||||
f"Camera {camera_config.name} has audio events enabled, but audio is not assigned to an input."
|
||||
@@ -1082,9 +1051,6 @@ class FrigateConfig(FrigateBaseModel):
|
||||
snapshots: SnapshotsConfig = Field(
|
||||
default_factory=SnapshotsConfig, title="Global snapshots configuration."
|
||||
)
|
||||
rtmp: RtmpConfig = Field(
|
||||
default_factory=RtmpConfig, title="Global RTMP restreaming configuration."
|
||||
)
|
||||
live: CameraLiveConfig = Field(
|
||||
default_factory=CameraLiveConfig, title="Live playback settings."
|
||||
)
|
||||
@@ -1138,7 +1104,6 @@ class FrigateConfig(FrigateBaseModel):
|
||||
"birdseye": ...,
|
||||
"record": ...,
|
||||
"snapshots": ...,
|
||||
"rtmp": ...,
|
||||
"live": ...,
|
||||
"objects": ...,
|
||||
"motion": ...,
|
||||
@@ -1272,11 +1237,6 @@ class FrigateConfig(FrigateBaseModel):
|
||||
verify_zone_objects_are_tracked(camera_config)
|
||||
verify_autotrack_zones(camera_config)
|
||||
|
||||
if camera_config.rtmp.enabled:
|
||||
logger.warning(
|
||||
"RTMP restream is deprecated in favor of the restream role, recommend disabling RTMP."
|
||||
)
|
||||
|
||||
# generate the ffmpeg commands
|
||||
camera_config.create_ffmpeg_cmds()
|
||||
config.cameras[name] = camera_config
|
||||
|
||||
@@ -446,28 +446,3 @@ def parse_preset_output_record(arg: Any) -> list[str]:
|
||||
return None
|
||||
|
||||
return PRESETS_RECORD_OUTPUT.get(arg, None)
|
||||
|
||||
|
||||
PRESETS_RTMP_OUTPUT = {
|
||||
"preset-rtmp-generic": ["-c", "copy", "-f", "flv"],
|
||||
"preset-rtmp-mjpeg": ["-c:v", "libx264", "-an", "-f", "flv"],
|
||||
"preset-rtmp-jpeg": ["-c:v", "libx264", "-an", "-f", "flv"],
|
||||
"preset-rtmp-ubiquiti": [
|
||||
"-c:v",
|
||||
"copy",
|
||||
"-f",
|
||||
"flv",
|
||||
"-ar",
|
||||
"44100",
|
||||
"-c:a",
|
||||
"aac",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def parse_preset_output_rtmp(arg: Any) -> list[str]:
|
||||
"""Return the correct preset if in preset format otherwise return None."""
|
||||
if not isinstance(arg, str):
|
||||
return None
|
||||
|
||||
return PRESETS_RTMP_OUTPUT.get(arg, None)
|
||||
|
||||
@@ -653,7 +653,7 @@ class TestConfig(unittest.TestCase):
|
||||
"inputs": [
|
||||
{
|
||||
"path": "rtsp://10.0.0.1:554/video",
|
||||
"roles": ["detect", "rtmp"],
|
||||
"roles": ["detect"],
|
||||
},
|
||||
{"path": "rtsp://10.0.0.1:554/record", "roles": ["record"]},
|
||||
]
|
||||
@@ -930,7 +930,7 @@ class TestConfig(unittest.TestCase):
|
||||
"width": 1920,
|
||||
"fps": 5,
|
||||
},
|
||||
"rtmp": {"enabled": True},
|
||||
"audio": {"enabled": True},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1167,122 +1167,6 @@ class TestConfig(unittest.TestCase):
|
||||
assert runtime_config.cameras["back"].snapshots.height == 150
|
||||
assert runtime_config.cameras["back"].snapshots.enabled
|
||||
|
||||
def test_global_rtmp_disabled(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.dict(exclude_unset=True)
|
||||
|
||||
runtime_config = frigate_config.runtime_config()
|
||||
assert not runtime_config.cameras["back"].rtmp.enabled
|
||||
|
||||
def test_default_not_rtmp(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.dict(exclude_unset=True)
|
||||
|
||||
runtime_config = frigate_config.runtime_config()
|
||||
assert not runtime_config.cameras["back"].rtmp.enabled
|
||||
|
||||
def test_global_rtmp_merge(self):
|
||||
config = {
|
||||
"mqtt": {"host": "mqtt"},
|
||||
"rtmp": {"enabled": False},
|
||||
"cameras": {
|
||||
"back": {
|
||||
"ffmpeg": {
|
||||
"inputs": [
|
||||
{
|
||||
"path": "rtsp://10.0.0.1:554/video",
|
||||
"roles": ["detect", "rtmp"],
|
||||
},
|
||||
]
|
||||
},
|
||||
"detect": {
|
||||
"height": 1080,
|
||||
"width": 1920,
|
||||
"fps": 5,
|
||||
},
|
||||
"rtmp": {
|
||||
"enabled": True,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
frigate_config = FrigateConfig(**config)
|
||||
assert config == frigate_config.dict(exclude_unset=True)
|
||||
|
||||
runtime_config = frigate_config.runtime_config()
|
||||
assert runtime_config.cameras["back"].rtmp.enabled
|
||||
|
||||
def test_global_rtmp_default(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,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
frigate_config = FrigateConfig(**config)
|
||||
assert config == frigate_config.dict(exclude_unset=True)
|
||||
|
||||
runtime_config = frigate_config.runtime_config()
|
||||
assert not runtime_config.cameras["back"].rtmp.enabled
|
||||
|
||||
def test_global_jsmpeg(self):
|
||||
config = {
|
||||
"mqtt": {"host": "mqtt"},
|
||||
@@ -1428,7 +1312,6 @@ class TestConfig(unittest.TestCase):
|
||||
def test_global_timestamp_style_merge(self):
|
||||
config = {
|
||||
"mqtt": {"host": "mqtt"},
|
||||
"rtmp": {"enabled": False},
|
||||
"timestamp_style": {"position": "br", "thickness": 2},
|
||||
"cameras": {
|
||||
"back": {
|
||||
|
||||
@@ -14,13 +14,12 @@ class TestFfmpegPresets(unittest.TestCase):
|
||||
"inputs": [
|
||||
{
|
||||
"path": "rtsp://10.0.0.1:554/video",
|
||||
"roles": ["detect", "rtmp"],
|
||||
"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",
|
||||
"rtmp": "-c copy -f flv",
|
||||
},
|
||||
},
|
||||
"detect": {
|
||||
@@ -31,9 +30,6 @@ class TestFfmpegPresets(unittest.TestCase):
|
||||
"record": {
|
||||
"enabled": True,
|
||||
},
|
||||
"rtmp": {
|
||||
"enabled": True,
|
||||
},
|
||||
"name": "back",
|
||||
}
|
||||
},
|
||||
@@ -157,29 +153,6 @@ class TestFfmpegPresets(unittest.TestCase):
|
||||
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
||||
)
|
||||
|
||||
def test_ffmpeg_output_rtmp_preset(self):
|
||||
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"][
|
||||
"rtmp"
|
||||
] = "preset-rtmp-jpeg"
|
||||
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
||||
frigate_config.cameras["back"].create_ffmpeg_cmds()
|
||||
assert "preset-rtmp-jpeg" not in (
|
||||
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
||||
)
|
||||
assert "-c:v libx264" in (
|
||||
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
||||
)
|
||||
|
||||
def test_ffmpeg_output_rtmp_not_preset(self):
|
||||
self.default_ffmpeg["cameras"]["back"]["ffmpeg"]["output_args"][
|
||||
"rtmp"
|
||||
] = "-some output"
|
||||
frigate_config = FrigateConfig(**self.default_ffmpeg)
|
||||
frigate_config.cameras["back"].create_ffmpeg_cmds()
|
||||
assert "-some output" in (
|
||||
" ".join(frigate_config.cameras["back"].ffmpeg_cmds[0]["cmd"])
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
|
||||
Reference in New Issue
Block a user