"""Regression tests for the video SynthID removal engine.""" from __future__ import annotations import csv import sys import threading from pathlib import Path 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_FPS, DEFAULT_VIDEO_SYNTHID_LONG_SIDE, DEFAULT_VIDEO_SYNTHID_NOISE_STD, ) if TYPE_CHECKING: from typing import BinaryIO ORACLE_MANIFEST = Path(__file__).resolve().parents[1] / "data" / "evaluations" / "video-synthid-oracle.csv" 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_shipped_defaults_match_a_certified_manifest_row() -> None: """The shipped operating point must be one the provider oracle actually cleared. Pinning the constant alone was not enough. Only ``noise_std`` was asserted, so ``long_side`` and ``fps`` could move to an uncertified geometry with a green suite -- and they are two thirds of what the oracle was shown. Reading the manifest ties all three to the evidence: raising the resolution or the frame rate now fails here until a ``not_detected`` row exists for that exact triple. The tuple stops at three fields because the model is a fourth thing the oracle was shown and neither tracked row records it. That omission is data-driven: add ``vae`` here in the same commit as the first row that records one. """ with ORACLE_MANIFEST.open(newline="", encoding="utf-8") as stream: certified = { (float(row["noise_std"]), int(row["long_side"]), float(row["fps"])) for row in csv.DictReader(stream) # The manifest deliberately leaves unrecorded fields empty, so a row # missing part of its configuration certifies no triple and is skipped # rather than crashing the parse. if row["output_verdict"] == "not_detected" and all(row[field] for field in ("noise_std", "long_side", "fps")) } assert certified, f"{ORACLE_MANIFEST.name} records no fully configured certified row" shipped = (DEFAULT_VIDEO_SYNTHID_NOISE_STD, DEFAULT_VIDEO_SYNTHID_LONG_SIDE, DEFAULT_VIDEO_SYNTHID_FPS) assert shipped in certified, ( f"shipped (noise_std, long_side, fps)={shipped} has no certified row in " f"{ORACLE_MANIFEST.name}; certified: {sorted(certified)}" ) 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]