"""Tests for ffmpeg.convert_file command generation (no encoding runs).""" from conftest import ffmpeg_converter, arg_after def _vf(cmd): return arg_after(cmd, "-vf") def test_compatibility_dvd_basics(make_file_project): conv = ffmpeg_converter(profile="compatibility") conv.convert_file(make_file_project(), "/tmp/out.mpg", 0) cmd = conv.command_var assert "mpeg2video" in cmd assert "ac3" in cmd # fork uses AC3 for NTSC DVD assert arg_after(cmd, "-ar") == "48000" assert arg_after(cmd, "-b:v") == str(4500 * 1000) assert arg_after(cmd, "-b:a") == str(192 * 1000) assert _vf(cmd) == "scale=720:480" assert "-sn" in cmd # no soft-sub passthrough def test_runs_under_nice(make_file_project): conv = ffmpeg_converter() conv.convert_file(make_file_project(), "/tmp/out.mpg", 0) assert conv.command_var[:4] == ["nice", "-n", "10", "ffmpeg"] def test_progress_goes_to_file_not_pipe(make_file_project): # the deadlock fix: -progress must target a file, never pipe:N conv = ffmpeg_converter() conv.convert_file(make_file_project(), "/tmp/out.mpg", 0) prog = arg_after(conv.command_var, "-progress") assert prog is not None assert not prog.startswith("pipe:") assert prog.endswith(".progress") def test_text_hardsub_filter_after_scale(make_file_project): fp = make_file_project( hardsub_index=2, hardsub_kind="text", embedded_subtitles=[{"index": 2, "codec": "subrip", "language": "eng", "title": "", "default": True, "forced": False, "kind": "text"}], ) conv = ffmpeg_converter() conv.convert_file(fp, "/tmp/out.mpg", 0) vf = _vf(conv.command_var) assert vf is not None assert vf.startswith("scale=720:480") assert "subtitles=" in vf assert "si=0" in vf # first (and only) subtitle stream def test_text_hardsub_escapes_path(make_file_project): fp = make_file_project( file_name="/movies/My Movie: 2024.mkv", hardsub_index=2, hardsub_kind="text", embedded_subtitles=[{"index": 2, "codec": "subrip", "language": "eng", "title": "", "default": False, "forced": False, "kind": "text"}], ) conv = ffmpeg_converter() conv.convert_file(fp, "/tmp/out.mpg", 0) vf = _vf(conv.command_var) assert r"\:" in vf # the ':' in the path is escaped def test_image_hardsub_uses_filter_complex_overlay(make_file_project): fp = make_file_project( hardsub_index=3, hardsub_kind="image", embedded_subtitles=[{"index": 3, "codec": "hdmv_pgs_subtitle", "language": "eng", "title": "", "default": True, "forced": False, "kind": "image"}], ) conv = ffmpeg_converter() conv.convert_file(fp, "/tmp/out.mpg", 0) cmd = conv.command_var fc = arg_after(cmd, "-filter_complex") assert fc is not None assert "overlay" in fc # overlay must come before scale so bitmap subs stay aligned to the source assert fc.index("overlay") < fc.index("scale=720:480") assert fc.endswith("[vsub]") assert arg_after(cmd, "-map") == "[vsub]" # video taken from the graph assert "-vf" not in cmd # not both -vf and filter_complex def test_high_profile_two_pass_and_448k_audio(make_file_project): # regression for the AC3 448k -> 384k clamp bug fp = make_file_project(two_pass_encoding=True, video_rate_final=3752, audio_rate_final=448) conv = ffmpeg_converter(profile="high") conv.convert_file(fp, "/tmp/out.mpg", 0) cmd = conv.command_var assert "-pass" in cmd and "-passlogfile" in cmd assert arg_after(cmd, "-b:a") == str(448 * 1000) # NOT clamped to 384k assert arg_after(cmd, "-b:v") == str(3752 * 1000) assert len(conv.childs) == 1 # spawns the pass-2 child def test_audio_bitrate_table_allows_ac3_rates(make_file_project): conv = ffmpeg_converter() assert conv._adjust_audio_bitrate(448) == 448 assert conv._adjust_audio_bitrate(400) == 448 # rounds up to next valid assert conv._adjust_audio_bitrate(192) == 192 assert conv._adjust_audio_bitrate(9999) == 640 # clamps to table max def test_even_dimensions_and_positive_crop_offset(make_file_project): # odd letterbox height (1079) must be rounded even, offset positive fp = make_file_project(width_midle=1920, height_midle=1079) conv = ffmpeg_converter() conv.convert_file(fp, "/tmp/out.mpg", 0) cmd = conv.command_var blob = _vf(cmd) or arg_after(cmd, "-filter_complex") or "" assert "1079" not in blob # no odd dimension assert ":-" not in blob # no negative crop/pad offset assert "1078" in blob # rounded down to even def test_start_offset_emits_ss_before_inputs(make_file_project): conv = ffmpeg_converter() conv.convert_file(make_file_project(), "/tmp/out.mpg", 0, start_offset=120) cmd = conv.command_var # -ss appears before each -i (two inputs: audio-delay copy + video) assert cmd.count("-ss") == 2 first_i = cmd.index("-i") first_ss = cmd.index("-ss") assert first_ss < first_i def test_no_start_offset_has_no_ss(make_file_project): conv = ffmpeg_converter() conv.convert_file(make_file_project(), "/tmp/out.mpg", 0) assert "-ss" not in conv.command_var