mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-10-10 00:32:48 +03:00
Add sub stream recording with adaptive quality playback (#24009)
* add sub stream recording with adaptive quality playback Optionally record a second, lower bitrate stream alongside the main recording stream via a `record_sub` input role and `record.sub` config block, with its own retention windows. Recordings rows now carry the stream type plus the media details needed to serve both streams from one manifest: video codec, audio presence, audio codec and rate, and a record-time keyframe index. Playback resolves coverage across both streams and merges them into a single VOD sequence, falling back to a discontinuity manifest with per-clip init segments when the media signatures differ. The player exposes a quality selector, and an auto governor picks the stream from stall time, bandwidth, codec support, and the save-data hint. * fix tests and i18n
This commit is contained in:
committed by
Nicolas Mowen
parent
f7c5500ea8
commit
1498231eb9
@@ -255,6 +255,15 @@ 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.record.enabled
|
||||
and camera_config.record.sub.enabled
|
||||
and "record_sub" not in assigned_roles
|
||||
):
|
||||
raise ValueError(
|
||||
f"Camera {camera_config.name} has sub stream recording enabled, but record_sub 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."
|
||||
@@ -275,13 +284,11 @@ def verify_valid_live_stream_names(
|
||||
)
|
||||
|
||||
|
||||
def verify_recording_segments_setup_with_reasonable_time(
|
||||
camera_config: CameraConfig,
|
||||
def verify_record_output_args_segment_time(
|
||||
camera_config: CameraConfig, output_args: str | list[str], role: str
|
||||
) -> None:
|
||||
"""Verify that recording segments are setup and segment time is not greater than 60."""
|
||||
record_args: list[str] = get_ffmpeg_arg_list(
|
||||
camera_config.ffmpeg.output_args.record
|
||||
)
|
||||
"""Verify that a recording role's output args segment at a reasonable time."""
|
||||
record_args: list[str] = get_ffmpeg_arg_list(output_args)
|
||||
|
||||
if record_args[0].startswith("preset"):
|
||||
return
|
||||
@@ -291,16 +298,32 @@ def verify_recording_segments_setup_with_reasonable_time(
|
||||
except ValueError:
|
||||
raise ValueError(
|
||||
f"Camera {camera_config.name} has no segment_time in \
|
||||
recording output args, segment args are required for record."
|
||||
{role} output args, segment args are required for record."
|
||||
) from None
|
||||
|
||||
if int(record_args[seg_arg_index + 1]) > 60:
|
||||
raise ValueError(
|
||||
f"Camera {camera_config.name} has invalid segment_time output arg, \
|
||||
f"Camera {camera_config.name} has invalid segment_time in {role} output args, \
|
||||
segment_time must be 60 or less."
|
||||
)
|
||||
|
||||
|
||||
def verify_recording_segments_setup_with_reasonable_time(
|
||||
camera_config: CameraConfig,
|
||||
) -> None:
|
||||
"""Verify that recording segments are setup and segment time is not greater than 60."""
|
||||
verify_record_output_args_segment_time(
|
||||
camera_config, camera_config.ffmpeg.output_args.record, "recording"
|
||||
)
|
||||
|
||||
if camera_config.record.sub.enabled:
|
||||
verify_record_output_args_segment_time(
|
||||
camera_config,
|
||||
camera_config.ffmpeg.output_args.effective_record_sub,
|
||||
"sub stream recording",
|
||||
)
|
||||
|
||||
|
||||
def verify_zone_objects_are_tracked(camera_config: CameraConfig) -> None:
|
||||
"""Verify that user has not entered zone objects that are not in the tracking config."""
|
||||
for zone_name, zone in camera_config.zones.items():
|
||||
|
||||
Reference in New Issue
Block a user