mirror of
https://github.com/wiltodelta/remove-ai-watermarks.git
synced 2026-08-09 23:50:40 +02:00
Make the video SynthID operating point measurable and hard to move silently
The shipped profile was certified by one oracle row, but only noise_std was pinned: long_side and fps -- two thirds of what the verifier was actually shown -- could move with a green suite. The test now derives the pin from data/evaluations/video-synthid-oracle.csv, so a default without a certifying row fails. The certified profile is a perturbation-to-signal ratio, not a bare noise_std. sd-vae-ft-mse publishes no scaling_factor key, so 0.18215 comes from the AutoencoderKL class default under an upper-unbounded diffusers pin. The loader now gates that value, carries it on VideoVaeRuntime, and passes it into encode and decode so the validated value is the applied value. video_synthid_sweep.py loads through the same function: the harness producing the certified rows was the one path exempt from the gate it exists to feed. psnr_db is measured against the already-resized frame and before the encoder, so it cannot see the downscale, the decimation, or the codec, and no in-loop metric can. scripts/video_fidelity_probe.py scores the delivered file end to end, streaming the way the engine does and sharing its frame-selection rule rather than copying it -- a frame-count check cannot catch a rule that reorders frames without changing how many. The manifest gains source geometry, vae, track, verbatim verdict and session fields. The two 2026-07-31 rows keep them empty: they were never recorded and are not recoverable. Verdicts now have four states, because the verifier's unclear reading logged as not_detected is the silent regression the manifest exists to prevent. docs/video-synthid-quality-research.md records the research behind this: the noise axis is worth about 2 dB and is nearly exhausted, resolution is the real prize but is an uncertified destruction axis rather than a free win, and every proposed autoencoder swap was refuted. First local measurements included. Verified: engine output is byte-identical before and after the refactor on a locally built clip, at noise_std 0.00 and 0.15. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f481e6f944
commit
8fe0b0110f
@@ -2,20 +2,27 @@
|
||||
|
||||
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_NOISE_STD
|
||||
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 pathlib import Path
|
||||
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,
|
||||
@@ -281,8 +288,36 @@ def test_probe_video_timestamps_uses_best_effort_pts(
|
||||
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_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:
|
||||
|
||||
Reference in New Issue
Block a user