don't treat unknown audio as an audio-bearing stream

A recording row with NULL has_audio (ffprobe failed and the cv2 fallback can't report audio) marked the whole stream as audio-bearing, so every confirmed video-only row on it was dropped as a glitch. A stream now counts as audio-bearing only when a row is known to carry audio.
This commit is contained in:
Josh Hawkins
2026-10-09 06:37:21 -05:00
parent d4a7504d67
commit 71445231f6
2 changed files with 21 additions and 3 deletions
+17
View File
@@ -13,6 +13,7 @@ from frigate.models import Recordings
from frigate.util.recording_coverage import (
_rows_query,
coverage_spans,
null_audio_glitches,
plan_clip,
realized_timeline,
resolve_coverage,
@@ -166,6 +167,22 @@ class TestRecordingCoverage(CoverageDbTestCase):
expected = int(5 * 1024 * 1024 * 8 / 10)
assert summary["main"]["bitrate"] == expected
def test_unknown_audio_row_keeps_video_only_stream(self):
self._insert("s1", 1000.0, 1010.0, "sub", has_audio=False)
self._insert("s2", 1010.0, 1020.0, "sub", has_audio=None)
self._insert("s3", 1020.0, 1030.0, "sub", has_audio=False)
kept = null_audio_glitches(resolve_coverage("front_door", 1000.0, 1030.0))
self.assertEqual(
[i.sub.path for i in kept], [f"/tmp/s{n}.mp4" for n in (1, 2, 3)]
)
def test_video_only_glitch_dropped_on_audio_stream(self):
self._insert("s1", 1000.0, 1010.0, "sub", has_audio=True)
self._insert("s2", 1010.0, 1020.0, "sub", has_audio=False)
self._insert("s3", 1020.0, 1030.0, "sub", has_audio=None)
kept = null_audio_glitches(resolve_coverage("front_door", 1000.0, 1030.0))
self.assertEqual([i.sub.path for i in kept], ["/tmp/s1.mp4", "/tmp/s3.mp4"])
def test_other_camera_rows_excluded(self):
self._insert("m1", 1000.0, 1010.0, "main")
self._insert("o1", 1000.0, 1010.0, "main", camera="back_yard")
+4 -3
View File
@@ -204,11 +204,12 @@ def coverage_spans(intervals: list[CoverageInterval]) -> list[dict[str, Any]]:
def stream_has_audio(intervals: list[CoverageInterval], main: bool) -> bool:
"""Whether a stream is audio-bearing over a coverage window.
A stream counts as audio-bearing unless EVERY one of its rows reports
has_audio False; NULL (legacy or undetermined) counts as audio.
A stream counts as audio-bearing only when one of its rows is known
to carry audio. A NULL row (legacy, or a segment ffprobe could not
read) proves nothing either way.
"""
return any(
row is not None and row.has_audio is not False
row is not None and row.has_audio is True
for row in ((interval.main if main else interval.sub) for interval in intervals)
)