mirror of
https://github.com/wiltodelta/remove-ai-watermarks.git
synced 2026-10-14 21:40:47 +02:00
Extend the development-only benchmark family from images to audio and video, and close four research directions from the watermark-landscape map with local, revision-pinned evidence. Benchmark schema: media_type audio and video rows, audioseal and videoseal adapters with media-checked adapter binding, sample-domain audio fidelity (SNR with unbounded_identical), frame-domain video fidelity (mean PSNR, changed-frame fraction), and per-frame temporal evidence in videoseal detection records. The report accepts all three media types and carries SNR columns. Audio: shared pinned AudioSeal oracle, synthetic and system-voice speech cohorts with matched negatives, codec, noise, removed, and forged arms, and the provenance experiment proving visual-only video cleaning leaves the audio bitstream and watermark verdict invariant. Video: TorchScript-only VideoSeal oracle (the pip package is unusable on macOS arm64 and its loader resolves paths relative to cwd), video cohort with crf/scale/fps attacks and four-state arms, temporal evaluation measuring the crf decay curve, the frame-aggregation matrix (computed locally after finding the TorchScript build ignores the aggregation argument), and real provider clips as carriers. Forgery: double-embedding study showing the last writer wins completely under both oracles, scoped remover-trace probe, and the forged/ removed cohort arms encoding each scheme's correct expected verdict (presence rule for audioseal, message rule for videoseal). C2PA resolution: measured the five vendors' resolver contracts and the C2PA 2.2 18.10.5 privacy gradient; product decision recorded that this tool never resolves over the network. A registry guard pins the published resolution-API set. Gate: ruff and pyright src/ clean, 2114 passed / 3 skipped; maintain.sh stops only on the known unfixed lightning 2.6.5 CVEs, pre-existing.
42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
"""Tests for the shared AudioSeal oracle's pure helpers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
SCRIPTS = Path(__file__).resolve().parents[1] / "scripts"
|
|
if str(SCRIPTS) not in sys.path:
|
|
sys.path.insert(0, str(SCRIPTS))
|
|
|
|
from audioseal_oracle import SAMPLE_RATE, window_bounds # noqa: E402
|
|
|
|
|
|
class TestWindowBounds:
|
|
def test_exact_multiple_covers_every_sample_once(self) -> None:
|
|
bounds = window_bounds(32_000, 1.0, SAMPLE_RATE)
|
|
|
|
assert bounds == [(0, 16_000), (16_000, 32_000)]
|
|
|
|
def test_trailing_remainder_keeps_its_own_window(self) -> None:
|
|
bounds = window_bounds(32_500, 1.0, SAMPLE_RATE)
|
|
|
|
assert bounds[-1] == (32_000, 32_500)
|
|
assert len(bounds) == 3
|
|
|
|
def test_short_signal_is_one_partial_window(self) -> None:
|
|
assert window_bounds(100, 1.0, SAMPLE_RATE) == [(0, 100)]
|
|
|
|
def test_empty_signal_has_no_windows(self) -> None:
|
|
assert window_bounds(0, 1.0, SAMPLE_RATE) == []
|
|
|
|
@pytest.mark.parametrize(
|
|
("total", "window_s", "rate"),
|
|
[(-1, 1.0, 16_000), (100, 0.0, 16_000), (100, -1.0, 16_000), (100, 1.0, 0), (100, 0.00001, 16_000)],
|
|
)
|
|
def test_rejects_degenerate_arguments(self, total: int, window_s: float, rate: int) -> None:
|
|
with pytest.raises(ValueError, match=r"total_samples|window_s|sample_rate"):
|
|
window_bounds(total, window_s, rate)
|