vmaf-tune — quality-aware encode automation harness¶
vmaf-tune finds the encoder settings that reach a target VMAF score. It drives FFmpeg over a grid of encoder parameters, scores each encode with vmaf, and either writes a JSONL corpus of (source, encoder, params, bitrate, vmaf) rows or answers a question directly: which CRF hits VMAF 92, which codec is cheapest at that target, what a per-title bitrate ladder looks like.
The tool is a fork-added Python package (ADR-0237, Research-0044). A Go port of the same subcommands is described in vmafx-tune-go.md.
Install¶
-
Install the package from the repository root. The core install has no runtime dependencies beyond the Python standard library:
This installs two equivalent console scripts,
vmaf-tuneandvmafx-tune. Without installing, run the checkout shim instead: -
Put the external binaries on
PATH(or pass--ffmpeg-bin/--vmaf-bin):ffmpegbuilt with the encoders you want to tune (--enable-libx264, plus--enable-libsvtav1forlibsvtav1, and so on).ffprobeis needed for container sources and HDR detection.vmaf, this fork's CLI, built with meson (see getting started).
-
Optional extras, installed as
pip install -e "tools/vmaf-tune[NAME]":Extra Adds For fastOptuna the TPE search of fastreportmatplotlib the charts of report; without it the report renders its tables and a placeholder per chartonnxONNX Runtime ONNX inference: the fastproxy, the per-shot predictor and the saliency modelsdevpytest, ruff, Optuna, matplotlib, ONNX Runtime running the test suite (see Tests)
vmaf-tune --version prints the package version.
Quick start¶
Sweep two presets and three CRF values over one 1080p clip. The grid is the Cartesian product of --preset and --crf, so this writes six rows:
vmaf-tune corpus \
--source ref.yuv \
--width 1920 --height 1080 --pix-fmt yuv420p \
--framerate 24 --duration 10 \
--preset medium --preset slow \
--crf 22 --crf 28 --crf 34 \
--output corpus.jsonl
Then ask the corpus which CRF reaches a target:
The corpus page lists every corpus flag and the row schema. Recommend covers the target-VMAF and target-bitrate queries.
Subcommands¶
vmaf-tune --help lists 14 subcommands. Each one has a page with its flag table and examples.
| Subcommand | Purpose | Page |
|---|---|---|
corpus | Encoder grid sweep plus scoring; writes the JSONL corpus | corpus |
recommend | Lowest-bitrate encode that meets a target VMAF, or the row closest to a target bitrate | recommend |
predict | Predict per-shot VMAF with an ONNX predictor and validate it | predict |
fast | Proxy model plus Bayesian search, verified once by a real encode | fast path |
tune-per-shot | Per-shot CRF zones from shot detection | per-shot |
recommend-saliency | Saliency-aware ROI encode | saliency-aware |
ladder | Per-title bitrate ladder (Pareto ABR) | ladder |
compare | Codec comparison at matched VMAF | compare |
benchmark | Offline cross-codec ranking from an existing JSONL | benchmark |
auto | Pick the cheapest strategy and run it | auto |
prefilter | Pelorus deband strength plus CRF joint autotune | prefilter |
report | Render a profile card from compare, ladder and per-shot JSON | report |
encode-profile | Run one recommendation from a report profile | report |
sidecar | Train and inspect the local predictor bias correction | predict |
There is no hdr subcommand. HDR handling is automatic on corpus and is controlled with --auto-hdr, --force-sdr, --force-hdr-pq and --force-hdr-hlg; see HDR and sampling.
ref.yuv ─► corpus ─► corpus.jsonl ─► recommend ──► CRF for a target
│ └► benchmark ─► encoder ranking
└─────────► predict / sidecar (predictor training)
ref.yuv ─► compare | ladder | tune-per-shot | fast | auto ─► JSON ─► report
└► encode-profile
Topic pages¶
These pages cover behaviour shared across subcommands.
| Topic | Page |
|---|---|
| Codec registry, preset names, quality ranges | codec adapters |
| AV1 encoders (libaom, SVT-AV1, SVT-AV1-HDR knobs) | AV1 codecs |
| NVENC, AMF, QSV and Apple VideoToolbox encoders | hardware codecs |
| x265, VP9 and VVenC encoders | software codecs |
| Which libvmaf backend scores the encodes | score backend |
| Automatic VMAF model choice per resolution | resolution-aware |
| HDR detection and sample-clip mode | HDR and sampling |
Two-pass encoding (--two-pass) | multi-pass |
| Coarse-to-fine CRF search | coarse-to-fine |
| Target-VMAF bisect contract | bisect |
No-reference early elimination (--fast-nr) | fast NR |
| Encode cache (Python API) | cache |
| Scratch directory, disk space, environment variables | workdir |
| Ladder variants | bitrate grid, default sampler |
| FFmpeg filter wiring and patches | FFmpeg wiring |
Design records¶
| Subject | Record |
|---|---|
| Tool and corpus | ADR-0237, Research-0061 |
tune-per-shot | ADR-0392 |
recommend-saliency | ADR-0293 (consumes vmaf-roi sidecars) |
ladder | ADR-0295 |
fast | ADR-0276, ADR-0291 |
prefilter | ADR-1116 |
benchmark | ADR-0424 |
sidecar | ADR-0394 |
encode-profile | ADR-0643 |
Tests¶
python3 -m venv .venv-tune
.venv-tune/bin/pip install -e "tools/vmaf-tune[dev]"
.venv-tune/bin/python -m pytest tools/vmaf-tune/tests/
The dev extra holds every package the suite imports, so a run from it has no failure and no skip for a missing package. Each test runs in its own temporary working directory (tests/conftest.py). The suite mocks subprocess.run almost everywhere, so it needs neither ffmpeg nor a built vmaf; the tests that need more skip and name what is missing:
| Skip reason | Precondition |
|---|---|
| no vmaf binary reachable | this fork's vmaf CLI: VMAF_BIN_FOR_TESTS=/path/to/vmaf, build/tools/vmaf, or a vmaf on PATH that has --backend |
set VMAF_TUNE_INTEGRATION=1 | opt-in runs against the real ffmpeg / libx265 |
the train extra | PyTorch for the predictor-training test |
| h264_qsv not compiled in or VA-API driver too old | an Intel GPU whose QSV encoder works |
| BBB corpus missing | the BBB clip under /workspace/.corpus/bbb_e2e/ (dev container) |
Former section names¶
ADRs and the changelog archive link to sections of the page this overview replaced; each heading points to the page that now holds the content.
fast subcommand — proxy + Bayesian + GPU-verify (Phase A.5)¶
Now on vmaf-tune fast.
Codec adapter contract¶
Now under adapter contract.
Per-content-type recipes (F.4)¶
Now under per-content-type recipes.
Sample-clip mode¶
Now under clip sampling.