vmaf — command-line reference¶
vmaf scores a reference / distorted video pair with one or more VMAF models (plus any extra feature extractors) and writes per-frame and pooled scores to an XML, JSON, CSV or subtitle log. This page is the canonical flag reference: every flag in vmaf --help, with its default, interactions and an example.
Scope
The code's --help is authoritative for the set of flags at any given commit. This page adds defaults, interactions and runnable examples per ADR-0100. It supersedes the abbreviated help string in core/tools/README.md.
Related pages: bench.md for the vmaf_bench micro-benchmark, ffmpeg.md for the FFmpeg libvmaf filter, python.md for the Python bindings and vmafx-cli.md for the vmafx alias.
Quick start¶
Build the binary as described in the source-build guide; with meson setup build core it lands at build/tools/vmaf.
# .y4m pair: no geometry flags needed
vmaf --reference ref.y4m --distorted dist.y4m
# .yuv pair: geometry is mandatory
vmaf \
--reference ref.yuv \
--distorted dist.yuv \
--width 1920 --height 1080 \
--pixel_format 420 --bitdepth 8 \
--output scores.xml
Without --model, the built-in vmaf_v1.0.16_3d0h model is loaded. Without --xml|--json|--csv|--sub, the output format is XML.
The default model differs from upstream Netflix
Upstream Netflix defaults to vmaf_v0.6.1; this fork defaults to vmaf_v1.0.16_3d0h (ADR-1169), so the same command prints different numbers on each. Pin --model version=vmaf_v0.6.1 to get the upstream values. On the standard 576x324 test pair the pooled VMAF moves from 76.667831 to 82.816060. See models/v1.md for the v1 model family.
Option reference¶
Every option of vmaf, generated from the API definition (core/api/vmafx.toml, option groups; see API generation). The sections below explain each group in detail. vmaf --help prints the same list from the same source.
| Option | Short | Value | Default | Description |
|---|---|---|---|---|
--reference | -r | string | Reference video: a .y4m file, or raw planar .yuv together with the width, height, pixel format and bit depth. | |
--distorted | -d | string | Distorted video, in the same form as the reference. | |
--width | -w | uint >= 1 | Width of raw .yuv input in pixels. | |
--height | -h | uint >= 1 | Height of raw .yuv input in pixels. | |
--pixel_format | -p | 420 | 422 | 444 | Chroma subsampling of raw .yuv input. | |
--bitdepth | -b | 8 | 10 | 12 | 16 | Bits per sample of raw .yuv input. | |
--check-sample-range, --check_sample_range | bool | false | Refuse a frame with a sample above 2^bpc - 1 and name the plane, row, column and value (ADR-1918). | |
--color_range_ref | unknown | limited | full | Colour range of the reference input. | ||
--color_range_dist | unknown | limited | full | Colour range of the distorted input. | ||
--color_primaries_ref | unknown | bt709 | bt2020 | Colour primaries of the reference input. | ||
--color_primaries_dist | unknown | bt709 | bt2020 | Colour primaries of the distorted input. | ||
--color_trc_ref | unknown | bt709 | smpte2084 | pq | Transfer characteristic of the reference input. | ||
--color_trc_dist | unknown | bt709 | smpte2084 | pq | Transfer characteristic of the distorted input. | ||
--color_matrix_ref | unknown | bt709 | bt2020nc | ictcp | Matrix coefficients of the reference input. | ||
--color_matrix_dist | unknown | bt709 | bt2020nc | ictcp | Matrix coefficients of the distorted input. | ||
--model | -m | string | library default (VMAF_DEFAULT_MODEL_VERSION) | Model, colon-delimited: version= a built-in model, path= a model file, name= the name in the report, disable_clip, enable_transform, <feature>.<option>=<value> overloads. Several models score in one pass (repeat the option; the filter separates them with |). |
--backend | auto | cpu | cuda | sycl | hip | metal | auto | Backend: auto uses the available ones; any other value runs that backend alone and fails when it is not available. | |
--no_cuda | bool | false | Disable the CUDA backend. | |
--no_sycl | bool | false | Disable the SYCL (oneAPI) backend. | |
--no_hip | bool | false | Disable the HIP (ROCm) backend. | |
--no_metal | bool | false | Disable the Metal (Apple silicon) backend. | |
--feature | string | Additional feature extractor, name[=key=value:...] (for example psnr or cambi=full_ref=true); several may be given (the filter separates them with |). Mutually exclusive with the CTC presets. | ||
--aom_ctc | v1.0 | v2.0 | v3.0 | v4.0 | v5.0 | v6.0 | v7.0 | AOM common test conditions preset: a fixed model and feature set. | ||
--nflx_ctc | v1.0 | Netflix common test conditions preset: a fixed model and feature set. | ||
--tiny-model, --tiny_model | string | Tiny ONNX model to load alongside the classic models. | ||
--tiny-device, --tiny_device | auto | cpu | cuda | openvino | openvino-npu | openvino-cpu | openvino-gpu | coreml | coreml-ane | coreml-gpu | coreml-cpu | rocm | auto | ONNX Runtime execution provider of the tiny model. | |
--dnn-ep, --dnn_ep | auto | cpu | cuda | openvino | openvino-npu | openvino-cpu | openvino-gpu | coreml | coreml-ane | coreml-gpu | coreml-cpu | rocm | Alias of the tiny-model device under the ONNX Runtime name (execution provider); both set the same setting. | ||
--tiny-threads, --tiny_threads | uint | Intra-op threads of the CPU execution provider (0: the runtime's default). | ||
--tiny-fp16, --tiny_fp16 | bool | false | Request fp16 input and output where the execution provider supports it. | |
--tiny-model-verify, --tiny_model_verify | bool | false | Require a Sigstore bundle verification of the tiny model (cosign verify-blob) before it loads; a missing bundle, a missing cosign or a failed verification refuses the model. | |
--tiny-codec, --tiny_codec | string | Encoder of the distorted clip, required by codec-aware tiny models (fr_regressor_v2/v3), which refuse to score without it. Must be in the model sidecar's encoder_vocab; the ffprobe names h264, hevc, av1, vp9 and vvc are accepted. | ||
--tiny-preset, --tiny_preset | string | Encoder preset (medium, slow, p4, 5, ...), read as the encoder defines it. Unset: ordinal 5 (medium). A model trained with one preset (fr_regressor_v3) ignores it and warns. | ||
--tiny-crf, --tiny_crf | uint 0..63 | CRF or QP used for the encode, normalised as the model sidecar declares. Required with the codec and preset. | ||
--tiny-resize, --tiny_resize | bilinear | nearest | bicubic | disabled | disabled | Resize filter for NCHW tiny models whose input size differs from the frame; disabled refuses the mismatch (-ERANGE). The three filters give scores about 2% apart: record the filter with the model. | |
--no-reference, --no_reference | bool | false | No-reference mode; needs a no-reference tiny model. The reference becomes a formality: only the distorted picture is scored. | |
--threads | uint | Worker threads of the feature extractors, capped to the hardware threads (0: score in the calling thread). | ||
--frame_cnt | uint >= 1 | Score at most this many frames. | ||
--frame_skip_ref | uint | Skip this many frames at the start of the reference. | ||
--frame_skip_dist | uint | Skip this many frames at the start of the distorted video. | ||
--no_prediction | -n | bool | false | Extract features only; no model score. |
--cpumask | -c | uint | Bitmask of CPU instruction sets the extractors must not use. | |
--gpumask | uint | Bitmask of GPU operations the extractors must not use. | ||
--sycl_device | uint | SYCL GPU by index (unset: selected automatically). | ||
--hip_device | uint | HIP GPU by index (opt-in: HIP is off unless this or --backend hip is given). | ||
--metal_device | uint | Metal GPU by index (opt-in: Metal is off unless this or --backend metal is given). | ||
--subsample | uint >= 1 | 1 | Score every n-th frame (1: every frame). | |
--precision | legacy | max | full | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | legacy | Score precision: N (1 to 17) writes %.<N>g; max or full write %.17g (round-trip lossless); legacy writes %.6f (Netflix-compatible). The scoring server returns lossless scores unless asked otherwise. | |
--output | -o | string | Report file. | |
--xml, --json, --csv, --sub | json | xml | csv | sub | xml | Report format; json and xml carry the backend receipt. | |
--provenance-sidecar | bool | false | Also write the provenance record to <output>.provenance.json; CSV and SUB reports carry it nowhere else (RC4 WP5). | |
--netflix-compat, --netflix_compat | bool | false | Restore the Netflix-upstream defaults: CPU backend, %.6f precision, vmaf_v0.6.1 model. | |
--quiet | -q | bool | false | Disable the FPS meter when run in a terminal. |
--version | -v | bool | false | Print the version and exit. |
--list-backends | bool | false | Print the scoring backends this binary was built with and which of them initialise here, as JSON, and exit (ADR-1874). | |
--help | bool | false | Print this message and exit. | |
--verify-provenance | string | Re-run the configuration a JSON report records and compare every configuration field and score bit for bit; exits nonzero naming the first difference (RC4 WP5). |
Input flags¶
| Flag | Short | Argument | Required | Notes |
|---|---|---|---|---|
--reference | -r | path | yes (not with --no-reference) | .y4m or .yuv path. |
--distorted | -d | path | yes | .y4m or .yuv path. |
--width | -w | unsigned | yes for .yuv | Ignored for .y4m (embedded). |
--height | -h | unsigned | yes for .yuv | Ignored for .y4m. |
--pixel_format | -p | 420 | 422 | 444 | yes for .yuv | 420 covers the overwhelming majority of streamable content. |
--bitdepth | -b | 8 | 10 | 12 | 16 | yes for .yuv | 10 and 12 bit require a 10-/12-bit aware model (e.g. vmaf_b_v0.6.3 for banding sensitivity). |
--check-sample-range | none | no | Refuse a frame with a sample above \(2^{\mathrm{bitdepth}} - 1\) (for example 1024 in a 10-bit .yuv) and stop with a non-zero exit status; the message names the picture, plane, row, column and value. Off by default. Underscore alias --check_sample_range. See Sample range. |
If any of --width, --height, --pixel_format, --bitdepth is supplied, the input is treated as raw YUV and all four become mandatory. vmaf reads only .y4m and .yuv; decode other containers first.
A raw .yuv file of 10 or 12 bits stores each sample in 16 bits, so it can hold values above \(2^{\mathrm{bitdepth}} - 1\). Such input is invalid: the CPU extractors and their GPU twins may score it differently. --check-sample-range finds the first such sample.
Odd frame dimensions (for example 1921x1081 or 19x19) are accepted for raw .yuv and .y4m inputs in 4:2:0 and 4:2:2. Chroma plane extents use ceiling division ((dim + 1) / 2), which matches container layouts and covers the last boundary samples (ADR-1398).
Models¶
--model / -m takes a colon-delimited key=value string (see Option-string grammar for escaping : and \):
--model path=<file> # load a .json model from disk
--model version=<builtin> # load a built-in model by name
--model path=...:name=<str> # rename the metric in the output log
--model version=...:disable_clip # disable score clipping to [0, 100]
--model version=...:enable_transform # apply transform
Pass --model several times to run several models in one pass. Each model needs a unique name=, otherwise the CLI errors out. This example runs VMAF and VMAF-NEG side by side:
vmaf -r ref.y4m -d dist.y4m \
--model version=vmaf_v0.6.1:name=vmaf \
--model version=vmaf_v0.6.1neg:name=vmaf_neg \
--output scores.json --json
Built-in model versions¶
Built-in models are compiled into libvmaf with -Dbuilt_in_models=true (the default).
| Version | Purpose |
|---|---|
vmaf_v1.0.16_3d0h | Default. v1.0.16 standard 1080p model, 3H viewing distance. |
vmaf_v1.0.16_1d5h_2160 | v1.0.16 4K model, 2160p at 1.5H. Used by the fork's 4K resolution ladder. |
vmaf_v1.0.16_5d0h | v1.0.16 phone model (1080p at 5H). |
vmaf_v1.0.16_3d0h_2160 | v1.0.16 consumer 4K (2160p at 3H); operates on a [0, 110] range. |
vmaf_v1.0.16_hfr_3d0h, vmaf_v1.0.16_hfr_1d5h_2160, vmaf_v1.0.16_hfr_5d0h, vmaf_v1.0.16_hfr_3d0h_2160 | The four v1.0.16 models for high-frame-rate content (about 50 / 60 fps), one per viewing condition above. Their motion feature uses the five-frame window with a moving average (VMAF v1 models, Motion). |
vmaf_v0.6.1 | Previous default, and still upstream's. 1080p training set, classic release. |
vmaf_v0.6.1neg | Negative-gain (NEG), non-enhancing; recommended for encoder A/B where one encoder may artificially sharpen. There is no NEG counterpart to any v1.0.16 model, so asking for NEG also selects the v0.6.1 generation. |
vmaf_b_v0.6.3 | Banding-aware variant (used with CAMBI). |
vmaf_4k_v0.6.1 | 4K training set. |
vmaf_4k_v0.6.1neg | 4K + NEG. |
The float-precision variants (vmaf_float_v0.6.1, vmaf_float_v0.6.1neg, vmaf_float_b_v0.6.3, vmaf_float_4k_v0.6.1) also resolve but are legacy. Prefer the integer versions for performance; use the float versions only for bit-exact comparison with older reports.
Model file limits¶
JSON model files may contain at most 512 simultaneously nested arrays or objects, including the outermost container. A 513th level fails model loading; the internal parser records maximum depth of nesting reached, and the CLI may report only the enclosing model-load failure.
The limit does not cap the number of features or array elements at one level. Flatten unnecessarily nested custom model data instead of nesting deeper.
Additional features¶
--feature enables extra metrics beyond what the model already consumes. The syntax is the same colon-delimited form as --model, with the same escaping rules (Option-string grammar):
--feature psnr
--feature psnr=enable_chroma=true:enable_apsnr=true
--feature float_ssim=enable_db=true:clip_db=true
--feature cambi
--feature ciede
--feature psnr_hvs
--feature brisque
--feature brisque=model_path=/path/to/brisque_live.model
--feature motion=motion_five_frame_window=true:motion_moving_average=true
See ../metrics/features.md for the full list of feature identifiers and per-feature options.
Option validation is strict. An unknown option key or a typo (for example --feature adm=adm_csf_moed=2) is rejected immediately with libvmaf ERROR feature extractor '<name>': unknown option '<key>', and vmaf exits non-zero (ADR-1183).
Feature-specific notes¶
brisque. The no-reference metric ships its trained model embedded in the binary, so it needs no extra arguments.model_pathoverrides it with an on-disk libsvm model and is required only for builds withbuilt_in_modelsdisabled. See ../metrics/brisque.md.- Five-frame motion window. The last example above is the motion feature of the high-frame-rate models on its own: each frame is compared with the frame two back instead of the previous one (Motion, five-frame window). Its scores are written under
integer_motion2_mffw_mmaandinteger_motion3_mffw_mma. - Picture pool with that window. The context keeps the reference pictures of the two frames before the current one, so its picture pool needs at least four pictures. The tool sizes its pool before it loads the models, so a run without
--threadsalways preallocates four, one more than it needs without the window; with--threadsthe count is unchanged. Thepicture pool: N pictures pre-allocatedline counts them, read-ahead pictures included. A C API caller that preallocates fewer than four pictures for an_hfrmodel gets-EINVALinstead of a stall (C API).
Shared feature contexts¶
Repeated registrations share work only when their option-derived feature keys match:
--feature motionand--feature motion=motion_force_zero=truekeep separate contexts and output keys; the latter adds the_force_0suffix.- Explicit default values and option aliases resolve to the same keys as their canonical settings.
- Equivalent CPU/GPU twins keep the first registered context.
- The same rules apply when several loaded models request different feature parameters.
Feature extractors on a GPU backend¶
With --backend cuda, sycl, hip or metal, a --feature that names a CPU extractor runs on that backend's twin, picked the same way a model's features are (ADR-1359):
vmaf ... --backend sycl --feature ciede # runs ciede_sycl
vmaf ... --backend cuda --feature float_ssim # runs float_ssim_cuda
vmaf ... --backend sycl --feature brisque # no twin: runs brisque on the CPU
The twin is used only when it can compute exactly what you asked for. In the four cases below the CPU extractor runs instead, and vmaf prints one warning line on stderr naming the feature and the reason:
| Reason | Warning (for --backend sycl) |
|---|---|
| The backend has no twin of the extractor | vmaf: warning: --feature brisque: the sycl backend has no twin of this extractor; computing it on the CPU |
| The twin lacks an option you set, or implements only its default value | vmaf: warning: --feature float_motion: float_motion_sycl cannot honour option 'motion_filter_size'; computing it on the CPU |
| The twin cannot run this input size and bit depth with these options | vmaf: warning: --feature float_ssim: float_ssim_sycl cannot run 100x100 8-bit pictures with these options; computing it on the CPU (with float_ssim=scale=10, which leaves less than SSIM's 11x11 window) |
A non-zero --gpumask disables the backend's extractors | vmaf: warning: --feature ciede: cuda feature extraction is disabled (non-zero --gpumask); computing it on the CPU |
The run carries on after a warning; the JSON receipt lists which extractor ran where. A twin computes the same metric names, and its scores can differ from the CPU extractor's within the cross-backend tolerances. Its auxiliary outputs can differ too:
- On SYCL,
--feature motionreportsinteger_motion,integer_motion2andinteger_motion3, where the CPU extractor reportsVMAF_integer_feature_motion_sad_scoreinstead ofinteger_motion. - On SYCL,
--feature float_motionreportsmotionandmotion2but notmotion3, which only the CPU extractor computes.
Use --backend cpu to get the CPU extractor's exact output.
Nothing changes in three cases:
- A twin name, such as
--feature ciede_sycl, registers that extractor. It still fails with exit code100when its backend is not active (ADR-0543). --backend cpualways runs the CPU extractor.--backend auto, or no--backend, registers the name as given, even when a GPU backend is initialised.
Features that a --model needs resolve to the active backend's twin in every mode, with the same option and input-size checks.
Option-string grammar¶
--model and --feature take a colon-delimited list of key=value pairs:
:separates pairs.- The first
=in a pair separates the key from the value; everything after it belongs to the value, so a path may contain further=characters. .separates the feature name from the option name in a model feature overload (--model version=...:adm.adm_enhn_gain_limit=1.2).
Keys and values escape differently, because values are where paths live:
| You want | In a key | In a value |
|---|---|---|
a literal : | \: | \: |
a literal = | \= | = or \= |
a literal . | \. (overload feature/option name) | . |
a literal \ | \\ | \ (but see below) |
A key is the part before the first =, the feature name of --feature, or either half of a model overload key. In a key, \:, \=, \. and \\ are escapes and any other backslash is data.
Backslashes in values¶
In a value, a backslash is data, so Windows paths are written as they are:
vmaf -r ref.y4m -d dist.y4m --model 'path=C:\models\vmaf_v0.6.1.json'
vmaf -r ref.y4m -d dist.y4m --model 'path=..\..\models\vmaf_v0.6.1.json'
vmaf -r ref.y4m -d dist.y4m --model 'path=\\server\share\models\vmaf_v0.6.1.json'
vmaf -r ref.y4m -d dist.y4m --model 'path=C:\models\.cache\vmaf_v0.6.1.json'
vmaf -r ref.y4m -d dist.y4m --model 'path=/srv/models=2026/vmaf.json'
vmaf -r ref.y4m -d dist.y4m --model 'path=/srv/odd\:name/vmaf.json'
The one exception is a run of backslashes directly before a : or =, or at the end of the value. Such a run is read in pairs: \\ stands for one backslash, and a single backslash left over escapes the : or = after it (at the very end of the value it stays a backslash). This keeps a backslash in front of a delimiter expressible:
| Written | Value |
|---|---|
path=C:\out\ | C:\out\ |
path=C:\out\\:name=x | C:\out\, then the pair name=x |
name=a\:b | a:b |
name=a\\\:b | a\:b |
A : that spells a Windows drive letter is treated as data, not as a pair separator. That means a single ASCII letter at the start of a key or a value, followed by : and then \ or /.
Quote the whole option string
Use single quotes in your shell, as above. Otherwise the shell eats the backslashes before vmaf sees them.
The rules are identical for --model, --feature and the vmafx alias.
Output¶
| Flag | Default | Notes |
|---|---|---|
--output / -o <path> | no file | Writes the per-frame + pooled log to <path>. |
--xml | default | XML report (upstream-compatible). |
--json | JSON report. | |
--csv | One row per frame. | |
--sub | SubRip subtitle format, useful for overlaying scores during playback. |
Progress and the per-model pooled score are written to stderr only when stderr is a terminal. The progress line is suppressed by --quiet; the pooled score line is suppressed only when --quiet and --output are both given. When stderr is redirected, nothing is printed there.
Each <metric> row of XML, and each entry of pooled_metrics in JSON, carries min, max, mean and harmonic_mean; there is no flag to select a subset. The percentile methods (median, perc5, perc10, perc20) are available through the C API (ADR-1188) but are not written into the report.
Backend receipt in JSON output¶
A JSON report ends with the score format, the provenance record of the run and two keys that say where the features were computed (ADR-1359); the library writes all of them (ADR-2073):
"score_format": "%.17g",
"provenance": {"abi_major":0,"abi_minor":1,"abi_patch":5,"active_backend":"sycl", ...},
"feature_backends": [
{"extractor": "ciede_sycl", "backend": "sycl"},
{"extractor": "brisque", "backend": "cpu"}
],
"backend_used": "sycl"
backend_usediscuda,sycl,hipormetalwhen at least one feature extractor ran on that device, andcpuwhen every extractor ran on the CPU. It reports what ran, not what was initialised:--backend syclwith only--feature brisqueand--no_predictionreportscpu.feature_backendslists every feature extractor of the run, in registration order, with the backend it ran on. It includes the extractors a model needs and reflects the CPU replacements made after the first frame, so a model feature that fell back to the CPU appears as acpuentry.provenanceis the library's provenance record of the run: library, ABI and build, device, options, frames, models with their SHA-256, the producer of every feature, the command line, and the digests that let--verify-provenancecheck the report. Score provenance documents every field. The scoring server copies it into every response (scoring API contract).score_formatis the printf format the scores were written with.
A run mixed device twins and CPU extractors when backend_used names a device and feature_backends holds at least one cpu entry. XML reports carry the record as a <provenance> element; CSV and SUB reports carry none of these keys, and --provenance-sidecar writes the record next to them as <output>.provenance.json.
Verifying a report¶
re-runs the command line a JSON report recorded and compares every configuration field and every score bit for bit; it exits 0 on a match, 1 naming the first difference, and 2 when the check cannot run. See Score provenance.
Score precision¶
--precision N # printf "%.<N>g", N in 1..17
--precision max|full # printf "%.17g": IEEE-754 round-trip lossless (opt-in)
--precision legacy # printf "%.6f": synonym for the default
The default is %.6f, which matches upstream Netflix output byte for byte so the CPU golden gate passes without explicit flags (ADR-0119, which supersedes ADR-0006). Pass --precision=max whenever you need IEEE-754 round-trip lossless output: cross-backend numeric diffs, archival reports, any consumer that re-parses scores into doubles. The flag affects XML, JSON, CSV, SUB and stderr consistently.
The vmafx alias defaults to --precision=max (vmafx-cli.md). See precision.md for when to pick each mode.
Backend selection¶
Each backend is opt-in at build time through a meson flag. At runtime, backend selection is per invocation through the flags below; no environment variable overrides it. If no GPU backend is built in, the GPU flags are silently inert. See ../backends/index.md for the runtime dispatch rules and which features have GPU or SIMD twins.
Selection flags¶
| Flag | Default | Effect |
|---|---|---|
--backend <name> | auto | Exclusive backend selector: auto, cpu, cuda, sycl, hip, metal. A specific backend disables the others through the matching --no_X flags before dispatch and pins its device index: gpumask=0 for CUDA, sycl_device=0, hip_device=0 or metal_device=0 for the others. With auto, the compiled-in backends compete by registry order (SYCL, then CUDA); HIP and Metal join only through their device flags. |
--no_cuda | off | Forbid CUDA dispatch even if the CUDA backend is built in. |
--no_sycl | off | Forbid SYCL dispatch even if the SYCL backend is built in. |
--sycl_device <N> | auto (first GPU) | Pick the SYCL device by ordinal from the oneAPI device list. |
--no_hip | off | Forbid HIP/ROCm dispatch even if the HIP backend is built in. |
--hip_device <N> | disabled (opt-in) | Pick the HIP/ROCm device by ordinal; 0 is the first AMD GPU. Without this flag the HIP backend is never used, even when built with -Denable_hip=true. See ../backends/hip/overview.md. |
--no_metal | off | Forbid Metal dispatch even if the Metal backend is built in (macOS only). |
--metal_device <N> | disabled (opt-in) | Pick the Metal GPU by ordinal (macOS only); 0 is the first Metal device, typically the integrated Apple GPU on Apple Silicon. Without this flag the Metal backend is never used, even on macOS builds. See ../backends/metal/index.md. |
--cpumask <bitmask> (-c) | all ISAs enabled | Mask out specific CPU ISAs (for example force scalar, or disable AVX-512). Values are fork-internal; see core/src/cpu.h. |
--gpumask <mask> | GPU enabled | Not a per-op mask; see --gpumask. |
--threads <N> | 0 (serial) | Worker thread count; see Threads. |
Which backends this binary can use¶
vmaf --list-backends prints, as one JSON document on stdout, every backend the CLI knows (cpu, cuda, sycl, hip, metal, in that order) and exits 0. It needs no input files and ignores the other options.
{
"backends": [
{"name": "cpu", "compiled": true, "usable": true},
{"name": "cuda", "compiled": true, "usable": false, "init_status": -19},
{"name": "sycl", "compiled": false, "usable": false},
{"name": "hip", "compiled": false, "usable": false},
{"name": "metal", "compiled": false, "usable": false}
]
}
| Field | Meaning |
|---|---|
compiled | The backend is built into this binary. The --help text lists every backend name on every build, so it does not answer this. |
usable | The backend's state initialises on its default device (index 0) on this host: the same call a run with --backend <name> makes. Always true for cpu, never for a backend that is not compiled. |
init_status | Present when a compiled backend did not initialise: the negative errno its initialiser returned (for example -19, -ENODEV, when no device is found). |
Each compiled GPU backend is initialised once and released, which can take up to about a second per backend. The library may log why an initialisation failed on stderr; stdout carries only the JSON. vmaf-tune --score-backend and vmafx-tune --score-backend read this report (score backends, ADR-1874).
The gpumask flag¶
Despite the $bitmask placeholder in the usage string, --gpumask is not a per-operation mask:
- Passing the flag at all opts into GPU backend selection.
- Any non-zero value then disables the GPU feature extractors for both CUDA and SYCL, so the run falls back to the CPU implementations.
--gpumask 0therefore means "use the GPU" and--gpumask 1means "use the CPU"; the latter is byte-identical to--no_cuda --no_sycl.- Negative values are rejected (
should be a non-negative integer). Upstream accepts--gpumask -1only because POSIXstrtoulsilently converts"-1"toULONG_MAX; this fork refuses a value the caller did not mean (ADR-1209). Write--gpumask 1instead.
Threads¶
Without --threads, no worker pool is created and CPU extractors run one frame at a time. Values above the host's core count are capped. The flag is valid with every backend, including cuda and sycl, and the result is identical to a serial run.
Threaded CPU submission keeps at most one pending frame job per worker, in addition to jobs already running. When decoding runs ahead of feature extraction, submission waits for queue capacity instead of retaining an unbounded backlog. This bounds pending work; score storage and backend buffers still contribute to memory use. See thread-pool behavior.
Removed backends¶
Vulkan backend removed (ADR-0726)
The --no_vulkan, --vulkan_device and --backend vulkan flags no longer exist; passing them produces an unrecognised-option error. See ../backends/vulkan/overview.md for historical context.
Frame range¶
--frame_cnt <N> # stop after N frames (both streams)
--frame_skip_ref <N> # skip the first N frames of the reference
--frame_skip_dist <N> # skip the first N frames of the distorted
--subsample <N> # compute scores only every Nth frame (default 1 = all frames)
--subsample trades precision for speed. Pooled scores are still computed over the sampled subset, so keep it at 1 for final reports.
Input colorimetry¶
--color_range_ref/_dist <limited|full|unknown>
--color_primaries_ref/_dist <bt709|bt2020|unknown>
--color_trc_ref/_dist <bt709|smpte2084|pq|unknown>
--color_matrix_ref/_dist <bt709|bt2020nc|ictcp|unknown>
A raw .yuv or .y4m file carries no colorimetry, so each input is described separately: the _ref flags describe the reference, the _dist flags the distorted video. Give all four attributes of an input or none of them; a partly specified input is a usage error. pq is an alias of smpte2084.
Only a model that declares a conversion_target reads these flags: libvmaf then converts both inputs to the model's colorspace (and pixel format and bit depth, where the model pins them) before it extracts features, and refuses a run whose input colorimetry is missing (libvmaf returned -22, with a message naming the missing attributes). Models without a conversion_target, including every shipped VMAF model, ignore the flags and score the pictures as they are. The conversion needs a vmaf built with -Denable_zimg=true (build flags); without it a run that needs a conversion fails with -ENOTSUP.
vmaf -r ref.yuv -d dist.yuv -w 576 -h 324 -p 420 -b 10 -m path=hdr_model.json \
--color_range_ref limited --color_primaries_ref bt2020 --color_trc_ref pq --color_matrix_ref bt2020nc \
--color_range_dist limited --color_primaries_dist bt2020 --color_trc_dist pq --color_matrix_dist bt2020nc
Input read-ahead¶
vmaf reads the reference and the distorted input on two reader threads, each up to two frames ahead of scoring (ADR-1366). There is no flag to set. The measurements are in Research-1366.
Reading the files and copying each frame into a libvmaf picture then overlaps feature extraction, and the two inputs are read at the same time. Runs whose per-frame cost was mostly reading gain the most:
- At 3840x2160 8-bit 4:2:0,
--feature psnrdrops from about 7 to 8 ms to about 3.5 to 4 ms per frame on the CPU, with or without--threads. - The
psnr,motionandadmtwins on an Intel Arc B580 (--backend sycl) drop from about 8 ms to about 4 ms. - A run already limited by feature extraction, such as the default model on 16 CPU threads, runs at the same speed as before.
What stays the same¶
Read-ahead does not change what is scored:
- The scoring loop receives the same frames, in the same order and pairs, and hands them to libvmaf from the same thread as before. Scores are identical, including at
--precision max. --frame_cnt Nstops each reader afterNframes; nothing past frameNis read.--frame_skip_refand--frame_skip_distskip their frames before the readers start.- The exit codes are unchanged: a stream that ends early still exits 0 with the
ended beforewarning, and a failed read still exits 102 without writing a report.
What changes¶
| Aspect | Change |
|---|---|
| Memory | The picture pool holds four more pictures, two per input: about 50 MB at 3840x2160 8-bit 4:2:0, about 100 MB at 10-bit. The picture pool: N pictures pre-allocated line shown on a terminal counts them. |
| Threads | Two more threads exist while frames are being scored. |
| Diagnostics | A reader can reach a damaged frame of its input before the scoring loop stops at the end of the other input. The reader's own message, for example Error reading YUV frame data., is then printed although the run scores the common frames and exits 0. |
Main-thread fallback¶
Both inputs are read on the main thread, as before, when:
- on Linux and macOS, both paths name the same file, pipe or device (the same device and inode). Two readers of one pipe would each receive whichever frames they reached first.
--no-referenceopens the distorted input twice, so there it reads on the main thread; - on Windows, either input is not a regular file (a pipe or a console). Windows reports no inode to compare, and two separately opened regular files never share a read position;
- a reader thread cannot be created.
Preset bundles¶
These expand to a canonical model and feature list for AOM and Netflix common-test-conditions reports. For example, --aom_ctc v7.0 is equivalent to:
--model version=vmaf_v0.6.1:name=vmaf
--model version=vmaf_v0.6.1neg:name=vmaf_neg
--feature psnr=reduced_hbd_peak=true:enable_apsnr=true:min_sse=0.5
--feature ciede
--feature float_ssim=scale=1:enable_db=true:clip_db=true
--feature float_ms_ssim=enable_db=true:clip_db=true
--feature psnr_hvs
--feature cambi
# plus common_bitdepth=on (forces reference + distorted to the same bitdepth)
--aom_ctc proposed is deprecated and errors out with an explanation.
Tiny-AI flags¶
These flags load an ONNX tiny model alongside the classic models. See ../ai/inference.md for the full walkthrough and the per-model registry (model/tiny/registry.json, sha256 pins, known limitations).
| Flag | Default | Effect |
|---|---|---|
--tiny-model <path> | none | Load a .onnx tiny model alongside classic models. |
--tiny-device <ep> / --dnn-ep <ep> | auto | ONNX Runtime execution provider; see below. |
--tiny-threads <N> | 0 (ORT default) | CPU EP intra-op threads. |
--tiny-fp16 | off | Request fp16 I/O where the EP supports it. |
--tiny-model-verify | off | Require Sigstore-bundle verification of the loaded model; see Sigstore verification. |
--no-reference | off | No-reference (NR) mode; see NR mode. |
--tiny-codec, --tiny-preset, --tiny-crf | see below | Codec-context inputs; see Codec-context flags. |
--tiny-resize <mode> | disabled | Auto-resize for NCHW models; see Resize mode. |
Underscore aliases exist for every tiny flag (--tiny_model, --tiny_device, --tiny_threads, --tiny_fp16, --tiny_model_verify, --no_reference, --dnn_ep, --tiny_codec, --tiny_preset, --tiny_crf, --tiny_resize), for symmetry with the underscore flags upstream uses. --netflix_compat is the underscore alias of --netflix-compat.
--tiny-model composes with --model
Tiny-AI models are additional scores layered on top of the classic SVM/XGBoost prediction, not a replacement for it. Use --no_prediction to get tiny scores alone (ADR-0023).
Execution provider¶
--tiny-device and --dnn-ep are equivalent: both select the ONNX Runtime execution provider and write the same internal setting. --dnn-ep follows ORT terminology; --tiny-device predates the alias. Accepted values:
auto | cpu | cuda | openvino | openvino-npu | openvino-cpu | openvino-gpu
| coreml | coreml-ane | coreml-gpu | coreml-cpu | rocm
openvino-npu pins device_type=NPU (Intel AI-PC); openvino-cpu and openvino-gpu pin the OpenVINO CPU or GPU plugin with no fallback. See docs/ai/inference.md for the full matrix.
Quantised sibling models¶
When --tiny-model names <stem>.onnx, the loader inspects the companion sidecar <stem>.json. If the sidecar declares quant_mode != "fp32" (such as "dynamic", "static" or "qat"), the runtime loads the quantised sibling <stem>.int8.onnx when it is present and valid.
When --tiny-model names an explicit .int8.onnx path directly, the runtime loads that artifact directly without attempting to append a redundant .int8 suffix.
If the int8 artifact is missing, fails the op allowlist, or cannot be opened by the installed ONNX Runtime, the loader falls back to the fp32 baseline <stem>.onnx rather than failing the run (ADR-1032). The fallback is announced on the VMAF_LOG_LEVEL_DEBUG channel, which the CLI does not expose (it runs at VMAF_LOG_LEVEL_INFO), so it is silent on the command line by design. API callers that set VmafConfiguration.log_level = VMAF_LOG_LEVEL_DEBUG see which graph was opened.
No-reference mode¶
--no-reference puts the CLI into no-reference (NR) mode (ADR-0520):
--reference/-ris no longer required. The CLI opens the distorted source twice (twovideo_inputhandles backed by the same file), and the rank-4 tiny-model dispatch reads picture bytes from the slot that would have held the reference, so the model sees the distorted frame.--tiny-modelbecomes mandatory, because no classic NR scorer exists in the fork. Omitting it prints--no-reference requires --tiny-model; no classic NR scorer exists.- NR mode forces
--no_prediction. Classic SVM scorers, including the default model, consume FR feature columns (vif_*,adm2,motion2) that cannot be computed without a reference, so no classic model is scored. - The tiny model must accept a rank-4 single-luma input (
[1, 1, H, W]with fully resolved spatial dims matching your distorted source). Rank-2 feature-vector tiny models (ADR-0518) load but always score0.0in NR mode, because their input features are derived from the reference. - The JSON / XML / CSV report contains only the tiny-AI feature column the model wrote; no
pooled_metricsblock exists while--no_predictionis active.
Codec-context flags¶
--tiny-codec <name> # encoder identity for codec-conditioned tiny models
# (libx264, libx265, libsvtav1, libvpx-vp9, h264_nvenc, ...)
--tiny-preset <name> # encoder preset string (medium, slow, p4, 5, ...)
--tiny-crf <0..63> # CRF / QP integer; values above 63 clamp at 63
These flags drive vmaf_dnn_set_codec_context() on the tiny model, and --tiny-resize drives vmaf_dnn_set_resize_mode(); see api/dnn.md.
Codec-conditioned tiny models (for example the v2 ladder regressor) accept a small categorical block alongside the per-frame features: encoder identity, preset ordinal and CRF / QP. The CLI sets this block once at model-load time. Setting any of the three flags to a non-default value enables the path. See ADR-0522 for the categorical encoding rationale.
| Flag | Default | Notes |
|---|---|---|
--tiny-codec | none (required by codec-aware models) | Must match an entry of the model sidecar's encoder_vocab; the vocabulary differs per model (fr_regressor_v2 lists 11 encoders and unknown, fr_regressor_v3 16 encoders and no unknown). Common ffprobe aliases (h264, hevc, av1, vp9, vvc) are accepted. |
--tiny-preset | ordinal 5 (medium-equivalent) | Encoder-specific; mirrors train_fr_regressor_v2.py::PRESET_ORDINAL. A model trained with one preset value (fr_regressor_v3) ignores it and logs a warning. |
--tiny-crf | none (required with --tiny-codec / --tiny-preset) | Normalised as the model's sidecar declares: clamped to [0, 63] and divided by 63 by default, min-max over 19..37 for fr_regressor_v3 (ADR-1558). |
Unknown codec names are rejected
A --tiny-codec value that is not in the model's encoder_vocab stops the run: vmaf prints --tiny-codec '<name>' not found in model encoder_vocab and exits non-zero. A codec flag on a model that has no codec block fails the same way (--tiny-codec / --tiny-preset / --tiny-crf require a codec-aware tiny model). A codec-aware model run without --tiny-codec stops on the first frame (tiny model <name> is codec-aware: ...), and --tiny-codec or --tiny-preset without --tiny-crf stops at load (ADR-1520). Pass --tiny-codec unknown when the encoder is not known and the model's vocabulary has that entry.
Resize mode¶
--tiny-resize (ADR-0550) is required when the source frame size (--width / --height) differs from the tiny model's declared input shape. The value is checked at parse time: a typo prints --tiny-resize must be one of: bilinear, nearest, bicubic, disabled.
--tiny-resize | Filter | Score-stable? |
|---|---|---|
disabled | None; a size mismatch fails with -ERANGE (the default) | Strict |
bilinear | OpenCV INTER_LINEAR / torchvision BILINEAR | Yes, the convention used by every shipped NR / image-input model |
nearest | OpenCV INTER_NEAREST | Yes, deterministic floor of the source coordinate |
bicubic | Separable Catmull-Rom (a = -0.5); torchvision BICUBIC | Yes, exporter parity |
The three filter modes produce scores that differ by about 2% on the same input. Treat the filter as a model hyperparameter and pin it alongside the model checkpoint.
Sigstore bundle verification¶
--tiny-model-verify is a boolean flag (no argument). Before the model is loaded into ORT, the loader runs cosign verify-blob against the model's Sigstore bundle. On success the loader proceeds; on failure the process exits non-zero with a diagnostic on stderr (--tiny-model-verify: signature verification failed for <path> (errno <n>)).
The bundle is not derived from the model file name. The loader reads registry.json from the directory that holds the model (by default model/tiny/registry.json), finds the entry whose onnx file name matches, and uses that entry's sigstore_bundle field, for example dists_sq.onnx.sigstore.json. Verification therefore needs:
- a model registered in the
registry.jsonnext to it; - the bundle file named by that entry;
- the
cosignbinary on the host'sPATH; - a POSIX host. On Windows verification returns
-ENOSYSand the run fails.
Use it in production inference pipelines that need supply-chain verification of model integrity, for example a release runner that pulls a fork-signed .onnx from an artifact store and refuses to score with an unsigned or tampered model. For local development against an unsigned checkpoint, omit the flag.
Every failure exits non-zero before any inference runs: cosign missing from PATH, a missing or invalid bundle, an unregistered model, or a cosign verify-blob rejection (invalid signature, digest mismatch or rejected certificate identity). See ADR-0211 for the registry schema and ../ai/inference.md for the signed-model workflow.
Logging and misc¶
| Flag | Short | Effect |
|---|---|---|
--help | Print the flag reference to stdout and exit 0. | |
--quiet | -q | Disable the FPS meter when run in a TTY. |
--no_prediction | -n | Skip final model prediction; extract features only. Useful for feeding raw features into a custom pool. |
--netflix-compat | Restore Netflix-upstream legacy defaults: CPU backend, %.6f precision and the vmaf_v0.6.1 default model. Underscore alias --netflix_compat. See vmafx-cli.md. | |
--list-backends | Print the backends this binary was built with and which of them initialise here, as JSON on stdout, and exit 0; see Which backends this binary can use. | |
--version | -v | Print the libvmaf version and git SHA to stderr and exit 0. |
CUDA-initialization, luminance, SpEED and VIF diagnostics are complete, newline-terminated stderr records. The logger supplies the libvmaf ERROR level prefix, so the message bodies do not repeat Error:. Log consumers should match the level token and message body, not the old duplicate libvmaf ERROR Error: spelling from CUDA initialization failures.
Windows¶
UTF-8 paths¶
On Windows, VMAFx-owned file operations interpret path strings as UTF-8 and convert them to UTF-16 before calling the wide Windows runtime APIs. This covers reference and distorted inputs, --output, JSON and ONNX model paths, CAMBI heatmap directories and the paths used by the companion tools. Names with accented or CJK characters reach the exact requested file rather than an ANSI-code-page approximation. POSIX path handling is unchanged.
UTF-8 arguments¶
The vmaf and vmafx executables enter through wmain on Windows and convert every UTF-16 argument to strict UTF-8 before the shared CLI parser runs. This keeps non-ASCII input, output and model paths independent of the active ANSI code page. An argument containing an invalid UTF-16 sequence fails before scoring instead of being replaced or misdirected. POSIX argument handling is unchanged.
Limits¶
Internal conversions accept paths shorter than 4096 UTF-8 bytes; longer or malformed UTF-8 paths fail instead of being truncated. The vendored Pelorus CSV parser is a documented exception until its upstream source adopts the same contract. See ADR-1182 for the exact migrated surfaces and the original library/CLI scope split.
Console output¶
The interactive progress line (frame counter, spinner, FPS) is written to stderr whenever stderr is a TTY and --quiet is not set. The spinner uses Unicode braille glyphs and an ANSI erase-to-end-of-line sequence, which a Windows console does not render correctly by default: under the conhost default code page (cp437) each two-glyph frame decodes as six garbage characters, under cp936 as replacement boxes, and legacy conhost prints the erase sequence literally as <-[K.
Since ADR-1166 the CLI handles this itself. On Windows it:
- records the current console output code page and stderr console mode,
- switches the console to UTF-8 (
CP_UTF8) and enablesENABLE_VIRTUAL_TERMINAL_PROCESSING, - restores both on exit, including error exits, so your shell is left as it was found,
- and, if the console refuses either change, falls back to a pure-ASCII spinner (
|/-\\) and pads with spaces instead of emitting the erase sequence.
There is no flag for this and nothing to configure. --quiet still suppresses the progress line, and redirecting stderr to a file or pipe suppresses it too. On Linux and macOS the emitted bytes are unchanged. Reported upstream as Netflix/vmaf#743.
Exit codes¶
| Code | Meaning |
|---|---|
| 0 | Success, or --help / --version / --list-backends invocation. |
| 1 | Any parse / I/O / runtime error. vmaf writes a diagnostic to stderr before exiting. |
| 100 | Explicit --backend <name> requested but the backend is not compiled in or failed to initialise (ADR-0498, ADR-0543). |
| 101 | No frames were decoded (empty or too-short input, or a --frame_skip_* value past end-of-stream). vmaf writes no frames decoded ... to stderr. |
| 102 | An input stream failed to read (truncated file, unreadable media, I/O error). vmaf writes problem while reading pictures to stderr and writes no output file, so a partial score cannot be mistaken for a complete one (ADR-1262). |
| 234 (also other values) | libvmaf failed to score a frame it had read: a feature extractor refused the frame or its options (for example float_ms_ssim on a picture below 176x176, or an unsupported viewing geometry). The exit status is the libvmaf error code modulo 256 on every platform, as a non-negative value (-EINVAL is 234; Windows does not report the raw 32-bit negative code). vmaf writes problem scoring picture N: libvmaf returned E to stderr, after the libvmaf message that names the extractor; before 2026-10 it wrote problem reading pictures, which read like an input failure. |
Apart from these codes, libvmaf does not surface granular error codes at the process boundary: the specific VMAF_ERR_* code from the C API is logged to stderr but collapsed to exit 1 from the CLI.
Backend not available¶
A backend requested with --backend that is not compiled in is never replaced silently. For example, --backend cuda on a build without CUDA prints vmaf: --backend cuda requested but this libvmaf was built without cuda support; refusing to silently fall back to CPU (ADR-0498) and exits 100.
Shorter streams and write failures¶
A stream that simply ends earlier than its partner is not an error. vmaf writes "<path>" ended before "<path>". to stderr, scores the frames the two have in common and exits 0; scoring a shorter distorted clip against a longer reference is a supported use. Exit 102 is reserved for a read that failed.
A failed output-file write (bad path, full disk, permission denied) exits non-zero: vmaf writes problem writing output to <path> (err=<n>) to stderr, where <n> is the negative VMAF_ERR_* code, instead of exiting 0 over a stale or partial file.
Context cleanup¶
Context cleanup is part of success. The CLI makes at most two immediate vmaf_close() attempts. If both fail, it prints vmaf: context cleanup failed after 2 attempts (err=<n>); retaining dependent resources and exits non-zero. Imported backend state and models deliberately stay alive until process exit instead of being freed beneath the retained context.
The vmaf_bench and vmaf_vpl tools use the same two-attempt rule and the same diagnostic shape with their own command prefix. Embedders should follow the retry ownership contract in the C API.
Worked example: the upstream golden pair¶
Download the canonical Netflix test pair from upstream:
curl -sSLO https://github.com/Netflix/vmaf_resource/raw/master/python/test/resource/yuv/src01_hrc00_576x324.yuv
curl -sSLO https://github.com/Netflix/vmaf_resource/raw/master/python/test/resource/yuv/src01_hrc01_576x324.yuv
Run VMAF (pinned to vmaf_v0.6.1) plus PSNR:
./build/tools/vmaf \
--reference src01_hrc00_576x324.yuv \
--distorted src01_hrc01_576x324.yuv \
--width 576 --height 324 --pixel_format 420 --bitdepth 8 \
--model version=vmaf_v0.6.1 \
--feature psnr \
--output scores.xml
On a terminal, stderr shows the banner, the progress meter and the pooled score (nothing is printed when stderr is redirected):
The head of scores.xml (the root version attribute is the vmaf --version string, for example v1.0.0-rc.2-310-g1b1663830; the metric names and values shown are those of the Netflix pair):
<VMAF version="<version>">
<params qualityWidth="576" qualityHeight="324" />
<fyi fps="..." />
<frames>
<frame frameNum="0" integer_adm2="0.962084" ... psnr_y="34.760779" ... vmaf="83.856284" />
...
</frames>
<pooled_metrics>
<metric name="vmaf" min="71.174759" max="87.180962" mean="76.667831" harmonic_mean="76.508907" />
...
</pooled_metrics>
</VMAF>
With --precision max the pooled mean prints as 76.667831491355784. Without --model version=vmaf_v0.6.1, the default model gives a pooled mean of 82.816060 for the same pair.
The vmaf_v0.6.1 pooled mean on this pair is one of the three Netflix CPU goldens preserved as a required CI gate. The CLI path is pinned to 76.66783025 in python/test/vmafexec_test.py; see ADR-0024.
Flag interactions and pitfalls¶
.yuvwithout geometry.--reference foo.yuvwithout--width/--height/--pixel_format/--bitdeptherrors out..y4mcarries geometry in its header;.yuvdoes not.- Duplicate model names. Each
--modelneeds a uniquename=. If the same built-in version is loaded twice, setname=on at least one. --no_predictionwith--model.--no_predictionskips model prediction but not loading: the model still selects which features to extract. To extract only the--featurelist, omit--modeland pass--no_prediction.- Default
%.6frounding. The default (and--precision legacy) hides differences of about 1e-6 that--precision=maxshows. Usemaxto compare scores numerically; the default exists for byte-for-byte agreement with pre-fork Netflix output, which the CPU golden gate depends on. --tiny-modelvs--model. They compose; see the note under Tiny-AI flags.--no_cuda+--no_sycltogether. Forces CPU-only even on a build with both GPU backends compiled in. Useful for cross-backend diff sessions.
Related¶
- bench.md —
vmaf_benchmicro-benchmark harness. - vmaf-perShot.md — per-shot CRF predictor sidecar (ADR-0222).
- ffmpeg.md — using the VMAF filter inside
ffmpeg. - python.md — Python bindings for the CLI.
- precision.md — dedicated
--precisionflag walkthrough. - ../backends/index.md — runtime backend dispatch rules.
- ../metrics/features.md — per-feature identifiers and options.
- ../ai/inference.md — tiny-AI inference walkthrough.
- ADR-0119 (current precision default; supersedes ADR-0006), ADR-0023, ADR-0024, ADR-0100.
Former section names¶
Older pages and records link to these headings; each points to the section that now holds its content.
Tiny-AI flags (fork-added)¶
Now under Tiny-AI flags.
Codec-context flags (fork-added)¶
Now under Codec-context flags.
History¶
Behaviour that older builds had, kept so old logs and scripts can be interpreted.
--threadswith a GPU backend (ADR-1197). Builds before this change aborted withlibvmaf ERROR context could not be synchronizedand exit 234 whenever--threadswas combined with--backend cudaor--backend sycl, for every thread count including--threads 1. The message was misleading: the GPU context was healthy and the failure came from the feature-extractor flush. If you see it, you are on an older build.testdata/bench_all.shpins--threads 1, so GPU rows produced by older builds of that harness were failures rather than measurements.- Option-string escapes (ADR-1190, ADR-1355). Before ADR-1190 there was no escape mechanism:
path=C:\models\m.jsonwas rejected withbad option string "\models\m.json", andpath=/a/dir=eq/m.jsonwas silently truncated to/a/dir. Until ADR-1355 the key escapes also applied to values, so..\..\models\m.jsonwas read as....\models\m.json,\\server\shareas\server\share, andC:\models\.cacheasC:\models.cache. - Default model (ADR-1169). The default was
vmaf_v0.6.1before this fork moved tovmaf_v1.0.16_3d0h. - Proposed:
--gpu-calibrated(ADR-0234). A future flag would opt into a per-architecture ULP calibration head that maps raw GPU scores to their CPU-equivalent values, closing the cross-backend divergence of about 1e-4 that currently sits withinplaces=4tolerance. It is not shipped: the flag does not exist and the calibration model is not trained. The ADR lists the measurement gates that must clear first.