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:
Nicolas Mowen 2023-12-12 16:20:25 -07:00 committed by Blake Blackshear
parent 696434b36d
commit d2d1278a4d
13 changed files with 7 additions and 263 deletions

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -124,10 +124,6 @@ https://HA_URL/api/frigate/notifications/<event-id>/clip.mp4
<a name="streams"></a>
## 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

View File

@ -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

View File

@ -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)

View File

@ -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": {

View File

@ -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)

View File

@ -262,7 +262,6 @@ def process(path, label, output, debug_path):
}
]
},
"rtmp": {"enabled": False},
"record": {"enabled": False},
}
},