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:
Josh Hawkins
2026-08-27 20:30:35 -05:00
parent 31bbf910c7
commit 5d807587ab
68 changed files with 6813 additions and 602 deletions
+52
View File
@@ -196,6 +196,10 @@
"record": {
"label": "Record output arguments",
"description": "Default output arguments for record role streams."
},
"record_sub": {
"label": "Sub stream record output arguments",
"description": "Output arguments for record_sub role streams. The record output arguments are used when this is not set."
}
},
"retry_interval": {
@@ -522,6 +526,54 @@
"description": "Preview quality level (very_low, low, medium, high, very_high)."
}
},
"sub": {
"label": "Sub stream recording",
"description": "Settings for recording a second, lower quality stream.",
"enabled": {
"label": "Enable sub stream recording",
"description": "Enable recording of a second, lower quality stream for adaptive quality playback and extended retention."
},
"continuous": {
"label": "Sub stream continuous retention",
"description": "Number of days to retain sub stream recordings regardless of tracked objects or motion.",
"days": {
"label": "Retention days",
"description": "Days to retain recordings."
}
},
"motion": {
"label": "Sub stream motion retention",
"description": "Number of days to retain sub stream recordings triggered by motion.",
"days": {
"label": "Retention days",
"description": "Days to retain recordings."
}
},
"alerts": {
"label": "Sub stream alert retention",
"description": "Retention settings for sub stream recordings of alerts.",
"days": {
"label": "Retention days",
"description": "Number of days to retain recordings of detection events."
},
"mode": {
"label": "Retention mode",
"description": "Mode for retention: all (save all segments), motion (save segments with motion), or active_objects (save segments with active objects)."
}
},
"detections": {
"label": "Sub stream detection retention",
"description": "Retention settings for sub stream recordings of detections.",
"days": {
"label": "Retention days",
"description": "Number of days to retain recordings of detection events."
},
"mode": {
"label": "Retention mode",
"description": "Mode for retention: all (save all segments), motion (save segments with motion), or active_objects (save segments with active objects)."
}
}
},
"enabled_in_config": {
"label": "Original recording state",
"description": "Indicates whether recording was enabled in the original static configuration."
+52
View File
@@ -707,6 +707,10 @@
"record": {
"label": "Record output arguments",
"description": "Default output arguments for record role streams."
},
"record_sub": {
"label": "Sub stream record output arguments",
"description": "Output arguments for record_sub role streams. The record output arguments are used when this is not set."
}
},
"retry_interval": {
@@ -1048,6 +1052,54 @@
"description": "Preview quality level (very_low, low, medium, high, very_high)."
}
},
"sub": {
"label": "Sub stream recording",
"description": "Settings for recording a second, lower quality stream.",
"enabled": {
"label": "Enable sub stream recording",
"description": "Enable recording of a second, lower quality stream for adaptive quality playback and extended retention."
},
"continuous": {
"label": "Sub stream continuous retention",
"description": "Number of days to retain sub stream recordings regardless of tracked objects or motion.",
"days": {
"label": "Retention days",
"description": "Days to retain recordings."
}
},
"motion": {
"label": "Sub stream motion retention",
"description": "Number of days to retain sub stream recordings triggered by motion.",
"days": {
"label": "Retention days",
"description": "Days to retain recordings."
}
},
"alerts": {
"label": "Sub stream alert retention",
"description": "Retention settings for sub stream recordings of alerts.",
"days": {
"label": "Retention days",
"description": "Number of days to retain recordings of detection events."
},
"mode": {
"label": "Retention mode",
"description": "Mode for retention: all (save all segments), motion (save segments with motion), or active_objects (save segments with active objects)."
}
},
"detections": {
"label": "Sub stream detection retention",
"description": "Retention settings for sub stream recordings of detections.",
"days": {
"label": "Retention days",
"description": "Number of days to retain recordings of detection events."
},
"mode": {
"label": "Retention mode",
"description": "Mode for retention: all (save all segments), motion (save segments with motion), or active_objects (save segments with active objects)."
}
}
},
"enabled_in_config": {
"label": "Original recording state",
"description": "Indicates whether recording was enabled in the original static configuration."