Rewrite restream (#5106)

* Tear out restream config

* Rework birdseye restream

* Create go2rtc config handler

* Fix bug

* Write start script

* Rework style

* Fix python run syntax

* Output as json instead of yaml

* Put old live config back and fix birdseye references

* Fix camera webUI

* Add frigate env var subsitutions

* Fix webui checks

* Check keys

* Remove unused prest

* Fix tests

* Update restream docs

* Update restream docs

* Update live docs

* Update camera specific recommendation

* Update more docs

* add links for the docs

Co-authored-by: Felipe Santos <felipecassiors@gmail.com>

* Update note about supported audio codecs

* Move restream to go2rtc

* Docs fixes

* Add verification of stream name

* Ensure that webUI uses camera name

* Update docs to reflect new live stream name

* Fix check

* Formatting

* Remove audio from detect

Co-authored-by: Felipe Santos <felipecassiors@gmail.com>

* Fix docs

* Don't handle env variable substitution

* Add go2rtc version

* Clarify docs

Co-authored-by: Felipe Santos <felipecassiors@gmail.com>
This commit is contained in:
Nicolas Mowen
2023-01-16 16:50:35 -07:00
committed by GitHub
parent a7751f210b
commit 19afb035ff
17 changed files with 212 additions and 406 deletions

View File

@@ -344,6 +344,7 @@ class BirdseyeModeEnum(str, Enum):
class BirdseyeConfig(FrigateBaseModel):
enabled: bool = Field(default=True, title="Enable birdseye view.")
restream: bool = Field(default=False, title="Restream birdseye via RTSP.")
width: int = Field(default=1280, title="Birdseye width.")
height: int = Field(default=720, title="Birdseye height.")
quality: int = Field(
@@ -405,7 +406,6 @@ class FfmpegConfig(FrigateBaseModel):
class CameraRoleEnum(str, Enum):
record = "record"
restream = "restream"
rtmp = "rtmp"
detect = "detect"
@@ -519,39 +519,15 @@ class RtmpConfig(FrigateBaseModel):
enabled: bool = Field(default=False, title="RTMP restreaming enabled.")
class JsmpegStreamConfig(FrigateBaseModel):
height: int = Field(default=720, title="Live camera view height.")
quality: int = Field(default=8, ge=1, le=31, title="Live camera view quality.")
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")
quality: int = Field(default=8, ge=1, le=31, title="Live camera view quality")
class RestreamVideoCodecEnum(str, Enum):
copy = "copy"
h264 = "h264"
h265 = "h265"
class RestreamAudioCodecEnum(str, Enum):
aac = "aac"
copy = "copy"
opus = "opus"
class RestreamConfig(FrigateBaseModel):
enabled: bool = Field(default=True, title="Restreaming enabled.")
audio_encoding: list[RestreamAudioCodecEnum] = Field(
default=[RestreamAudioCodecEnum.aac, RestreamAudioCodecEnum.opus],
title="Codecs to supply for audio.",
)
video_encoding: RestreamVideoCodecEnum = Field(
default=RestreamVideoCodecEnum.copy, title="Method for encoding the restream."
)
force_audio: bool = Field(
default=True, title="Force audio compatibility with the browser."
)
birdseye: bool = Field(default=False, title="Restream the birdseye feed via RTSP.")
jsmpeg: JsmpegStreamConfig = Field(
default_factory=JsmpegStreamConfig, title="Jsmpeg Stream Configuration."
)
class RestreamConfig(BaseModel):
class Config:
extra = Extra.allow
class CameraUiConfig(FrigateBaseModel):
@@ -578,8 +554,8 @@ class CameraConfig(FrigateBaseModel):
rtmp: RtmpConfig = Field(
default_factory=RtmpConfig, title="RTMP restreaming configuration."
)
restream: RestreamConfig = Field(
default_factory=RestreamConfig, title="Restreaming configuration."
live: CameraLiveConfig = Field(
default_factory=CameraLiveConfig, title="Live playback settings."
)
snapshots: SnapshotsConfig = Field(
default_factory=SnapshotsConfig, title="Snapshot configuration."
@@ -621,7 +597,6 @@ class CameraConfig(FrigateBaseModel):
config["ffmpeg"]["inputs"][0]["roles"] = [
"record",
"detect",
"restream",
]
if has_rtmp:
@@ -758,9 +733,17 @@ def verify_config_roles(camera_config: CameraConfig) -> None:
f"Camera {camera_config.name} has rtmp enabled, but rtmp is not assigned to an input."
)
if camera_config.restream.enabled and not "restream" in assigned_roles:
raise ValueError(
f"Camera {camera_config.name} has restream enabled, but restream is not assigned to an input."
def verify_valid_live_stream_name(
frigate_config: FrigateConfig, camera_config: CameraConfig
) -> None:
"""Verify that a restream exists to use for live view."""
if (
camera_config.live.stream_name
not in frigate_config.go2rtc.dict().get("streams", {}).keys()
):
return ValueError(
f"No restream with name {camera_config.live.stream_name} exists for camera {camera_config.name}."
)
@@ -854,7 +837,10 @@ class FrigateConfig(FrigateBaseModel):
rtmp: RtmpConfig = Field(
default_factory=RtmpConfig, title="Global RTMP restreaming configuration."
)
restream: RestreamConfig = Field(
live: CameraLiveConfig = Field(
default_factory=CameraLiveConfig, title="Live playback settings."
)
go2rtc: RestreamConfig = Field(
default_factory=RestreamConfig, title="Global restream configuration."
)
birdseye: BirdseyeConfig = Field(
@@ -895,7 +881,7 @@ class FrigateConfig(FrigateBaseModel):
"record": ...,
"snapshots": ...,
"rtmp": ...,
"restream": ...,
"live": ...,
"objects": ...,
"motion": ...,
"detect": ...,
@@ -968,7 +954,12 @@ class FrigateConfig(FrigateBaseModel):
**camera_config.motion.dict(exclude_unset=True),
)
# Set live view stream if none is set
if not camera_config.live.stream_name:
camera_config.live.stream_name = name
verify_config_roles(camera_config)
verify_valid_live_stream_name(config, camera_config)
verify_old_retain_config(camera_config)
verify_recording_retention(camera_config)
verify_recording_segments_setup_with_reasonable_time(camera_config)