Robustness baseline

Read this if you integrate or evaluate Laidline's watermarks and need to know which edits a mark survives, why the others break it, and what a decode-side fix could recover. You will get the measured survival rates per medium, the mechanism behind each failure and the headroom before anything has to be re-embedded. Skip if you want the full result tables (Benchmarks) or how a result becomes a grade (Grading). Time: 20 minutes for sections 1 to 3; the rest is reference. Needs: nothing; pip install laidline-bench reruns the suites.

In short

  • A mark survives compression, resizing, mild crops, tone edits and codecs; it does not survive large crops, rotation, screenshots, tempo or pitch changes, heavy video compression or a paraphrase.
  • Every failure is traced to a mechanism (a whole-frame resize, a 20 ms bit grid, an equal-weight average, a global z-test), so several gaps are decode-side and can be closed without re-marking existing assets (section 5 separates them from the ones that need a new embedding).
  • Rates come with Wilson 95 percent intervals; read small samples (music n=30, video n=43) as coarse.
  • Oracle rows are not product numbers: they estimate what a perfect resync could recover.
  • Only benign edits are in scope; adversarial removal is not.

What each Laidline watermark survives today, why the failures happen, and how much a decode-side fix could recover before anything is re-embedded. The numbers come from the suites in laidline-bench (laidline bench --help). The full per-medium tables are in Benchmarks. Benign edits only: adversarial removal is out of scope.

New images are marked with PixelSeal by default (watermark.image.scheme: pixelseal); the image numbers below are TrustMark's, the scheme PixelSeal replaced. What the PixelSeal scheme survives with the product's decoder, its unmarked-photo test, the analytic false-accept bound, the real-screenshot measurement and its timings are in Grading, "PixelSeal image scheme" (module laidline_bench.pixelseal_product).

  1. How to read the numbers
  2. How each pipeline works
  3. Cross-media matrix
  4. Root causes
  5. Headroom and the hardening items
  6. Corrections and caveats recorded

1. How to read the numbers

The runs

medium scheme corpus and n device package in compliance/data/
image TrustMark 0.9.2, BCH_5, 61-bit payload; Q, B and C each forced COCO val2017, 500 photos (seed 0); after the 38 dB PSNR floor Q n=493, B n=484, C n=438; sweeps on the first 100 (Q 98, B 98, C 87) cuda robustness.json
image, unmarked detect's Q/B/C chain (TrustMark), earlier run COCO val2017, 5,000 unmarked photos cuda phantom.json
unmarked, all media (2026-10 null campaign) the shipped defaults: PixelSeal default reads and keyed, TrustMark, VideoSeal unkeyed and keyed, keyframe TrustMark, AudioSeal unkeyed and keyed, SynthID-style and KGW text 38,500 photos, 4,854 clips of 5 s, 5,000 each of single utterances, 30 s and 120 s joins, 4,979 music clips, 20,000 documents per scheme; blind positives of issuer 1 cuda for image, video and audio; text on cpu none: published in benchmarks
audio AudioSeal 0.2.0, 16-bit issuer payload; batch and streaming (block) LibriSpeech test-clean speech n=500, Goldberg music n=30 (seed 0); sweeps on the first 100 speech clips and the 30 music clips; Twilio: 100 recorded calls cuda audio_robustness.json
video VideoSeal 1.0 @870ca7f (92-bit payload, BCH t=16); keyframe TrustMark (one IDR frame per 1 s) 43 Xiph derf clips of 5 s (keyframes: 2 skipped, so n=41 marked); sweeps on all clips VideoSeal cuda:0, keyframes cpu video_robustness.json
text SynthID (temperature 1.0), KGW (temperature 1.0), KGW (greedy) Qwen/Qwen2.5-0.5B-Instruct, 200 C4 realnewslike prompts per arm (50-token prefix, up to 300 new tokens), 500 human C4 continuations; sweeps on the first 100 prompts cuda text_robustness.json
  • Every run: RTX 5080, torch 2.14.0+cu130, TF32 off for matmul and cuDNN, cuDNN deterministic, cuDNN benchmark off (the machine block of each result; the product's default, watermark.cuda_precision: strict), with two exceptions: the video keyframe scheme ran on the CPU, and the phantom run's machine block does not record the TF32 and cuDNN flags (the bench turns TF32 off on cuda).
  • The per-item records and the decoders' soft outputs (*.arrays.npz) are kept with the original runs and are not part of the package; with them soft voting, windows, offsets and thresholds can be evaluated offline without a re-run, and only a new embedding needs a new run. The packages in compliance/data/ ship the rates, the sweeps and "Where it breaks", not the per-item data.

Rates, intervals and small samples

Every rate comes with its Wilson 95% interval. With small n the interval matters more than the rate:

n all items pass reads as at least where
493 100.0% 99.2% image main rows, variant Q
500 100.0% 99.2% audio speech main rows
200 100.0% 98.1% text main rows
100 100.0% 96.3% audio speech and text sweeps
98 100.0% 96.2% image sweeps, Q and B
43 100.0% 91.8% video, VideoSeal
30 100.0% 88.6% audio music
  • Music n=30: a single clip is 3.3% of the corpus. Read music rows as coarse.
  • Video n=43 (41 for keyframes): one clip moves a rate from 100.0% to 97.7%, and 0 of 43 unmarked clips bounds the false-positive rate only below 8.2%. n=43 is the robustness sample; the false-positive evidence is the 2026-10 null campaign's 4,854 unmarked clips (upper bound 0.079%).
  • Text sweeps n=100 and image sweeps n=98: a sweep point locates a break, not a precise rate.

Operating points and false positives

medium what counts false positives, 2026-10 null campaign (current) earlier run, kept as a dated record
image, PixelSeal (the default) the exact 61-bit payload from the default reads; keyed: a verified tag presence 0 of 38,500 unmarked photos (Wilson upper bound 0.0100 %); keyed tag accepted 0 of 38,500 (0.0100 %); 0 of 2,200 screenshots of unmarked photos (0.174 %); no read of any configuration, TrustMark's included, presented one of the 40,700 photos and screenshots as marked (benchmarks) 0 of 5,000 COCO val2017 photos (upper bound 0.077 %)
image, TrustMark detect's Q/B/C chain returns the exact 61-bit payload; a registry hit also needs the query's bytes or a pHash within 10 bits of the evidence entry no hits in the campaign set, as above chain phantom rate on 5,000 unmarked photos: 8 of 5000, 0.16% (0.081% to 0.32%); per variant Q 1, B 5, C 2. This bench's own unmarked originals: 2 of 500 (0.4%, 0.11 to 1.4%), both from B
audio, unkeyed (16-bit mark) public presence at the shipped threshold 0.5; the issuer is never named single utterances 9 of 5,000 (0.18 %, upper bound 0.34 %), 30 s joins 4 of 5,000 (0.08 %, 0.21 %), 120 s joins 12 of 5,000 (0.24 %, 0.42 %), music 361 of 4,979 (7.25 %, 8.00 %), over the 0.5 % line; sounds 191 of 5,000 (3.82 %), synthetic speech 2 of 2,000 (0.10 %) (benchmarks) 0.75% of n=530 unmarked clips at 0.39 (0.29 to 1.9%); 0.38% at 0.5
audio, keyed (audioseal-p70-r1) a verified tag; public presence under the streaming-card rule tag accepted 0 of 5,000 per speech stratum and 0 of 4,979 music (upper bound 0.077 %), 0 of 26,979 in all; public presence 0 on speech, music 2 of 4,979 (0.15 %), sounds 15 of 5,000 (0.49 %)
video, VideoSeal the exact 92-bit payload after BCH (t=16) and the CRC-16 presence 0 of 4,854 unmarked 5 s clips (upper bound 0.079 %); keyed tag accepted 0 of 4,854 (0.079 %); a uniformly random read passes with probability 2^-60.9 (benchmarks) 0 of 43 unmarked clips (0 to 8.2%); 0 of 1,740 keyed (upper bound 0.22 %); a uniformly random read passes with probability 2^-64.4 (the earlier, optimistic figure)
video, keyframes the majority payload of the TrustMark reads, keyed: a verified tag tag accepted 0 of 4,854 (0.079 %) 0 of 43 unmarked clips (0 to 8.2%)
text p < 0.001 from one z-test over the text for presence; grade B at p < 1e-5 over at least 200 tokens (KGW: tokens covered by distinct n-grams, exact binomial tail) grade B 0 of 40,000 reads (20,000 documents per scheme, upper bound 0.02 % per scheme); presence KGW 32 and SynthID-style 19 of 20,000; the gate was chosen on the same documents, so this is not a held-out result (benchmarks) human C4: SynthID 1 of 500 (0.2%, z max 3.31), KGW 0 of 500; unmarked generations: SynthID 1 of 200 (0.5%, z max 3.54), KGW 0 of 200 in both arms. Guard: binomial bound on the 0.1% limit, PASS (section 6). At the earlier 1e-3 grade B gate the campaign's 20,000 documents per scheme gave 19 SynthID-style and 32 KGW

Audio columns: "detected" is the detector score at or above the threshold; "exact" is detected with all 16 issuer bits right, which is what detect needs to name the issuer. Image and video rates are exact decodes; text rates are p < 0.001 unless the column says grade B.

Oracle rows

An oracle row applies the true inverse of an attack before decoding: the true rotation angle, the true crop position on a mid-grey canvas of the original size, the photo's true box on a screenshot, a trim rounded up to a whole 20 ms audio block, a video crop padded back at its true offset. They are not product numbers. They estimate what a perfect decode-side resync could recover, so an oracle far above its attack says "search at decode time", and an oracle near its attack says "the mark itself is gone; change the embedding".

  • The crop oracles (image centre and corner crop, video crop) are not guaranteed ceilings. The grey canvas blanks the area the crop lost, while the plain crop keeps its content at a new scale (TrustMark and VideoSeal resize the whole frame), so an oracle can fall below its attack. The image bench flags such points; in this run there were none (an earlier small pilot had one, at corner crop 80). Treat crop oracles as estimates.
  • Text has no oracle rows.

Sweeps and "Where it breaks"

Each sweep reruns one attack family over a parameter ladder on a seeded subsample, with the same metrics as the main rows. Its "Where it breaks" row reads:

column meaning
holds >= 90% up to the harshest parameter, going from mild to harsh, at which the rate is still at least 90%
holds >= 50% up to the same at 50%
oracle ceiling the oracle curve at the same points, where one exists
margins at first failing point how far the failing items missed (below)
hint a heuristic from the margins and the oracle, never a measurement

Margins, per medium:

medium decoded near mid far
image (100 raw bits, BCH_5 t=5) <= 5 bit errors <= 10 <= 25 above 25
video, VideoSeal (248 codeword bits, t=16) <= 16 <= 32 <= 62 above 62
video, keyframes (100 bits, t=5; the averaged vote) <= 5 <= 10 <= 25 above 25
audio (16 bits, no ECC) 0 errors 1 to 2 3 to 4 5 or more
text (z of the p < 0.001 test) p < 0.001 at least half the z needed a quarter below

Hints: mostly near suggests soft voting or a stronger ECC; mostly mid or far with an oracle of at least 80% suggests a resync search; mostly far with a low or no oracle suggests an embedding change. Text uses "more evidence" (near) and "windowed scoring" (embed) instead.

2. How each pipeline works

Paths are inside the installed laidline package unless they start with trustmark/ or audioseal/ (the installed trustmark 0.9.2 and audioseal 0.2.0). Line numbers refer to the source that was measured and can shift between releases.

Image: TrustMark 0.9.2

stage what happens where
payload 61 bits, version:3 | issuer_id:22 | asset_seq:36, under BCH_5 (5 correctable errors); the 100-bit packet adds 35 parity bits and 4 version bits watermark/payload.py:1, :16
embed Q first, then B, then C, keeping the first variant above the 38 dB PSNR floor watermark/image/trustmark.py:115-137
where the mark lives one 256x256 residual from the encoder, colour-shift removed, upsampled over the whole frame (or over the centre square when the aspect ratio is above 2) and added to the pixels trustmark/trustmark.py:465-507, :201-241 (ASPECT_RATIO_LIM 2.0 at :70)
sign and log fingerprint phash64/v1, C2PA manifest and signature, evidence entry core/api.py:594-707, c2pa/sign.py:133
detect decode_variant resizes the whole frame to 245x245, thresholds the 100 decoder outputs at 0 and runs BCH on the hard bits; decode tries Q, B and C in turn watermark/image/trustmark.py:138-157, :166-172; trustmark/trustmark.py:121
schema bits trustmark reads the schema from raw bits 98 and 99, which sit outside the BCH trustmark/datalayer.py:64
not used TrustMark's ROTATION (a 0/90/180/270 search) and DETECTFIRST (a box localiser) trustmark/trustmark.py:401-448
registry confirmation a hit counts only when the query's bytes match, or its pHash (of the whole query) is within fingerprint_max_distance 10 detect/watermark_check.py:56-115, core/config.py:361

A recovered crop would still be fingerprinted whole, so it would likely land at grade C (the pHash distance of crops is not measured; in keyed mode that C is on the full tier only, the public tier shows D or nothing): hardening a crop decode also means changing confirmation.

Audio: AudioSeal 0.2.0

stage what happens where
payload a bare 16-bit issuer id: no version, no CRC, no ECC watermark/payload.py:111
batch embed the mono mid-signal is resampled to 16 kHz, generator_base computes the residual there, the residual is resampled back and added at the native rate watermark/audio/audioseal.py:206-228
streaming embed (block) each 20 ms (320 samples at 16 kHz) block is marked on its own with generator_streaming and added a whole number of blocks later; below 16 kHz the stream passes unmarked watermark/audio/audioseal.py:261-364
detect mono at 16 kHz through detector_base, then detector_streaming; detected when the score reaches detect_threshold (default 0.5) watermark/audio/audioseal.py:230-254, core/config.py:191
score prob is the share of samples whose per-sample score is above 0.5 audioseal/models.py:413-418
bits the sign of the whole-clip mean of the per-sample bit logits, read against a 20 ms grid anchored at the first sample audioseal/models.py:420-430; watermark/audio/audioseal.py:21-23
loudness AudioSeal's NormalizationProcessor is built only when a checkpoint's config asks for it; all four Laidline checkpoints load with normalizer=None audioseal/builder.py:135-136, :152-153
limits detect refuses audio above 120 s (max_detect_duration_s); C2PA is written for wav, flac, mp3 and m4a only core/config.py:190; media/audio.py:37 (EMBEDDABLE_AUDIO)

Where the mark lives, from the filters (speech, 100 clips): the batch bits need the low band (high-pass 300 Hz leaves 88.0% exact, 500 Hz 1.0%, while detection stays at 100.0%) and survive a 4 kHz low-pass (99.0%). The streaming bits need the band above 6 kHz (low-pass 8 kHz leaves 99.0% exact, 6 kHz 0%). Streaming detection survives the bench's gentle two-pole filters (lowpass_4k and bandpass_phone: 100.0% detected, 0% exact) but not the brick-wall 8 kHz round trip or G.711 (0% detected), which is why a phone leg removes the unkeyed streaming mark. A keyed stream's payload reads through simulated G.711 (Audio).

Audio: the keyed P70 payload

In keyed mode the 16 bare bits above become audioseal-p70-r1 (Payload keys, "Audio"):

  • 70 bits under a BCH code (m = 7, t = 9);
  • spread over 1.0 s cells of an 8 s cycle;
  • read per 1.0 s segment on 20 ms grids and decoded per word (Chase-II p = 8);
  • one tag check per call.

That fixes two of the 16-bit failures in "Root causes" below. The whole-clip mean is replaced by per-segment reads with error correction. The grid problem is handled two ways: the default read (CPU) covers files whose start is intact on the 20 ms grid, and deep scanning (GPU, off by default) searches the phase for trims, offsets and excerpts. Under the hardened decode a span read also reads a mark inside a longer recording (measured at 9 s in 30 s, 12 and 24 s in 120 s) at the phase search's own coarse peaks (98, 93 through Opus 24 kbit/s, and 98 of 100 on fresh units; Grading). On 2 CPU threads it adds 0.02 s to a 120 s detect that reads at the first peak (the call is about 67 s, mostly the hardened decode) and about 2.9 s when all three phases are read. Measured on 200 fresh clips (Benchmarks, "Keyed audio payload"):

read result
default read 100 % through every binding codec except Opus at 12 kbit/s, which read 97.3 % (post-stratified, PASS)
deep scanning 200 of 200 on every binding row, trims and offsets included; Opus 12 kbit/s 94.0 % (best effort)

There were 0 wrong payloads and 0 own-accepts on 1,591 null clips and 1.2 million decoder-level nulls. Lines not met:

  • Third-party label on own marks (closed by the rule shipped, below): under the two-grid rule that ran, one own mark was labelled third-party at Opus 12 kbit/s under deep scanning, and the same one-word mechanism showed on two more own marks in the forced reads. The rule now shipped needs the foreign head on three or more grids (chosen after that data; 0 of 31 such calls, no power). The powered measurement (3,000 of Laidline's own marks under foreign keys, each read scored as if no own payload had been chosen) failed its line (7 or more labels fail): the three-grid rule labelled 13 of 3,000 (the two-grid rule 80, R6' (two grids and two word positions) 21). The own payload was chosen on all 3,000 calls, so the product showed none of the 13 labels. The rule now shipped also needs each counted word to score at least 0.97, a floor chosen after that data and tested once on a fresh 3,000 own marks: 0 of 3,000 labelled (rate shown below 1 per 1,000), 2,999 of 3,000 own heads and 150 of 150 foreign marks kept; under Opus 12 kbit/s the product labelled 129 of 150 foreign marks, reported as measured (Payload keys, "Audio"; Benchmarks, "Third-party rule S97 and its hold-out"). Measured at full float32 with deterministic cuDNN, the shipped CUDA precision.
  • Timing: in the quiet re-time the default 3-grid reader met every CPU time line. Its 30 s miss in the first run was load. The 5-grid reader, which is not the default, missed at 12 s.
  • Timing (report only): one file-registry cell of the keyed audio timing check is unexplained and indicative. The measured channel stays within the bound stated in Payload keys residual 10 on every backend measured; the mitigations are the equal-work construction and the registry recommendation (the file registry is the development backend; production uses Postgres or S3).
  • Stream against file: the stream path read 3 more than the file path at Opus 12 kbit/s. The line failed by its letter; it was accepted after the data.
  • The 89-fresh-clip check of Opus 12 kbit/s on whole files is UNPROVEN at that size.
  • GPU against CPU, as shipped (rules pre-registered): Laidline runs its models on a GPU at full float32 with deterministic cuDNN (watermark.cuda_precision: strict, the default; Configuration). With decode: hardened and the keyed constants on both, the same 350 saved clips were read by the product on the GPU (the precision set by the product itself, as shipped under watermark.device: auto) and on the CPU. The clips are deliberately hard: short marks inside longer clips, codec cuts and unmarked clips that came near a threshold; they are not population rates. The line, 0 units differing in a decision (presence on either tier, payload, the chosen payload, grade, status, tag, third-party label, deep-scan stage and payload read), passed: 0 of 350.
    • The path that reported presence differed on 1 unit, a 0.5 s mark inside a 30 s clip: both devices showed it present, the CPU on the windowed path and the GPU on the located path. The two devices read it at the same phase, but they disagree on the clip's last seconds, where the mark is not: AudioSeal's detector carries a recurrent (LSTM) layer through the clip, and the tiny arithmetic differences between the CPU's and the GPU's float32 kernels grow along it: on this clip, from about 1e-9 in a frame's score in the first second to a few hundredths from 18 s on, and up to 0.76 in the last 5 s. Scores that drift across 0.5 there change the shares of windows that hold no mark: the best 1 s window on both devices lies there, at 0.81 of its samples on the CPU (over the 0.70 threshold: windowed) and 0.64 on the GPU (under it, so the GPU reported the 0.5 s window on the mark itself: located), and the CPU's best 0.5 s window, which centres the cell statistic, moved there too.
    • The cell statistic agreed within 1e-6 wherever both devices searched the same phase and cell span (226 of 256 compared). The phase or the span moved on the other 30, and 28 of those differed by more than 1e-4 (26 unmarked clips, 2 excerpts); none changed the cell gate's admission.
    • Before this setting, the GPU ran torch's default reduced-precision (TF32) convolutions. The same 350 clips measured that way: 9 differed, 4 of them in presence (3 short excerpts; 1 unmarked 30 s clip shown present on the GPU's full tier) and 1 on the public tier, 0 in payload, tag, grade B or third-party label. The decode compares shares of samples scored above 0.5, and a gate statistic, with fixed thresholds; where a share or the statistic sits near its threshold, a small arithmetic change decides it the other way.
    • Every published GPU figure for keyed audio detection (the cell gate's floor and hold-out counts, the excerpt rows, the third-party hold-out) was measured at full float32 with deterministic cuDNN, which is now what the product runs. The GPU records of this line are identical, field for field, to a full-precision run made with the bench's own switch (350 of 350), and the CPU records to that run's CPU records (350 of 350).
    • Full float32 does not make the two devices bit-equal on long clips (the recurrent layer above): GPU and CPU agree on decisions on these 350 clips, not on every statistic.

Audio: voice calls (the 2026-10 matrix)

The keyed buffered stream, simulated phone paths, read with the shipped defaults of 2026-10-27 (rows and method in Benchmarks: Voice calls; the rows a voice bot can rely on in Audio). What limits the payload, in the order it was found:

  • Length. Presence reads from 1.5 s delivered; the payload from 8.0 s delivered on the 20 ms grid (a stream fed 10 s delivers 9.5 s, since 0.5 s is held back at close). Claim 10 s.
  • Alignment. The default read counts 320-sample blocks from the first sample. An excerpt starting 1 to 319 samples off the grid read 6 of 100 (16 kHz) and 4 of 100 (24 kHz) against 100 of 100 on the grid; a pure delay of 2 to 480 samples that is not a whole block read 0 of 50. Presence survives (77 to 81 %). This is what fails G.722 (22-sample delay) and AMR-WB (95 samples), which read 50 of 50 and 48 of 50 once the delay is removed. The keyless phase search added after the run (Payload keys, "Audio") targets it; it is off by default (payload.phase_search) and was measured in the v2 matrix (Audio, "Voice calls").
  • Codecs that destroy the mark. Opus at 8 kbit/s (4 of 50 even aligned), Speex (0 of 50) and AMR-NB (28 of 50 aligned). The mark's residual sits under 4 kHz, 23.5 dB under the speech; bandwidth is not the cause.
  • Noise. White noise loses half the payloads at about 22 dB SNR; babble reads 94 % at 20 dB. Packet loss up to 10 % (repeat or zero fill) costs nothing measurable (100 of 100 per cell).
  • Rooms. At 0 dB direct-to-reverb ratio the payload is usually lost (3 to 13 % at RT60 0.1 to 0.5 s) and presence stays at 83 to 94 %; +6 dB reads 67 % and +12 dB 100 % at RT60 0.3 s. Reverb followed by G.711 reads 3 %.
  • Wrong payloads, not met. The line "0 wrong payloads" failed on 6 of 6,200 marked units (reverb, white noise at 20 dB, G.722), each with a failed tag and a payload of another issuer. No tier now shows a payload whose tag failed.

Video: VideoSeal 1.0 and the keyframe stopgap

stage what happens where
payload 92 bits, version:4 | issuer:24 | asset_seq:48 | CRC-16, under BCH(255, t=16) over 248 bits, padded to VideoSeal's 256-bit message watermark/video_ecc.py:1-5, :18
embed VideoSeal predicts the watermark on every 4th frame (at 256x256, from luma) and carries it to the next 3; the residual is JND-attenuated (it hides in texture) and added at full resolution; libx264 crf 18 in mp4 watermark/video/videoseal.py:69-85, core/video.py:212-313
audio track marked with the batch AudioSeal mark; never decoded at detect core/video.py:247-257, :316-328
detect up to 256 frames on a stride that is a multiple of 4, each resized to 256x256; the per-frame message logits are averaged with equal weight, then BCH and the CRC run core/video.py:656-712, watermark/video/videoseal.py:111-134
discarded the per-frame detection channel preds[:, 0]; there is no windowing or segment vote watermark/video/videoseal.py:118
keyframes TrustMark Q on one forced IDR frame per second; detect reads the key frames plus the marking positions and takes a hard majority vote of whole payloads (keyed mode: the keyed layout uses Q only to embed and read, through the hardened Q-only reader) watermark/video/keyframes.py:42-56, core/video.py:715-724 (decode_keyframes), :737 (_keyframe_candidates)

Text: statistical mark at generation time

stage what happens where
schemes SynthID tournament (ngram 5, depth 30) by default; KGW (green-list ratio 0.25, bias 2.0, context width 1, so bigrams) for greedy traffic; keys by HKDF-SHA256 core/config.py:160, watermark/text/keys.py:1-19
where marking happens during sampling: the vLLM logits processor (laidline-vllm) or generate_marked (laidline-transformers); the proxy only injects the key and records effectiveness server/proxy/text.py, core/api.py:857-927
where the mark lives in which tokens were chosen; an edit that changes a token also changes the context of the next n-gram
detect one z-test over the first max_detect_tokens tokens (8192; KGW at most 1024); present at p < 0.001 core/api.py:1022-1067, core/config.py:150-155, :170-172
KGW scoring each distinct n-gram counts once (repeated n-grams are skipped) watermark/text/kgw.py:92-126
grades present over at least 200 tokens is grade B (SynthID: the tokens, score.tokens; KGW: scored + context_width), else grade D detect/text_check.py:26-64
scope only the configured scheme and the default key are scored; there is no windowed scoring core/api.py:1051-1060

3. Cross-media matrix

Headline rates from the main rows. Audio cells read "detected / exact" at 0.39 when the two differ. A second value in a cell is the other mode or scheme named in the column header, where it differs. n/a: not applicable or not measured.

attack family image, Q (n=493) audio, speech batch (n=500); streaming video, VideoSeal (n=43); keyframes (n=41) text, SynthID t=1 (n=200); KGW
compression JPEG q50 96.8%; WebP q50 93.9%; JPEG q75 twice 98.8%; 256-colour palette 99.4% Opus 12 kbps 99.6% / 96.2%; G.711 mu-law 100.0%; MP3 64 100.0%; AAC 64 100.0%. Streaming: G.711 mu-law 0%; Opus 12 100.0% / 70.6% H.264 crf 23 93.0%, crf 28 53.5%, crf 35 14.0%; H.265 crf 28 27.9%; VP9 crf 33 83.7%; 1 Mbit/s cap 90.7%. Keyframes: crf 28 78.0% n/a (Unicode and whitespace normalisation: 100.0%; KGW 99.5%)
geometric rotate +2° 90.1%, -2° 93.1%; +5° 1.2%, -5° 2.6%; 90° 0%; centre crop 90% 100.0%, 75% 31.8%, 50% 0%; corner crop 75% 0%; resize 0.5 100.0%; aspect 0.8 93.9%; horizontal flip 100.0% tempo 0.9 1.4% / 0.2%, 1.1 2.0% / 0.6%; pitch +2 semitones 0.4% / 0%; speed 1.1 1.2% / 0%. Streaming: tempo 0.9 99.8% / 90.4%; pitch +2 100.0% / 0% rotate 5° 93.0%, 90° 95.3%; hflip 93.0%; centre crop 80% 62.8%; corner crop 80% 41.9%; rescale 0.5 62.8%. Keyframes: rotate 5° and 90° 0%; crop 80% 92.7%; rescale 0.5 90.2% n/a
framing and overlay 10% black border 0%; caption bar 99.6%; logo 100.0% n/a letterbox 34.9%; caption box 95.3%. Keyframes: letterbox 0%; caption box 82.9% n/a
tone and colour (audio: level and EQ) brightness x1.2 95.7%; contrast x0.7 100.0%; saturation 0 94.5%; gamma 1.5 99.8% volume -12 dB 100.0% / 99.8%; +6 dB clipped 100.0%; compressor 100.0%; phone band 100.0%; low-pass 4 kHz 100.0% / 98.8%. Streaming: phone band and low-pass 4 kHz 100.0% / 0% brightness and contrast 97.7%; greyscale 100.0%. Keyframes: 85.4% and 85.4% n/a
noise, blur and local edits noise sigma 5 100.0%; blur radius 2 99.6%; sharpen 100.0% white noise 20 dB SNR 76.6% / 57.6%; reverb 100.0% / 5.8%. Streaming: noise 100.0% / 99.2% n/a delete 30% of words 97.0%; swap 30% 94.0%; insert 10% 100.0%; typos 5% 100.0%. KGW: 99.5%, 99.5%, 100.0%, 99.0%
temporal and offset n/a trim 10 ms 100.0% / 0%; trim 1 s 100.0%; middle half kept 54.4% / 5.8%. Streaming: trim 10 ms 48.4% / 0% start trim 1.3 s 90.7%; middle 2 s 90.7%; every 10th frame dropped 97.7%; 15 fps 97.7%; speed x1.25 95.3%. Keyframes: both trims 0%; 15 fps 78.0% first 100 tokens kept 100.0% (grade B 0%); first 50 99.5%. KGW: 100.0%, 96.5%
splice and mix n/a marked half joined to an unmarked half 100.0% / 99.6% (88.2% detected at 0.5); music bed 10 dB below 41.8% / 11.6%. Streaming: splice 100.0% (2.6% at 0.5); music bed 100.0% / 100.0% first half of the frames marked 97.7%. Keyframes: 95.1% mark as 25% of a human text 100.0%. KGW t=1 98.0%; KGW greedy 17.0%
neural re-generation img2img not run EnCodec 6 kbps 70.8% / 0%; Mimi 1.0% / 0%. Streaming: EnCodec 100.0% / 0% n/a paraphrase by the same model 49.5%; EN-DE-EN translation 89.5%. KGW: 57.0%, 97.5%
capture screenshot (90% of a 1080p screen) 0% real Twilio call (n=100) 99.0% / 98.0% screen recording 69.8%. Keyframes: 0% n/a
unmarked (false positives), earlier runs; the 2026-10 null campaign's are in "Operating points and false positives" TrustMark chain 0.16% (n=5000); PixelSeal 0 of 38,500 in the campaign 0.75% at 0.39, 0.38% at 0.5 (n=530); unkeyed 0.18%, 0.08%, 0.24% (single, 30 s, 120 s) and music 7.25% in the campaign 0 of 43; 0 of 4,854 in the campaign human text 0.2% (1 of 500); KGW 0%; grade B 0 of 40,000 in the campaign

The KGW greedy arm (a small model decoding greedily) detects 95.0% at identity but reaches grade B on 1.0%: see section 4.

4. Root causes

Each failure traced to its mechanism, with the sweep that supports it. Rates are exact decodes (audio: issuer exact) unless marked "detected".

Image: the whole-frame resize and the hard BCH

symptom mechanism evidence (sweeps: Q n=98)
a small rotation is lost detect decodes the frame as it is; there is no rotation search, and the pattern turned by a few degrees misaligns with the decoder's grid rotation holds 90.8% at 2°, 42.9% at 3°, 15.3% at 4°, 1.0% at 5°, 0% from 7°; the oracle (rotate back by the true angle) is 100.0% at every angle up to 15°
a quarter turn is lost same; TrustMark's own ROTATION flag would try exactly these 90°, 180°, 270°: 0%; oracle 100.0%
a centre crop is lost from 75% the embed stretches one 256x256 pattern over the whole frame and detect squeezes the whole frame back to 245x245, so a crop is a rescale plus a shift of the pattern holds 100.0% at 80%; 35.7% at 75%; 0% from 70%. Oracle (the crop pasted back at its true position): 100.0% at 75%, 92.9% at 70%, 62.2% at 65%, 17.3% at 60%, 0% at 50%
a 50% crop is lost even by the oracle half of each side leaves too little of the one pattern for BCH_5, wherever it is placed oracle_crop_50 0% (n=493) although its raw bits rise from 50.6% to 82.1%
uniform scaling is fine the whole-frame resize makes the decoder scale-invariant scale 0.25 98.0%, 3 100.0%
a screenshot or a border is lost the photo fills only part of the frame the decoder squeezes, so the pattern shrinks and shifts screenshot fill from 90% to 30% of the screen: 0%; oracle (the photo's box cut out): 100.0% down to 45%, 96.9% at 30%. 10% border (pad_10): 0%
non-uniform squash breaks late a different scale per axis aspect 0.8 94.9%, 0.7 62.2% (37 far of 37 failing; the bench's hint says embedding change, but there is no oracle, and a decode-side aspect or scale search would undo a squash: a resync/search candidate, unmeasured)
compression and blur fail near the BCH radius hard decision on the 100 bits; 5 errors corrected, the sixth fails JPEG holds 92.9% at q35, 77.6% at q25 (14 near, 7 mid, 1 far of 22 failing), 31.6% at q15; blur radius 4 76.5%
some near misses are schema misses raw bits 98 and 99 pick TrustMark's schema and are outside the BCH, so one flipped schema bit fails a decode with at most 5 errors Q: JPEG at q25 (2), blur radius 4 (3), rotation at 3° (4); C: centre crop at 75% (8)

B and C tolerate rotation better than Q (at 5°: B 40.8%, C 28.7%; at 4°: B 81.6%, C 55.2%) and C tolerates the 75% crop better (74.7%). Horizontal flip survives on every variant (Q 100.0%); vertical flip is not a bench row, and a development probe found it does not decode.

Audio: the 20 ms bit grid and whole-clip averaging

symptom mechanism evidence (speech, batch, n=100)
any trim that is not a whole number of 20 ms blocks loses the issuer the 16 bits are read on a 20 ms grid anchored at the first sample; out of phase, bits flip while the score mostly survives start offset 0 ms and 20 ms: 100.0% exact; 1, 2, 5, 8, 10, 12, 15, 18, 30 and 50 ms: 0% exact. Detection stays 100.0% at 1, 2, 10, 20, 30 and 50 ms but drops to 53.0% at 5 ms, 37.0% at 8 ms and 61.0% at 12 ms. Oracle (trim rounded up to a whole block): 100.0% at every offset
the offset misses are close the phase error flips a few bits, not all at 1 ms: 59 near, 41 mid of 100 failing (streaming: 100 far)
the main rows the same grid trim_10ms 100.0% detected, 0% exact; oracle_trim_10ms 100.0% exact; middle half kept (cut off the grid) 54.4% detected, 5.8% exact
a short marked share is not detected prob is the share of marked samples over the whole clip, and the bits are a whole-clip mean, so unmarked audio dilutes both marked share 50%: 99.0% exact; 25%: 2.0% detected, 1.0% exact. Kept duration 0.5 s: 100.0% (a short clip is fine when it is all marked)
mixing costs the issuer before the score likely: the bed shifts the whole-clip bit means sooner than it pulls the per-sample score below 0.5 music bed 20 dB below: 99.0% detected, 79.0% exact; 15 dB: 84.0% / 40.0%; 10 dB: 37.0% / 9.0%
a 1% tempo change breaks the batch mark likely: the batch message rests on one alignment held across the whole clip, and a tempo change drifts it; the saved 100 ms time profiles can confirm it tempo 0.99: 18.0% detected, 17.0% exact; 0.98: 8.0% / 6.0%; 1.01: 19.0% / 18.0%. The streaming mark (each block marked on its own) holds 94.0% to 97.0% exact from 0.95 to 1.05
pitch and speed are lost resampling moves the content the detector reads; no oracle exists pitch -0.5 and +0.5 semitones: 1.0% and 0% detected; speed 0.98: 1.0%
near misses under noise and codecs 16 bare bits, no ECC, no redundancy noise 25 dB: 89.0% (11 near of 11 failing); Opus 10 kbps: 72.0% (9 near, 1 mid); low-pass 3 kHz: 63.0% (37 near); high-pass 300 Hz: 88.0% (12 near)
quiet audio loses the issuer no loudness normalisation before the detector volume -12 dB 100.0%; -20 dB 90.0% detected, 56.0% exact (40 near of 41 failing); -30 dB 3.0% detected
the unkeyed streaming mark dies on a phone leg its bits sit above 6 kHz; gentle two-pole filters keep detection (lowpass_4k, bandpass_phone: 100.0% detected, 0% exact), a brick-wall 8 kHz resample does not low-pass 8 kHz 99.0% exact, 6 kHz 0%; G.711 and the 8 kHz round trip 0% detected (n=500); keyed, the payload reads through simulated G.711 (Audio)

Music (n=30) repeats the batch pattern with a weaker issuer read: 83.3% exact with no change, 23.3% to 40.0% after Opus 10 to 24 kbps (mostly near: 22 near of 22 failing at 24 kbps), and no clip exact after a 1% tempo change.

Video: the equal-weight average and the BCH radius

symptom mechanism evidence (sweeps: n=43)
compression past crf 23 frames are averaged with equal weight, then 248 hard bits go to BCH with t=16; heavier compression pushes the averaged read past the radius H.264 crf 18 100.0%, 20 97.7%, 23 93.0%, 26 62.8%, 28 53.5%, 30 32.6%, 32 18.6%, 35 14.0%, 40 4.7%
the first failures are near the radius the signal is still there; a soft decoder or a stronger code would take them crf 26: 13 near, 4 mid of 17 failing; crf 23: 3 near of 3; VP9 crf 33: 7 near of 7; social re-encode: 11 near, 5 mid of 16
heavy compression removes the mark mostly far misses: likely beyond a decode-side fix crf 35: 2 near, 8 mid, 27 far of 37 failing; H.265 crf 28: 17 far of 31
more frames help averaging gains over a quarter of the frames, so frame selection and weighting matter exact on the first 25% of frames against all frames: crop 80% 34.9% against 62.8%; screen recording 51.2% against 69.8%; crf 28 48.8% against 53.5%
crops, bars and screen capture the whole frame is resized to 256x256, as in TrustMark centre crop holds 93.0% at 90%, 86.0% at 85%, 62.8% at 80%, 7.0% at 70%; oracle 93.0% at 80%, 76.7% at 70%, 23.3% at 60%. Letterbox 34.9%, screen recording 69.8%
downscaling likely: fewer pixels carry each part of the pattern scale 0.6 90.7%, 0.5 62.8%, 0.33 18.6%
rotation and flips survive likely VideoSeal's training with geometric augmentations; the TrustMark keyframes need the pattern upright rotate 5° 93.0%, 10° 81.4%; 90° 95.3%; hflip 93.0%. Keyframes: 0% at 5° and 90°
keyframe trims the keyframe scheme reads fixed positions on a 1 s grid and votes whole payloads; a cut off the grid reads unmarked frames start trim 0.1, 0.3, 0.6, 1.5, 2.5 s: 0%; 1 s: 95.1%. Kept segments decode only when they start on a whole second (3 s: 95.1%, 1 s: 92.7%; 4, 2 and 0.5 s: 0% or 2.4%). 10 fps: 0%

VideoSeal margin counts (near, mid, far) can differ from the exact-decode rates by 1 to 2 clips: the 248-bit margin also counts the 28 zero-padding bits, which the decoder restores before BCH. The same holds for the VideoSeal margins in section 5.

VideoSeal splices hold (25% of the frames marked: 95.3%), so partial edits are not the weakness; compression and framing are. The keyframe scheme is more robust to compression and scale (crf 28 78.0%, scale 0.5 90.2%) but fails every edit that moves its grid.

Text: the global z-test and scheme-only scoring

symptom mechanism evidence
marked text inside human text is diluted one z-test over the whole scored window, no windows SynthID (window 8192 tokens holds the whole mark in 500 of 500 embed rows): embed share 10% still 100.0%. KGW t=1: 99.0% at 25%, 32.0% at 10%. KGW greedy: 64.0% at 75%, 29.0% at 50%, 16.0% at 25% (sweeps n=100)
KGW embed misses at 10% are the cap, not dilution KGW scores only the first 1024 tokens KGW t=1 at 10%: 65 of 68 failing items had none of the mark inside the window, 3 part of it; at 25%: 0 of 4
a text marked under another scheme or key is not scored detect scores only watermark.text.scheme with the default key known gap; no row measures it
short texts detect but do not grade p < 0.001 needs few tokens, grade B needs 200 SynthID: p < 0.001 reached by 200 of 200, median 9 tokens, p90 15; length 25 tokens 98.0% detected; grade B 98.0% at 200 tokens, 0% at 150. KGW t=1: median 13 tokens, p90 36; 94.0% at 50 tokens, 72.0% at 25; grade B 100.0% at 300 kept tokens, 0% at 200
greedy KGW grades D greedy decoding on a 0.5B model repeats itself, and KGW scores each distinct n-gram once, so a 300-token text has few scored tokens identity 95.0% detected, grade B 1.0%; scored mean 63 of 300 tokens; the 10 identity misses have distinct-bigram ratio 0.09 and repetition rate 0.91 (detected items 0.22 and 0.74)
heavy edits break the hashed n-grams an edit changes the context of the n-gram that follows; SynthID hashes 5-grams, KGW (context width 1) bigrams SynthID: delete 30% 97.0%, 40% 73.0%, 50% 30.0%; swap 30% 95.0%, 40% 38.0%; typos 10% 53.0%. KGW t=1: delete 50% 98.0%; swap 50% 79.0%; typos 10% 97.0%. Greedy KGW fails from 5% of words (delete 89.0%, insert 82.0%, swap 81.0%)
paraphrase a rewrite keeps few n-grams SynthID 49.5%, KGW t=1 57.0%, KGW greedy 30.5%

5. Headroom and the hardening items

Image: the targets (variant Q)

target now (n=493) oracle, main row oracle, sweep (n=98) decode-side search can reach it? fix
centre crop 50% >= 80% 0% oracle_crop_50 0% 0% at 50%; 62.2% at 65%; 92.9% at 70%; 100.0% at 75% the oracle estimate suggests search alone cannot reach it (it recovers 70 to 75%, not 50%; the crop oracle is not a guaranteed ceiling) tiled embedding (new embedding), plus multi-scale crop search and fingerprint confirmation for crops
rotation ±5° >= 90% 1.2% (+5°), 2.6% (-5°) oracle_rotate_+5 100.0% 100.0% at every angle up to 15° yes rotation search, including 90° steps
screenshot >= 80% 0% oracle_screenshot 100.0% 100.0% down to 45% fill, 96.9% at 30% yes canvas detection
compression unchanged JPEG q50 96.8%, WebP q50 93.9% re-run after every change
chain FPR <= 0.5% 0.16% (0.081% to 0.32%) fingerprint confirmation and a phantom re-run for every added search

Every extra decode attempt is another chance of a phantom. Each search is paired with fingerprint confirmation and a phantom re-run; the saved unmarked soft outputs (500 originals in the image run, 5,000 photos in the phantom run, 100 logits per decoder each) let a search's false-positive cost be estimated offline before it ships.

The hardening items, mapped to the evidence

Decode-side items change only detect: cheap, and they help assets that are already marked. Embedding items need a new mark: existing assets keep today's robustness, and every bench reruns.

item medium evidence kind
rotation search (small angles) image rotation Q at 3°: "resync/search candidate" (22 near, 31 mid, 3 far of 56 failing; oracle 100.0%) decode-side
quarter-turn search image quarter turns: 98 far of 98 failing, oracle 100.0% decode-side (TrustMark's ROTATION does it)
crop and scale search image, video image centre crop Q at 75%: "resync/search candidate" (13 near, 35 mid, 15 far of 63; oracle 100.0%); video crop 80%: 62.8% against oracle 93.0% decode-side
tiling image crop 50%: oracle 0% (raw bits 82.1%) new embedding
aspect or scale search image aspect 0.7: 62.2%, 37 far of 37, no oracle decode-side, unmeasured (a resync/search candidate)
canvas detection image; video (hypothesis) image screenshot fill: 98 far of 98, oracle 100.0%; pad_10 0%. Video letterbox 34.9% and screen recording 69.8% have no oracle and mixed margins: a hypothesis to test with an oracle row first decode-side (TrustMark's DETECTFIRST localiser is one option)
soft voting across variants and tiles, schema retry image JPEG Q at q25: "soft voting or stronger ECC candidate" (14 near of 22) plus 2 schema misses; "a fixed-schema decode fixes them" (Laidline accepts only BCH_5, so the schema bits can be ignored) decode-side
fingerprint confirmation for crops image, video detect fingerprints the whole query, so a recovered crop lands at grade C decode-side (detect)
audio offset search audio offset 1 ms: 59 near, 41 mid of 100; oracle 100.0% at every offset; streaming: 100 far, oracle 100.0% decode-side (a search over the 320 sample phases of a block)
audio windowed detection audio marked share 25%: 2.0% detected; the saved 100 ms time profiles allow it offline decode-side
loudness normalisation before decode audio volume -20 dB: 56.0% exact (40 near of 41); -30 dB: 3.0% detected decode-side
audio redundancy and a sync pattern audio tempo 0.99: 17.0% exact; pitch ±0.5 semitones and speed 0.98: at most 1.0% detected; no oracle new embedding
streaming mark in the phone band audio G.711 0%; low-pass 6 kHz 0% exact new embedding
temporal weighting and voting video more frames help (the first 25% of frames decodes less than all frames: crop 80% 34.9% against 62.8%); per-frame logits and preds[:, 0] are saved for it decode-side
soft-decision BCH or a stronger code video crf 26: 13 near, 4 mid of 17 failing decode-side for soft decoding; a stronger code is a new embedding
embedding strength video crf 35: 27 far of 37 new embedding
keyframe window scan video, keyframes start trim 0.1 s: 41 far of 41; decodes again at a whole-second trim (95.1%) decode-side (read every frame near each second)
windowed scoring text KGW t=1 embed 10%: "windowed scoring candidate" (6 near, 9 mid, 53 far of 68), 65 of 68 outside the 1024-token window; KGW greedy embed 75%: 24 near, 10 mid, 2 far of 36 decode-side
scoring every scheme and active key text known gap decode-side

Proposed targets where none is set

Proposed targets, each grounded in the curve it names. Every one keeps its medium's false-positive target: audio below 1.0% at the operating point (not met for unkeyed music, 7.25%, in the 2026-10 null campaign), video 0 mis-decodes and 0 unmarked decodes, text the binomial guard on 0.1% for presence and a grade B gate at 1e-5.

medium row now proposed why this level
audio, batch speech start offset 1 to 50 ms, issuer exact 0% at every offset off the 20 ms grid >= 95% oracle 100.0% at every offset; offset search
audio, batch speech middle half kept, issuer exact 5.8% >= 90% an aligned 0.5 s clip holds 100.0%; the loss is the grid phase
audio, batch speech marked share 25%, detected 2.0% >= 90% windowed detection over the saved time profiles
audio, batch speech tempo 0.99 and 1.01, issuer exact 17.0% and 18.0% >= 90% (new embedding) the streaming mark already holds 97.0% and 95.0% there
audio, streaming G.711 mu-law, detected 0% >= 90% (new embedding) the batch mark holds 100.0%
audio codec rows (Opus 12, G.711, MP3, AAC) 96.2% to 100.0% exact unchanged regression guard
video, VideoSeal H.264 crf 23 93.0% >= 97% its 3 failures are all near (margin counts can differ from rates by 1 to 2 clips, section 4)
video, VideoSeal social re-encode 62.8% >= 80% 11 near, 5 mid of 16 failing
video, VideoSeal H.264 crf 28 53.5% >= 75% the keyframe scheme reaches 78.0% on the same clips; 5 near, 15 mid of 20 failing
video, VideoSeal centre crop 80% 62.8% >= 90% oracle 93.0%
video, VideoSeal letterbox, screen recording 34.9%, 69.8% >= 80%, if an oracle row confirms it hypothesis: canvas detection; no oracle yet and mixed margins; identity is 100.0%
video, keyframes start trim, kept segments 0% off the 1 s grid >= 90% 95.1% when the cut is on the grid
text, KGW t=1 mark as 10% of a human text 32.0% >= 90% needs scoring past the 1,024-token cap (65 of 68 misses have none of the mark inside it) plus windowed scoring; the mark is intact
text, every arm mark as 25% of a human text SynthID 100.0%, KGW t=1 98.0%, KGW greedy 17.0% within 5 points of the arm's identity row windowed scoring removes the dilution, not the arm's own limit
text, SynthID identity; delete, insert, swap 30% (sweeps) 100.0%; 97.0%, 100.0%, 95.0% unchanged regression guard

No target is proposed for paraphrase (49.5% to 57.0% on the sampled arms, 30.5% for greedy KGW), for greedy KGW grade B (1.0%) or for heavy video compression (crf 35 14.0%): each needs a scheme or embedding change beyond the current scheme.

Paraphrase is a designed limit, not an open item. A text watermark lives in the choice of tokens; a full rewrite replaces those choices, so no token-level scheme survives it, and Laidline makes no claim that it does. This sits inside the product's design rule for every medium: to strip a Laidline mark, an attacker has to destroy and rebuild the media rather than copy it, which makes the result their own work in substance. The measured rates above (about half the marks survive a same-model paraphrase, nearly all survive translation) are published as the limit. Text hardening is complete with the windowed scan and the KGW cap lift.

Audio presence on the public tier is limited to the fast and normalised reads: the public detect tier shows an AudioSeal presence only when decode: fast or the hardened decode's fast or normalised path read it, or when it is confirmed. Before the fine-read floor (below), the hardened decode flagged unmarked read speech on 0.68 % of single utterances, 5.33 % of 30 s joins and 14.17 % of 120 s joins (0 of 1,247 other clips, an earlier bench), against 0.16 %, 0.67 % and 0.42 % for what the public tier shows. In the 2026-10 null campaign the public tier showed 0.18 %, 0.08 % and 0.24 % of 5,000 unmarked single utterances, 30 s joins and 120 s joins, and 7.25 % of 4,979 music clips. Fallback-only presence stays on the full tier, with a caveat stating the rates (Grading, "Audio presence on the public tier").

The hardened audio fallback is gated by the fine-read floor (Grading, "Hardened audio decode"): a batch-card read found by the phase search or the windowed read counts only if its whole-clip or its 10 s fine-pass message confidence reaches 0.305. With the floor, the full tier flags unmarked read speech on 0.40 % of single utterances (Wilson 0.26 to 0.60 %), 0.67 % of 30 s joins (0.18 to 2.40 %) and 1.25 % of 120 s joins (0.43 to 3.61 %), and 0 of 1,247 other clips (an earlier bench; in the 2026-10 null campaign the full tier flagged 0.78 %, 0.66 % and 1.48 % of 5,000 single utterances, 30 s joins and 120 s joins and 654 of 4,979 music clips, 293 of them by the fallback paths alone). What the floor costs on marked audio: 1 of 3,192 issuer-exact reads on 37 ordinary rows. Its limit, published as measured: a mark shorter than the 10 s fine-pass excerpt inside long unmarked audio is protected only as far as it was measured. That is 29 of 30 fresh 3 s marks inside 30 s (one issuer-exact read lost) and 30 of 30 fresh 12 s marks inside 120 s.

6. Corrections and caveats recorded

# correction or caveat evidence
1 AudioSeal's loudness normaliser is off. An earlier note ("the detector normalises loudness over the whole input") was wrong: all four checkpoints load with normalizer=None. Windowed audio detection is still wanted for memory, not for loudness. audioseal/builder.py:135-136; volume rows: -12 dB 100.0%, -20 dB 90.0% detected, -30 dB 3.0%
2 The shipped audio threshold is 0.5. 0.39 is the bench operating point (lowest threshold with under 1% false positives on 530 clips). Rates at the shipped setting are the "at 0.5" column. core/config.py:191; 0.75% at 0.39, 0.38% at 0.5
3 KGW detection changed: each distinct n-gram is scored once, and grade B counts the tokens the distinct n-grams cover. Greedy KGW on a small model now detects but grades D. watermark/text/kgw.py:92-126, detect/text_check.py:58-64; KGW greedy 95.0% detected, grade B 1.0%
4 Text detect gap. Only the configured scheme and the default key are scored, with no windowed scoring. The embed rows measure the cost; KGW's 1024-token cap explains its misses at a 10% share (embed_window in the result). KGW t=1 embed 10%: 65 of 68 misses outside the window
5 The text FPR guard is a binomial bound on the 0.1% limit. At that limit 500 texts expect 0.5 flags, so one flag is not evidence of excess: the run's single flags pass (P(X>=1)=0.39 and 0.18). The guard cannot prove the rate is below 0.1% either: 0 of 500 still leaves a Wilson upper bound of 0.76%. SynthID: 1 of 500 human (z max 3.31), 1 of 200 unmarked (z max 3.54); KGW 0 flags
6 GPU against CPU. In the pilot, image and audio were compared item by item: 75 identical decisions and 0 differ for each. Text was compared on rates only, and the rates differ (SynthID grade B 87.5% on the GPU against 100.0% on the CPU for the pilot's items), because the completions themselves differ between devices (device numerics and batch seeding); a GPU rerun of the first generation group was 48 of 48 identical, which shows GPU determinism, not CPU agreement. The phantom rate on the GPU is 8 of 5000 (0.16%), identical to the CPU run. Soft outputs are not bit-identical (0.15% of image raw bits flip on the 2-image check; logits differ by up to 3.3 after WebP), so in the full runs some image and audio rows moved from the published CPU numbers, all within their earlier Wilson intervals; Benchmarks lists them. the GPU pilot comparison, the phantom result and its decoder.device_note
7 The earlier video numbers were embedded with TF32 on. This run has TF32 off, which changes the VideoSeal embed bytes; on 2 clips (akiyo_0 and park_joy_420_720p50_0; identity and h264_crf35), exact decodes matched and bit accuracy moved by up to about 0.04 on harsh rows. Across the 43 clips several rows moved, all inside the earlier Wilson intervals (Benchmarks). machine.tf32_note
8 libx264 output is not always byte-reproducible (seen in 2 of 16 encodes under mixed load, 0 of 240 in isolation; cause unidentified), so per-clip bit accuracy reproduces to about ±0.006 and an exact decode can move at the edge. diagnostics.reproducibility
9 The Twilio row is re-decoded from the earlier recordings (no new calls) on the GPU. It equals the earlier figure: 99.0% detected (94.6 to 99.8%), 98.0% exact; 0 of 10 control calls flagged. telco in the audio result
10 Oracle rows estimate a resync ceiling; the crop oracles are not guaranteed ceilings (section 1). "Oracle below the attack" lines in the image run
11 TrustMark schema bits 98 and 99 are outside the BCH. A flipped schema bit fails a decode with at most 5 raw errors; the image bench counts these as near and lists them. "Schema-bit misses" lines
12 Horizontal flip survives on TrustMark; vertical did not decode in a development probe. Only horizontal is a bench row; the vertical result is not a bench measurement. flip_h Q 100.0%
13 Text descriptors: distinct_ngram_ratio uses bigrams (KGW's unit at context width 1) and repetition_rate uses 4-grams. descriptors in the text result
14 Keyframe residual after the pooled-consistency rule. The hardened keyframe reader drops a payload one frame accepted when the other frames' reads of the same step, pooled, outscore it (the bridge clip: a soft decode at the BCH limit landed on a neighbouring codeword 14 of 96 bits away, another issuer, while the other marked frames read the embedded codeword just under the normalised gate). The rule needs that contrary evidence: a clip whose only readable frame is such a neighbour, with no other frame reading the embedded codeword above the score gate, still decodes the neighbour (grade D unkeyed; in keyed mode it is ineligible, and its issuer is shown as a claim only when it parses under the keyed layout, that is when the neighbour keeps the 3 version bits; one that changes them shows presence without a claim). The saved records hold 0 such clips; the population at risk is the one-frame decodes with no rival (1,162 of 1,254 in the earlier video run). Grading ("Pooled consistency")

Reference

  • Benchmarks: the full result tables, latency, validators and image sizes, and how to rerun a suite.
  • Grading: how a decode becomes a grade, per signal, and the per-signal limits.
  • Keys: keyed payloads for image, audio and video, and their residuals.
  • Configuration: watermark.* and detect.* settings quoted above.