76 lines
3.1 KiB
Python
76 lines
3.1 KiB
Python
"""End-to-end tests against a real ffmpeg. Skipped when ffmpeg is not available.
|
|
|
|
Set FFWRAP_FFMPEG_DIR to point at a folder containing ffmpeg/ffprobe, or put them on PATH.
|
|
"""
|
|
|
|
import os
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from ffwrap.command import Options, build_command, match_audio_selection
|
|
from ffwrap.probe import probe
|
|
from ffwrap.tools import locate_tools
|
|
|
|
TOOLS = locate_tools(os.environ.get("FFWRAP_FFMPEG_DIR"))
|
|
pytestmark = pytest.mark.skipif(TOOLS is None, reason="ffmpeg/ffprobe not found")
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def sample(tmp_path_factory) -> Path:
|
|
"""3 s 640x360 H.264 + jpn 5.1 AC3 + eng stereo AAC + English SRT in an MKV."""
|
|
d = tmp_path_factory.mktemp("media")
|
|
srt = d / "subs.srt"
|
|
srt.write_text("1\n00:00:00,500 --> 00:00:02,000\nHello\n", encoding="utf-8")
|
|
out = d / "sample.mkv"
|
|
subprocess.run([
|
|
TOOLS.ffmpeg, "-v", "error", "-y",
|
|
"-f", "lavfi", "-i", "testsrc2=size=640x360:rate=25:duration=3",
|
|
"-f", "lavfi", "-i", "sine=frequency=440:duration=3",
|
|
"-f", "lavfi", "-i", "sine=frequency=880:duration=3",
|
|
"-i", str(srt),
|
|
"-map", "0", "-map", "1", "-map", "2", "-map", "3",
|
|
"-c:v", "libx264", "-preset", "ultrafast",
|
|
"-c:a:0", "ac3", "-ac:a:0", "6", "-c:a:1", "aac", "-ac:a:1", "2", "-c:s", "srt",
|
|
"-metadata:s:a:0", "language=jpn", "-metadata:s:a:1", "language=eng",
|
|
"-metadata:s:s:0", "language=eng",
|
|
str(out),
|
|
], check=True)
|
|
return out
|
|
|
|
|
|
def run(info, opts, audio, out):
|
|
built = build_command(TOOLS.ffmpeg, info, opts, audio, out)
|
|
res = subprocess.run(built.args, capture_output=True, text=True)
|
|
assert res.returncode == 0, res.stderr
|
|
return probe(TOOLS.ffprobe, out)
|
|
|
|
|
|
def test_remux_to_mp4_keeps_streams(sample, tmp_path):
|
|
info = probe(TOOLS.ffprobe, sample)
|
|
eng = match_audio_selection(info.audio, [info.audio[1].index], info.audio)
|
|
out = run(info, Options(container="mp4"), eng, tmp_path / "out.mp4")
|
|
assert out.video.codec == "h264"
|
|
assert [(a.codec, a.language) for a in out.audio] == [("aac", "eng")]
|
|
assert [s.codec for s in out.subtitles] == ["mov_text"]
|
|
assert abs(out.duration - info.duration) < 0.5
|
|
|
|
|
|
def test_reencode_scale_and_downmix(sample, tmp_path):
|
|
info = probe(TOOLS.ffprobe, sample)
|
|
opts = Options(container="mkv", video_mode="encode", video_encoder="libx265", resolution=240,
|
|
speed=0, audio_mode="encode", audio_encoder="libopus", audio_channels=2, subtitles=False)
|
|
out = run(info, opts, [a.index for a in info.audio], tmp_path / "out.mkv")
|
|
assert out.video.codec == "hevc" and (out.video.width, out.video.height) == (426, 240)
|
|
assert [(a.codec, a.channels) for a in out.audio] == [("opus", 2), ("opus", 2)]
|
|
assert out.subtitles == []
|
|
|
|
|
|
def test_strip_audio_webm(sample, tmp_path):
|
|
info = probe(TOOLS.ffprobe, sample)
|
|
opts = Options(container="webm", video_mode="auto", video_encoder="libvpx-vp9", speed=0, audio_mode="strip")
|
|
out = run(info, opts, [], tmp_path / "out.webm")
|
|
assert out.video.codec == "vp9" and out.audio == []
|
|
assert [s.codec for s in out.subtitles] == ["webvtt"]
|