Rework audio encoding for restream (#5092)

* Use memo for recordings timezone

* Add audio encoding field and simplify stream creation

* Update docs and tests

* Fix bad logic
This commit is contained in:
Nicolas Mowen 2023-01-15 08:38:19 -07:00 committed by GitHub
parent daadd206dd
commit 01b9d4d848
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 18 deletions

View File

@ -356,8 +356,12 @@ rtmp:
restream: restream:
# Optional: Enable the restream (default: True) # Optional: Enable the restream (default: True)
enabled: True enabled: True
# Optional: Force audio compatibility with browsers (default: shown below) # Optional: Set the audio codecs to restream with
force_audio: True # possible values are aac, copy, opus. Set to copy
# only to avoid transcoding (default: shown below)
audio_encoding:
- aac
- opus
# Optional: Video encoding to be used. By default the codec will be copied but # Optional: Video encoding to be used. By default the codec will be copied but
# it can be switched to another or an MJPEG stream can be encoded and restreamed # it can be switched to another or an MJPEG stream can be encoded and restreamed
# as h264 (default: shown below) # as h264 (default: shown below)

View File

@ -7,9 +7,9 @@ title: Restream
Frigate can restream your video feed as an RTSP feed for other applications such as Home Assistant to utilize it at `rtsp://<frigate_host>:8554/<camera_name>`. Port 8554 must be open. [This allows you to use a video feed for detection in Frigate and Home Assistant live view at the same time without having to make two separate connections to the camera](#reduce-connections-to-camera). The video feed is copied from the original video feed directly to avoid re-encoding. This feed does not include any annotation by Frigate. Frigate can restream your video feed as an RTSP feed for other applications such as Home Assistant to utilize it at `rtsp://<frigate_host>:8554/<camera_name>`. Port 8554 must be open. [This allows you to use a video feed for detection in Frigate and Home Assistant live view at the same time without having to make two separate connections to the camera](#reduce-connections-to-camera). The video feed is copied from the original video feed directly to avoid re-encoding. This feed does not include any annotation by Frigate.
#### Force Audio #### Copy Audio
Different live view technologies (ex: MSE, WebRTC) support different audio codecs. The `restream -> force_audio` flag tells the restream to make multiple streams available so that all live view technologies are supported. Some camera streams don't work well with this, in which case `restream -> force_audio` should be disabled. Different live view technologies (ex: MSE, WebRTC) support different audio codecs. The `restream -> audio_encoding` field tells the restream to make multiple streams available so that all live view technologies are supported. Some camera streams don't work well with this, in which case `restream -> audio_encoding` should be set to `copy` only.
#### Birdseye Restream #### Birdseye Restream

View File

@ -524,16 +524,26 @@ class JsmpegStreamConfig(FrigateBaseModel):
quality: int = Field(default=8, ge=1, le=31, title="Live camera view quality.") quality: int = Field(default=8, ge=1, le=31, title="Live camera view quality.")
class RestreamCodecEnum(str, Enum): class RestreamVideoCodecEnum(str, Enum):
copy = "copy" copy = "copy"
h264 = "h264" h264 = "h264"
h265 = "h265" h265 = "h265"
class RestreamAudioCodecEnum(str, Enum):
aac = "aac"
copy = "copy"
opus = "opus"
class RestreamConfig(FrigateBaseModel): class RestreamConfig(FrigateBaseModel):
enabled: bool = Field(default=True, title="Restreaming enabled.") enabled: bool = Field(default=True, title="Restreaming enabled.")
video_encoding: RestreamCodecEnum = Field( audio_encoding: list[RestreamAudioCodecEnum] = Field(
default=RestreamCodecEnum.copy, title="Method for encoding the restream." 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( force_audio: bool = Field(
default=True, title="Force audio compatibility with the browser." default=True, title="Force audio compatibility with the browser."

View File

@ -6,7 +6,7 @@ import requests
from typing import Optional from typing import Optional
from frigate.config import FrigateConfig, RestreamCodecEnum from frigate.config import FrigateConfig, RestreamAudioCodecEnum, RestreamVideoCodecEnum
from frigate.const import BIRDSEYE_PIPE from frigate.const import BIRDSEYE_PIPE
from frigate.ffmpeg_presets import ( from frigate.ffmpeg_presets import (
parse_preset_hardware_acceleration_encode, parse_preset_hardware_acceleration_encode,
@ -18,18 +18,26 @@ logger = logging.getLogger(__name__)
def get_manual_go2rtc_stream( def get_manual_go2rtc_stream(
camera_url: str, codec: RestreamCodecEnum, engine: Optional[str] camera_url: str,
aCodecs: list[RestreamAudioCodecEnum],
vCodec: RestreamVideoCodecEnum,
engine: Optional[str],
) -> str: ) -> str:
"""Get a manual stream for go2rtc.""" """Get a manual stream for go2rtc."""
if codec == RestreamCodecEnum.copy: stream = f"ffmpeg:{camera_url}"
return f"ffmpeg:{camera_url}#video=copy#audio=aac#audio=opus"
for aCodec in aCodecs:
stream += f"#audio={aCodec}"
if vCodec == RestreamVideoCodecEnum.copy:
stream += "#video=copy"
else:
stream += f"#video={vCodec}"
if engine: if engine:
return ( stream += f"#hardware={engine}"
f"ffmpeg:{camera_url}#video={codec}#hardware={engine}#audio=aac#audio=opus"
)
return f"ffmpeg:{camera_url}#video={codec}#audio=aac#audio=opus" return stream
class RestreamApi: class RestreamApi:
@ -50,7 +58,10 @@ class RestreamApi:
if "restream" in input.roles: if "restream" in input.roles:
if ( if (
input.path.startswith("rtsp") input.path.startswith("rtsp")
and not camera.restream.force_audio and camera.restream.video_encoding
== RestreamVideoCodecEnum.copy
and camera.restream.audio_encoding
== [RestreamAudioCodecEnum.copy]
): ):
self.relays[ self.relays[
cam_name cam_name
@ -59,6 +70,7 @@ class RestreamApi:
# go2rtc only supports rtsp for direct relay, otherwise ffmpeg is used # go2rtc only supports rtsp for direct relay, otherwise ffmpeg is used
self.relays[cam_name] = get_manual_go2rtc_stream( self.relays[cam_name] = get_manual_go2rtc_stream(
escape_special_characters(input.path), escape_special_characters(input.path),
camera.restream.audio_encoding,
camera.restream.video_encoding, camera.restream.video_encoding,
parse_preset_hardware_acceleration_go2rtc_engine( parse_preset_hardware_acceleration_go2rtc_engine(
self.config.ffmpeg.hwaccel_args self.config.ffmpeg.hwaccel_args

View File

@ -25,7 +25,7 @@ class TestRestream(TestCase):
}, },
"restream": { "restream": {
"enabled": True, "enabled": True,
"force_audio": False, "audio_encoding": ["copy"],
}, },
}, },
"front": { "front": {