"""Tests for the shared ffmpeg progress helper.""" import unittest from unittest.mock import MagicMock, patch from frigate.util.ffmpeg import inject_progress_flags, run_ffmpeg_with_progress class TestInjectProgressFlags(unittest.TestCase): def test_inserts_flags_before_output_path(self): cmd = ["ffmpeg", "-i", "in.mp4", "-c", "copy", "out.mp4"] result = inject_progress_flags(cmd) self.assertEqual( result, [ "ffmpeg", "-i", "in.mp4", "-c", "copy", "-progress", "pipe:2", "-nostats", "out.mp4", ], ) def test_empty_cmd_returns_empty(self): self.assertEqual(inject_progress_flags([]), []) class TestRunFfmpegWithProgress(unittest.TestCase): def _make_fake_proc(self, stderr_lines, returncode=0): proc = MagicMock() proc.stderr = iter(stderr_lines) proc.stdin = MagicMock() proc.returncode = returncode proc.wait = MagicMock() return proc def test_emits_percent_from_out_time_us_lines(self): captured: list[float] = [] def on_progress(percent: float) -> None: captured.append(percent) stderr_lines = [ "out_time_us=1000000\n", "out_time_us=5000000\n", "progress=end\n", ] proc = self._make_fake_proc(stderr_lines) proc.stderr = MagicMock() proc.stderr.__iter__ = lambda self: iter(stderr_lines) proc.stderr.read = MagicMock(return_value="") with patch("subprocess.Popen", return_value=proc): returncode, _stderr = run_ffmpeg_with_progress( ["ffmpeg", "-i", "in", "out"], expected_duration_seconds=10.0, on_progress=on_progress, use_low_priority=False, ) self.assertEqual(returncode, 0) self.assertEqual(len(captured), 4) # initial 0.0 + two parsed + final 100.0 self.assertAlmostEqual(captured[0], 0.0) self.assertAlmostEqual(captured[1], 10.0) self.assertAlmostEqual(captured[2], 50.0) self.assertAlmostEqual(captured[3], 100.0) def test_passes_started_process_to_callback(self): proc = self._make_fake_proc([]) proc.stderr = MagicMock() proc.stderr.__iter__ = lambda self: iter([]) proc.stderr.read = MagicMock(return_value="") seen: list = [] with patch("subprocess.Popen", return_value=proc): run_ffmpeg_with_progress( ["ffmpeg", "out"], expected_duration_seconds=1.0, process_started=lambda p: seen.append(p), use_low_priority=False, ) self.assertEqual(seen, [proc]) def test_clamps_percent_to_0_100(self): captured: list[float] = [] def on_progress(percent: float) -> None: captured.append(percent) stderr_lines = ["out_time_us=999999999999\n"] proc = self._make_fake_proc(stderr_lines) proc.stderr = MagicMock() proc.stderr.__iter__ = lambda self: iter(stderr_lines) proc.stderr.read = MagicMock(return_value="") with patch("subprocess.Popen", return_value=proc): run_ffmpeg_with_progress( ["ffmpeg", "out"], expected_duration_seconds=10.0, on_progress=on_progress, use_low_priority=False, ) # initial 0.0 then a clamped reading self.assertEqual(captured[-1], 100.0)