"""Regression tests for the video SynthID removal engine.""" from __future__ import annotations import sys import threading from types import SimpleNamespace from typing import TYPE_CHECKING, cast import pytest from remove_ai_watermarks import optional_deps, video_encoding, video_invisible from remove_ai_watermarks.video_synthid import DEFAULT_VIDEO_SYNTHID_NOISE_STD if TYPE_CHECKING: from pathlib import Path from typing import BinaryIO def test_encoder_redirects_large_stderr_while_frames_are_streaming( tmp_path: Path, caplog: pytest.LogCaptureFixture, ) -> None: diagnostic = "synthetic ffmpeg diagnostic" tail_diagnostic = "synthetic ffmpeg diagnostic tail" caplog.set_level("INFO", logger=video_encoding.__name__) command = [ sys.executable, "-c", ( "import sys; " f"sys.stderr.buffer.write({diagnostic.encode()!r} + b'x' * 262144 + {tail_diagnostic.encode()!r}); " "sys.stderr.buffer.flush(); " "sys.stdin.buffer.read(); " "raise SystemExit(7)" ), ] encoder = video_encoding.start_raw_video_encoder(command) write_finished = threading.Event() write_errors: list[Exception] = [] def write_frames() -> None: try: encoder.stdin.write(b"f" * 262144) encoder.stdin.flush() except Exception as exc: # pragma: no cover - mutation cleanup path write_errors.append(exc) finally: write_finished.set() writer = threading.Thread(target=write_frames) writer.start() try: assert write_finished.wait(5), "stderr backpressure blocked the frame producer" assert write_errors == [] with pytest.raises(RuntimeError, match=diagnostic): video_encoding.finish_raw_video_encoder( encoder, tmp_path / "unused.mp4", operation="synthetic encode", ) assert "ffmpeg stderr truncated" in caplog.text assert tail_diagnostic in caplog.text finally: video_encoding.abort_raw_video_encoder(encoder) writer.join(timeout=5) def test_availability_requires_both_optional_packages(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setattr( optional_deps, "module_available", lambda *names: set(names) <= {"torch"}, ) assert video_invisible.is_available() is False def test_regeneration_rejects_noise_outside_unit_interval(tmp_path: Path) -> None: with pytest.raises(ValueError, match="between 0 and 1"): video_invisible.regenerate_video_candidate( tmp_path / "source.mp4", tmp_path / "candidate.mp4", noise_std=1.01, ) def test_encoder_and_mux_commands_separate_streaming_frames_from_source_audio( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: source = tmp_path / "source.mp4" output = tmp_path / "candidate.mp4" monkeypatch.setattr(video_encoding.shutil, "which", lambda _name: "/usr/bin/ffmpeg") profile = video_encoding.VideoEncodeProfile( pixel_format="yuv420p", color_range="tv", color_space="bt709", color_transfer="bt709", color_primaries="bt709", time_base="1/90000", ) command = video_encoding.raw_video_command( output, width=8, height=8, fps=2.0, crf=18, profile=profile, ) metadata_index = command.index("-map_metadata") assert command[metadata_index + 1] == "-1" output_pixel_format_index = command.index("-pix_fmt", command.index("-c:v")) assert command[output_pixel_format_index + 1] == "yuv420p" assert command[command.index("-color_range") + 1] == "tv" assert command[command.index("-colorspace") + 1] == "bt709" assert command[command.index("-color_trc") + 1] == "bt709" assert command[command.index("-color_primaries") + 1] == "bt709" assert command[command.index("-enc_time_base:v") + 1] == "1/90000" assert command[command.index("-video_track_timescale") + 1] == "90000" assert command[command.index("-x264-params") + 1] == ( "colorprim=bt709:transfer=bt709:colormatrix=bt709:range=limited" ) assert "pipe:0" in command assert str(source) not in command assert command[command.index("-map") + 1] == "0:v:0" assert command[command.index("-fps_mode") + 1] == "passthrough" assert "-shortest" not in command calls: list[list[str]] = [] def fake_run(mux_command: list[str], **_kwargs: object) -> SimpleNamespace: calls.append(mux_command) return SimpleNamespace(returncode=0, stdout="", stderr="") monkeypatch.setattr(video_encoding.subprocess, "run", fake_run) encoded_video = tmp_path / "encoded.mp4" video_encoding.mux_encoded_video( encoded_video, source, output, strip_metadata=True, ) mux_command = calls[0] assert mux_command.index(str(encoded_video)) < mux_command.index(str(source)) assert mux_command[mux_command.index("-map") + 1] == "0:v:0" second_map = mux_command.index("-map", mux_command.index("-map") + 1) assert mux_command[second_map + 1] == "1:a?" assert mux_command[mux_command.index("-c") + 1] == "copy" assert mux_command[mux_command.index("-map_metadata") + 1] == "-1" assert "-shortest" not in mux_command def test_mux_reports_bounded_disk_backed_stderr( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture, ) -> None: diagnostic = b"synthetic mux diagnostic" tail_diagnostic = b"synthetic mux diagnostic tail" caplog.set_level("INFO", logger=video_encoding.__name__) monkeypatch.setattr(video_encoding.shutil, "which", lambda _name: "/usr/bin/ffmpeg") def fake_run(_command: list[str], **kwargs: object) -> SimpleNamespace: stderr = cast("BinaryIO", kwargs["stderr"]) stderr.write(diagnostic + b"x" * 262144 + tail_diagnostic) stderr.flush() return SimpleNamespace(returncode=7) monkeypatch.setattr(video_encoding.subprocess, "run", fake_run) with pytest.raises(RuntimeError, match=diagnostic.decode()): video_encoding.mux_encoded_video( tmp_path / "encoded.mp4", tmp_path / "source.mp4", tmp_path / "output.mp4", strip_metadata=True, ) assert "ffmpeg stderr truncated" in caplog.text assert tail_diagnostic.decode() in caplog.text def test_timestamped_encoder_reads_nut_and_passes_pts_through( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: output = tmp_path / "candidate.mp4" monkeypatch.setattr(video_encoding.shutil, "which", lambda _name: "/usr/bin/ffmpeg") command = video_encoding.raw_video_command( output, width=8, height=8, fps=24.0, crf=18, profile=video_encoding.VideoEncodeProfile(time_base="1/90000"), timestamped_input=True, copy_input_timestamps=True, ) assert "-copyts" in command assert command[command.index("-f") : command.index("-f") + 4] == [ "-f", "nut", "-i", "pipe:0", ] assert command[command.index("-fps_mode") + 1] == "passthrough" assert command[command.index("-avoid_negative_ts") + 1] == "disabled" assert command[command.index("-enc_time_base:v") + 1] == "1/90000" def test_probe_encode_profile_preserves_supported_8_bit_properties( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: source = tmp_path / "source.mp4" source.write_bytes(b"video") monkeypatch.setattr(video_encoding.shutil, "which", lambda _name: "/usr/bin/ffprobe") monkeypatch.setattr( video_encoding.subprocess, "run", lambda *_args, **_kwargs: SimpleNamespace( returncode=0, stdout=( '{"streams":[{"pix_fmt":"yuvj422p","color_range":"tv",' '"color_space":"bt709","color_transfer":"bt709",' '"color_primaries":"bt709","time_base":"2/180000",' '"start_pts":180000,"bits_per_raw_sample":"8"}]}' ), stderr="", ), ) profile = video_encoding.probe_video_encode_profile(source) assert profile == video_encoding.VideoEncodeProfile( pixel_format="yuv422p", color_range="tv", color_space="bt709", color_transfer="bt709", color_primaries="bt709", time_base="1/90000", start_pts=180000, source_pixel_format="yuvj422p", component_depth=8, ) def test_probe_encode_profile_uses_compatible_defaults_without_ffprobe( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: monkeypatch.setattr(video_encoding.shutil, "which", lambda _name: None) assert video_encoding.probe_video_encode_profile(tmp_path / "source.mp4") == (video_encoding.VideoEncodeProfile()) def test_probe_video_timestamps_uses_best_effort_pts( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: source = tmp_path / "source.mp4" source.write_bytes(b"video") monkeypatch.setattr(video_encoding.shutil, "which", lambda _name: "/usr/bin/ffprobe") monkeypatch.setattr( video_encoding.subprocess, "run", lambda *_args, **_kwargs: SimpleNamespace( returncode=0, stdout="0.000000\n0.041667\n", stderr="", ), ) assert video_encoding.probe_video_timestamps(source) == (0.0, 0.041667) def test_default_noise_matches_full_clip_oracle_floor() -> None: assert DEFAULT_VIDEO_SYNTHID_NOISE_STD == 0.15 def test_stream_batches_consumes_only_one_batch_ahead() -> None: consumed: list[int] = [] def values(): for value in range(5): consumed.append(value) yield value batches = video_invisible._stream_batches(values(), 2) assert next(iter(batches)) == [0, 1] assert consumed == [0, 1]