ADR-0622: VMAF NEG Integration Implementation¶
- Status: Accepted (Implemented)
- Date: 2026-05-19
- Deciders: lusoris
- Tags:
vmaf-tune,neg,docs
Context¶
ADR-0616 decided to expose VMAF NEG model variants in vmaf-tune via a --neg flag. The NEG model files (model/vmaf_v0.6.1neg.json and model/vmaf_4k_v0.6.1neg.json) were already present in the repository. No additional model training was required.
This ADR records the concrete implementation decisions:
- Where the
neg_model_for()routing helper lives (resolution.py), so it is co-located with the relatedselect_vmaf_model_version()logic and theMODEL_*constants. - Where the
_add_neg_flag()helper lives (cli.py), so every subparser wires the flag identically. - Where
_resolve_vmaf_model()lives (cli.py), producing the effective model string at runner time rather than parser time — this keeps the routing out of argparse callbacks and testable as a pure function. - How
make_default_sampler()inladder.pythreads the model through toCorpusOptions.
Decision¶
Implementation of ADR-0616 Option A (--neg flag) using the following concrete patterns:
resolution.py— addsMODEL_1080P_NEG,MODEL_4K_NEGconstants andneg_model_for(model_version: str) -> strmapping helper.neg_model_foris idempotent, passthrough for pre-formattedkey=valuemodel strings, and falls back to appending"neg"for unknown models so libvmaf surfaces a clear error rather than the code silently selecting the wrong model.cli.py— adds_add_neg_flag(parser)helper (called for every affected subparser),_resolve_vmaf_model(args)(replaces everyargs.vmaf_modelusage in runner functions), and importsneg_model_forfromresolution.ladder.py— threadsvmaf_modelparameter throughmake_default_sampler()and_default_sampler()intoCorpusOptions.- Affected subcommands:
corpus,recommend,tune-per-shot,compare,ladder.
Alternatives considered¶
| Option | Decision |
|---|---|
Route inside argparse type= callback | Rejected: would fire at parse time, complicates testing, and prevents getattr(args, "neg", False) fallback for subcommands not yet wired |
Add vmaf_model to bisect_target_vmaf signature | Not needed: bisect_target_vmaf already accepts vmaf_model as a parameter; the CLI runner simply passes _resolve_vmaf_model(args) |
Separate --neg-model flag for explicit path | Rejected: per ADR-0616, --model-variant enum is deferred to V2 |
Consequences¶
- Positive:
vmaf-tune compare --negis correct for codec A vs. B comparisons where sharpening could inflate standard VMAF. - Positive:
neg_model_for()is idempotent and handles edge cases cleanly; tests lock down all branches. - Negative: Users must pass
--negexplicitly; wrong usage (e.g.--negfor production quality monitoring) produces misleading lower scores — mitigated bydocs/metrics/vmaf-neg.md. - Neutral:
ladder.py'smake_default_samplergrew one keyword argument (vmaf_model); existing callers are unaffected (default preserves historicvmaf_v0.6.1).
References¶
- Design ancestor: ADR-0616
- User direction: implement ADR-0616 (2026-05-19 session)
- Docs: docs/metrics/vmaf-neg.md
- Research: docs/research/0612-vmaf-neg-integration-research.md