From d2d1278a4d179c8cd474cd06b1eafcaf01225df1 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Tue, 12 Dec 2023 16:20:25 -0700 Subject: [PATCH] Remove rtmp (#8941) * remove rtmp from python * remove rtmp from nginx * remove rtmp from docs * fix test for missing role --- docker/main/build_nginx.sh | 6 - .../rootfs/usr/local/nginx/conf/nginx.conf | 15 --- docs/docs/configuration/camera_specific.md | 7 +- docs/docs/configuration/cameras.md | 2 - docs/docs/configuration/reference.md | 14 +- docs/docs/configuration/restream.md | 4 - docs/docs/guides/configuring_go2rtc.md | 2 +- docs/docs/integrations/home-assistant.md | 4 - frigate/config.py | 40 ------ frigate/ffmpeg_presets.py | 25 ---- frigate/test/test_config.py | 121 +----------------- frigate/test/test_ffmpeg_presets.py | 29 +---- process_clip.py | 1 - 13 files changed, 7 insertions(+), 263 deletions(-) diff --git a/docker/main/build_nginx.sh b/docker/main/build_nginx.sh index fd604c122..849754d97 100755 --- a/docker/main/build_nginx.sh +++ b/docker/main/build_nginx.sh @@ -5,7 +5,6 @@ set -euxo pipefail NGINX_VERSION="1.25.3" VOD_MODULE_VERSION="1.31" SECURE_TOKEN_MODULE_VERSION="1.5" -RTMP_MODULE_VERSION="1.2.2" cp /etc/apt/sources.list /etc/apt/sources.list.d/sources-src.list sed -i 's|deb http|deb-src http|g' /etc/apt/sources.list.d/sources-src.list @@ -49,10 +48,6 @@ mkdir /tmp/nginx-secure-token-module wget https://github.com/kaltura/nginx-secure-token-module/archive/refs/tags/${SECURE_TOKEN_MODULE_VERSION}.tar.gz tar -zxf ${SECURE_TOKEN_MODULE_VERSION}.tar.gz -C /tmp/nginx-secure-token-module --strip-components=1 rm ${SECURE_TOKEN_MODULE_VERSION}.tar.gz -mkdir /tmp/nginx-rtmp-module -wget -nv https://github.com/arut/nginx-rtmp-module/archive/refs/tags/v${RTMP_MODULE_VERSION}.tar.gz -tar -zxf v${RTMP_MODULE_VERSION}.tar.gz -C /tmp/nginx-rtmp-module --strip-components=1 -rm v${RTMP_MODULE_VERSION}.tar.gz cd /tmp/nginx @@ -63,7 +58,6 @@ cd /tmp/nginx --with-threads \ --add-module=../nginx-vod-module \ --add-module=../nginx-secure-token-module \ - --add-module=../nginx-rtmp-module \ --with-cc-opt="-O3 -Wno-error=implicit-fallthrough" make CC="ccache gcc" -j$(nproc) && make install diff --git a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf index 46706a92f..24c294725 100644 --- a/docker/main/rootfs/usr/local/nginx/conf/nginx.conf +++ b/docker/main/rootfs/usr/local/nginx/conf/nginx.conf @@ -275,18 +275,3 @@ http { } } } - -rtmp { - server { - listen 1935; - chunk_size 4096; - allow publish 127.0.0.1; - deny publish all; - allow play all; - application live { - live on; - record off; - meta copy; - } - } -} diff --git a/docs/docs/configuration/camera_specific.md b/docs/docs/configuration/camera_specific.md index 96299c7c4..57aca0385 100644 --- a/docs/docs/configuration/camera_specific.md +++ b/docs/docs/configuration/camera_specific.md @@ -69,16 +69,12 @@ cameras: ffmpeg: output_args: record: -f segment -segment_time 10 -segment_format mp4 -reset_timestamps 1 -strftime 1 -c:v copy -tag:v hvc1 -bsf:v hevc_mp4toannexb -c:a aac - rtmp: -c:v copy -c:a aac -f flv inputs: - path: rtsp://user:password@camera-ip:554/H264/ch1/main/av_stream # <----- Update for your camera roles: - detect - record - - rtmp - rtmp: - enabled: False # <-- RTMP should be disabled if your stream is not H264 detect: width: # <- optional, by default Frigate tries to automatically detect resolution height: # <- optional, by default Frigate tries to automatically detect resolution @@ -181,13 +177,12 @@ go2rtc: [See the go2rtc docs for more information](https://github.com/AlexxIT/go2rtc/tree/v1.8.4#source-rtsp) -In the Unifi 2.0 update Unifi Protect Cameras had a change in audio sample rate which causes issues for ffmpeg. The input rate needs to be set for record and rtmp if used directly with unifi protect. +In the Unifi 2.0 update Unifi Protect Cameras had a change in audio sample rate which causes issues for ffmpeg. The input rate needs to be set for record if used directly with unifi protect. ```yaml ffmpeg: output_args: record: preset-record-ubiquiti - rtmp: preset-rtmp-ubiquiti # recommend using go2rtc instead ``` ### TP-Link VIGI Cameras diff --git a/docs/docs/configuration/cameras.md b/docs/docs/configuration/cameras.md index a95ffae86..19f773528 100644 --- a/docs/docs/configuration/cameras.md +++ b/docs/docs/configuration/cameras.md @@ -16,7 +16,6 @@ Each role can only be assigned to one input per camera. The options for roles ar | `detect` | Main feed for object detection. [docs](object_detectors.md) | | `record` | Saves segments of the video feed based on configuration settings. [docs](record.md) | | `audio` | Feed for audio based detection. [docs](audio_detectors.md) | -| `rtmp` | Deprecated: Broadcast as an RTMP feed for other services to consume. [docs](restream.md) | ```yaml mqtt: @@ -29,7 +28,6 @@ cameras: - path: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2 roles: - detect - - rtmp # <- deprecated, recommend using restream instead - path: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/live roles: - record diff --git a/docs/docs/configuration/reference.md b/docs/docs/configuration/reference.md index cb10b7bcb..584560ea5 100644 --- a/docs/docs/configuration/reference.md +++ b/docs/docs/configuration/reference.md @@ -162,8 +162,6 @@ ffmpeg: detect: -threads 2 -f rawvideo -pix_fmt yuv420p # Optional: output args for record streams (default: shown below) record: preset-record-generic - # Optional: output args for rtmp streams (default: shown below) - rtmp: preset-rtmp-generic # Optional: Time in seconds to wait before ffmpeg retries connecting to the camera. (default: shown below) # If set too low, frigate will retry a connection to the camera's stream too frequently, using up the limited streams some cameras can allow at once # If set too high, then if a ffmpeg crash or camera stream timeout occurs, you could potentially lose up to a maximum of retry_interval second(s) of footage @@ -386,13 +384,6 @@ snapshots: # Optional: quality of the encoded jpeg, 0-100 (default: shown below) quality: 70 -# Optional: RTMP configuration -# NOTE: RTMP is deprecated in favor of restream -# NOTE: Can be overridden at the camera level -rtmp: - # Optional: Enable the RTMP stream (default: False) - enabled: False - # Optional: Restream configuration # Uses https://github.com/AlexxIT/go2rtc (v1.8.3) go2rtc: @@ -449,14 +440,13 @@ cameras: # Required: the path to the stream # NOTE: path may include environment variables or docker secrets, which must begin with 'FRIGATE_' and be referenced in {} - path: rtsp://viewer:{FRIGATE_RTSP_PASSWORD}@10.0.10.10:554/cam/realmonitor?channel=1&subtype=2 - # Required: list of roles for this stream. valid values are: audio,detect,record,rtmp - # NOTICE: In addition to assigning the audio, record, and rtmp roles, + # Required: list of roles for this stream. valid values are: audio,detect,record + # NOTICE: In addition to assigning the audio, detect, and record roles # they must also be enabled in the camera config. roles: - audio - detect - record - - rtmp # Optional: stream specific global args (default: inherit) # global_args: # Optional: stream specific hwaccel args (default: inherit) diff --git a/docs/docs/configuration/restream.md b/docs/docs/configuration/restream.md index 74baf365e..d31c0ec00 100644 --- a/docs/docs/configuration/restream.md +++ b/docs/docs/configuration/restream.md @@ -38,10 +38,6 @@ go2rtc: **NOTE:** This does not apply to localhost requests, there is no need to provide credentials when using the restream as a source for frigate cameras. -## RTMP (Deprecated) - -In previous Frigate versions RTMP was used for re-streaming. RTMP has disadvantages however including being incompatible with H.265, high bitrates, and certain audio codecs. RTMP is deprecated and it is recommended use the built in go2rtc config for restreaming. - ## Reduce Connections To Camera Some cameras only support one active connection or you may just want to have a single connection open to the camera. The RTSP restream allows this to be possible. diff --git a/docs/docs/guides/configuring_go2rtc.md b/docs/docs/guides/configuring_go2rtc.md index 1279f9950..7847a4b81 100644 --- a/docs/docs/guides/configuring_go2rtc.md +++ b/docs/docs/guides/configuring_go2rtc.md @@ -9,7 +9,7 @@ Use of the bundled go2rtc is optional. You can still configure FFmpeg to connect - WebRTC or MSE for live viewing with higher resolutions and frame rates than the jsmpeg stream which is limited to the detect stream - Live stream support for cameras in Home Assistant Integration -- RTSP (instead of RTMP) relay for use with other consumers to reduce the number of connections to your camera streams +- RTSP relay for use with other consumers to reduce the number of connections to your camera streams # Setup a go2rtc stream diff --git a/docs/docs/integrations/home-assistant.md b/docs/docs/integrations/home-assistant.md index f9cb74ebb..462cdeabc 100644 --- a/docs/docs/integrations/home-assistant.md +++ b/docs/docs/integrations/home-assistant.md @@ -124,10 +124,6 @@ https://HA_URL/api/frigate/notifications//clip.mp4 -## RTMP stream - -RTMP is deprecated and it is recommended to switch to use RTSP restreams. - ## RTSP stream In order for the live streams to function they need to be accessible on the RTSP diff --git a/frigate/config.py b/frigate/config.py index 59ca519fa..3f68f302a 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -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 diff --git a/frigate/ffmpeg_presets.py b/frigate/ffmpeg_presets.py index fe672b25e..82ca92dda 100644 --- a/frigate/ffmpeg_presets.py +++ b/frigate/ffmpeg_presets.py @@ -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) diff --git a/frigate/test/test_config.py b/frigate/test/test_config.py index 8c40b5338..94863709c 100644 --- a/frigate/test/test_config.py +++ b/frigate/test/test_config.py @@ -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": { diff --git a/frigate/test/test_ffmpeg_presets.py b/frigate/test/test_ffmpeg_presets.py index 0d3dab856..469c28f1f 100644 --- a/frigate/test/test_ffmpeg_presets.py +++ b/frigate/test/test_ffmpeg_presets.py @@ -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) diff --git a/process_clip.py b/process_clip.py index 16bf7afa4..2ab8dbe77 100644 --- a/process_clip.py +++ b/process_clip.py @@ -262,7 +262,6 @@ def process(path, label, output, debug_path): } ] }, - "rtmp": {"enabled": False}, "record": {"enabled": False}, } },