Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions media_shrinker.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@
BITRATE_SAFETY_MARGIN = 0.92
OPUS_MAX_BITRATE_BPS = 510_000
OPUS_MIN_REASONABLE_BITRATE_BPS = 16_000
SILENCE_START_RE = re.compile(r"silence_start:\s*(?P<value>[0-9]+(?:\.[0-9]+)?)")
SILENCE_END_RE = re.compile(r"silence_end:\s*(?P<value>[0-9]+(?:\.[0-9]+)?)")
SILENCE_START_RE = re.compile(r"silence_start:\s*(?P<value>-?[0-9]+(?:\.[0-9]+)?)")
SILENCE_END_RE = re.compile(r"silence_end:\s*(?P<value>-?[0-9]+(?:\.[0-9]+)?)")


class MediaShrinkerError(RuntimeError):
Expand Down
33 changes: 33 additions & 0 deletions tests/test_media_shrinker.py
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,39 @@ def test_parse_silencedetect_intervals_pairs_long_silence_start_and_end(
],
)

def test_parse_silencedetect_intervals_keeps_negative_start_at_recording_head(
self,
) -> None:
# ffmpeg back-dates silence_start by the detection window, so a file that
# begins in silence reports a slightly negative silence_start. The whole
# interval must survive so it can still be used as a split boundary.
stderr = """
[silencedetect @ 0x1] silence_start: -0.00816327
[silencedetect @ 0x1] silence_end: 150.5 | silence_duration: 150.5
"""

intervals = parse_silencedetect_intervals(stderr)

self.assertEqual(
intervals,
[SilenceInterval(start_seconds=-0.00816327, end_seconds=150.5)],
)

def test_negative_start_silence_still_drives_split_point(self) -> None:
# A silence that opens the recording but extends well past the midpoint is
# the best split boundary; dropping it forces an unwanted mid-audio cut.
intervals = parse_silencedetect_intervals(
"[silencedetect @ 0x1] silence_start: -0.008\n"
"[silencedetect @ 0x1] silence_end: 150.5 | silence_duration: 150.5\n"
)
segments = build_segments(
duration_seconds=300.0,
max_segment_duration_seconds=200.0,
silence_intervals=intervals,
)

self.assertEqual(segments[0].duration_seconds, 150.5)


class SilenceDetectionTests(unittest.TestCase):
@patch("media_shrinker.subprocess.run")
Expand Down
Loading