One SDK/wheel and the same TrustMark Q / BCH5 / strength1 runtime support:
| Profile | Encoder work | Default |
|---|---|---|
economy_5s |
Fresh signal on each frame in 125 ms windows every 5 seconds | Yes |
economy_2s |
Same windows every 2 seconds | No |
resilient |
Fresh signal on every frame | No |
At 24 fps and 10 seconds, these normally select 6, 15 and 240 frames respectively. Selection uses exact relative PTS, not a nominal FPS counter. Include the first observed frame in each occupied period even if low FPS/VFR steps over the nominal window. Preserve the rest of the timeline; do not insert frames in gaps. Unselected frames bypass PIL/Node unless visible disclosure or rotation needs pixel conversion. Every frame still passes through H264 encoding. AAC and visible labels apply to the whole export, independent of sparse watermarking.
Select the preset
with SDK(identity=identity) as sdk: # default economy_5s
sdk.mark(source, output, record, audio_kind="original")
with SDK(identity=identity, video_profile="economy_2s") as sdk:
sdk.mark(source, output, record, audio_kind="original")
# Per-export choice; does not mutate this SDK's default.
sdk.mark(other_source, other_output, other_record, audio_kind="original",
video_profile="resilient")
CLI: add --video-profile economy_2s or --video-profile resilient to
ariadne mark. Omit it for Economy 5s.
In a full product configuration generated by ariadne profile init, set:
"sdk": {
"audio_kind": "original",
"video_profile": "economy_2s"
}
The product setting applies through both mark --profile product.json and
sdk.mark(..., profile=config). A per-export choice must agree with that
product setting; conflicts and unknown profile names fail before publication.
Older schema1 product files without the new field use Economy 5s. The normalized
setting is included in the configuration fingerprint. A configured product
profile takes precedence over the SDK constructor's default. Image processing
is unchanged by the video preset.
Export read-back and blind verification
Economy export requires at least one independently decoded matching ID in every occupied scheduled window, with no conflicting ID in checked frames. Failed individual observations are retained; success does not require every marked frame to remain readable. Resilient and explicit legacy Fast retain the five-uniform-sample fresh-export gate. A worker failure, missing window, C2PA failure or failed ID/record match publishes neither media nor receipt. Receipts and signed assertions record the actual selected profile. The receipt also records selected frame counts, windows and read-back evidence.
The public verifier does not need the profile or expected ID. For new video payloads it scans sequentially until two concordant individual IDs, EOF, a conflict or a budget. For weak IDs it tests unknown-phase 1/2/5 s window groups using at most 20 cached logits per upstream BCH aggregate. Period 1 is retained only as a recovery hypothesis for experimental assets, not as a new encoder preset. Logits are computed at most once per scanned frame. Different recovered IDs remain conflicting; the signed token and registry never select the answer.
Default search budgets: 2000 frames, 120 seconds, 512 aggregate hypotheses.
Budget exhaustion gives incomplete/not_checked, never a negative. A lone ID
without aggregate confirmation is single_observation, not a confirmed claim.
A recovered ID describes observed watermark evidence; early stopping does not
establish full-video coverage or cryptographic source authentication. Candidate
period/phase aggregation remains exploratory: the small negative-control set
does not calibrate population false positives. Longer files may require a
larger explicit VideoWatermarker.scan_video budget on the operator's own
trusted processing queue; the public endpoint remains bounded by default.
Signed engine identifiers route to the correct scheme. Without a supported signed identifier, the full installation also checks legacy bit layouts. Unavailable legacy engines mean partial/incomplete scheme coverage. None of these presets is a statutory marking-frequency minimum or a certificate of compliance, copyright ownership or truth.
Install
Use Docker for the complete CPU bundle, including old-format compatibility:
docker build --platform linux/amd64 -t ariadne-mark:local .
docker run --rm --network none ariadne-mark:local models check
For a video-only installation, activate a Linux x86-64 / Python 3.12 virtualenv with FFmpeg/ffprobe and Node/npm available, then use the installed wheel:
python -m pip install --no-deps /path/to/ariadne_mark-0.7.2a1-py3-none-any.whl
ariadne setup video --fetch-models
ariadne runtime check
This uses hash locks inside the wheel and avoids Torch, NumPy and Python
TrustMark. ariadne setup media --fetch-models installs images and full legacy
compatibility. Extras alone do not provision/qualify native C2PA or models.
See wheel installation.
Provisioning is explicit and uses the packaged npm lockfile plus SHA-256 model
and source checks. Runtime requests never download code/models. The dependency
cache is ~/.cache/ariadne-mark/video-v1, configurable by ARIADNE_VIDEO_DATA.
Docker preprovisions it under /opt/ariadne-video, readable by the runtime user.
The qualified 0.7.2a1 media environment uses Node24, Linux x86-64/Python3.12,
PyAV 16.0.1 and c2pa-python 0.38.3 / native 0.91.11. Runtime preflight
checks that actual C2PA pair before media operations and HTTP startup; other media platforms are not qualified.
Python
from pathlib import Path
from ariadne_mark.pipeline import SDK
from ariadne_mark.signing import SigningIdentity
from ariadne_mark.registry import Registry
sdk = SDK(
identity=SigningIdentity.from_directory(Path(".ariadne/dev"), allow_dev=True),
registry=Registry(Path(".ariadne/registry.sqlite3")),
video_profile="economy_5s", # default; also economy_2s or resilient
)
# record: ProvenanceRecord with actual publisher/system/time and media_kind VIDEO
receipt = sdk.mark(Path("input.mp4"), Path("output.mp4"), record,
audio_kind="original")
result = sdk.verify(Path("output.mp4"))
sdk.close()
Each SDK owns lazy persistent workers for the profiles it actually uses. Create one SDK per product worker and reuse it. Shared-thread exports serialize access to the encoder and isolate per-export caches; start separate SDKs in separate processes for parallel jobs. After a worker failure, the export fails before publication; a later export can create a fresh worker. Receipts contain model-call count, profile, total processing seconds, signed-file SHA-256 and verification attempts.
Supported export boundary
MP4 input/output, 8-bit SDR, one video track and optionally one AAC track, square pixels, dimensions 256–1920 pixels per side, at most 5 minutes/18000 frames. H.264 and HEVC decoding depend on FFmpeg/PyAV; output is H.264 CRF18/preset fast. AAC bytes and timestamps are copied. Synthetic audio is not watermarked by this visual SDK. VFR timing, portrait layout and 90-degree rotation are tested.
WebM/AV1/VP9 and 4K were research ingestion/load tests. This release's signed export API remains MP4 within the boundary above. HDR, alpha, interlacing, other audio codecs and anamorphic pixels require explicit conversion first. A negative/incomplete watermark result never certifies human origin or truth.
Evidence
Historical Fast/Resilient selection references live in benchmarks/video/profiles/.
They describe older profiles and are not relabelled as Economy results. The
Economy research comparison used four 10-second 720p24 fixtures and two timing
repeats; fresh per-frame windows every 1/2/5 s were compared with Resilient. All
three Economy candidates recovered 24/24 ordinary transformed assets only after
including an additional exploratory slow search. One matched-payload scene
showed 5s requiring recovery where 2s read directly. These small sets do not
establish population accuracy or legal compliance. Installed-SDK export gates
and the cached-logit verifier differ from that private adapter; do not reuse
its timing numbers as the timing of the integrated SDK.
Choosing a mode for your product
| Delivery scenario | Practical starting point | What still needs validation |
|---|---|---|
| Mostly full final exports; minimising model work | Economy5s, the SDK default | Actual delivery and short-content risk; not a statutory minimum |
| Short clips or common leading trims | Compare Economy2s against Resilient | A window-free excerpt can still defeat Economy2s |
| Higher temporal coverage is important | Resilient | More CPU work; crop/remover resistance is not guaranteed |
| Multiple aspect ratios or social renditions | Prepare each rendition, then mark it | Switching a mode does not solve every spatial transformation |
| Images | The image TrustMark path | Video mode choice does not change image watermarking |
Keep the returned-file gate enabled in every mode. Choose against the actual product's output/delivery evidence, not the expected rarity of verification. Fewer marked frames means fewer model calls, not an identical percentage saving in end-to-end processing: decode/encode, signing and read-back still consume resources.
Legacy Fast compatibility
Explicit fast / fast-cpu-v2 retains anchor-aware shared-residual encoding:
refresh on a 64x36 RGB sample change (RMSE > 0.5 intensity units), scene change,
or 24-frame cap. Motion can approach Resilient cost. This compatibility path is
not renamed Economy; new Economy windows always use fresh perFrame inference.
Color and fractional FPS (0.7.1 candidate)
The video path now explicitly reads and writes the SDR matrix/range. Supported
matrices are BT.709, BT.601 (BT.470BG/SMPTE170M), FCC and SMPTE240M. The focused
color reference/export tests cover BT.601/BT.709, full and limited range.
Unspecified matrix/range uses an explicit BT.601/limited fallback (full for
yuvj*); this is an assumption, not a way to infer a missing source tag.
Unsupported matrices and mid-stream matrix/range changes require explicit
normalization and fail closed. Primaries/transfer tags are preserved, not
converted. HDR remains unsupported.
Marked RGB frames are explicitly converted back to the source YUV policy before H.264 encoding; unselected YUV frames keep their bypass. Swscale uses accurate rounding and full chroma interpolation. The receipt records the policy. A conversion reference is compared against FFmpeg, and an identity-marker export isolates conversion error from the watermark model's own residual and H.264 loss.
Blind recovery uses an observed-phase bank with 64 bins/second, periods 1/2/5s, 93.75ms aggregation windows and at most 512 candidates. The narrower recovery window leaves room inside a 125ms encoding window for phase discretization. This avoids exhausting the hypothesis budget merely because FPS is 24000/1001 or 30000/1001; no rounding of the actual media timeline is introduced. Search receipts expose bank version, bin spacing and window size. A completed bank means only this discrete bank was completed. Frame/time limits, conflicting IDs, missing engines and incomplete searches retain their distinct verdicts.
The pinned Python and Node BCH5 decoders are additionally checked by re-encoding the recovered payload and checking distance from the received 96 data/parity bits (maximum five errors). This addresses false-valid codewords in the pinned pre-fix decoders; it is not a calibration of the complete watermark detector or an authentication mechanism. The 4 schema bits are outside that BCH code. Payloads, models, strength and all marking presets are unchanged.
Crop/letterbox recovery is tracked separately in spatial research. The experimental cropdetect probe is not silently part of the public verifier's qualified path.
Short clips, excerpts and deliberate removal
An untrimmed short file can be successfully marked with Economy5s. A 3-second file normally contains only its initial 125ms window; trimming the first 200 ms can remove that only window. Economy2s adds an occupied window near 2 s in this example, but an excerpt wholly between its windows can also have no selected frames. There is no universal ten-second threshold or arbitrary-excerpt guarantee. The default remains Economy5s; choose per-frame Resilient when temporal coverage matters, and qualify the actual delivery edits. Stronger sampling does not make any watermark attack-proof. The final export gate checks the returned file, not a later user/platform edit.
The public upstream TrustMark remover removed the image mark on both tested source scenes and a Resilient video mark on one of two scenes in the external 0.7.0/macOS review. Economy windows were removable by replacing selected frames with nearby frames. These are small-corpus adversarial results, not population statistics. The 0.7.1a1/Linux paired recheck also removed the image mark in 4/4 trials (two scenes, two IDs each). Both video identity controls retained ID; after the public remover, crowd recovered only by aggregation after 240 frames, while face returned not_found after 240 frames. See current validation. C2PA can validate surviving credentials; stripped metadata plus a lost watermark can leave no recoverable link. Do not describe Resilient as irreversible, a copyright security boundary, or a certified compliance setting.
Full-range Economy bypass (0.7.1a2)
Full-range 4:2:0 frames are normalized to the encoder's actual yuv420p layout without rescaling sample values or invoking the watermark model. Deprecated yuvj420p is layout-compatible; copying planes with their real strides avoids PyAV's implicit full-to-limited conversion. Non-420 layouts use explicit color conversion. Receipts identify color pipeline v2. Pixel/contrast checks span all frames; mean-only gradient tests are insufficient. HDR and non-8-bit formats are rejected using descriptors and decoded-frame properties.
Current qualification and interpretation
0.7.2a1 results confirm distinct schedules on a 6 s/12 fps fixture (Economy5s: 4 selected frames, Economy2s: 6, Resilient: 72). This is integration evidence, not a new speed/durability benchmark. Follow the protocols and evidence index for cold/warm, positive/negative verification, CPU/memory and transformation scope. Known full-range 4:4:4 chroma offset remains; evaluate prepared 4:2:0 SDR inputs. No profile is a statutory minimum or an unremovable watermark.