vmaf-tune AV1 encoders: libaom-av1, libsvtav1 and SVT-AV1-HDR¶
Use --encoder libaom-av1 for the AV1 reference encoder (slow, best compression) and --encoder libsvtav1 for SVT-AV1 (fast, good for batches). SVT-AV1-HDR is a runtime variant of libsvtav1, not a third adapter. This page covers the two adapters, how they compare and how to tune the SVT-AV1-HDR fork. The registry of all adapters is vmaf-tune-codec-adapters.md.
Quick start¶
Sweep SVT-AV1 over two presets and three CRFs:
vmaf-tune corpus \
--source ref.yuv \
--width 1920 --height 1080 --pix-fmt yuv420p \
--framerate 24 --duration 10 \
--encoder libsvtav1 \
--preset medium --preset slow \
--crf 28 --crf 35 --crf 42 \
--output corpus_av1.jsonl
The corpus row records the preset name ("medium"). The FFmpeg argv carries SVT-AV1's integer (-preset 7).
Adapter parameters¶
| Property | libaom-av1 | libsvtav1 |
|---|---|---|
| FFmpeg encoder | libaom-av1 | libsvtav1 |
| Quality knob | -crf | -crf |
| CRF accepted | 0..63 | 20..50 |
| Default CRF | 35 | 35 |
| Speed knob | -cpu-used 0..9 | -preset 0..13 |
| Preset names accepted | 10 (placebo ... ultrafast) | 8 (placebo ... veryfast) |
| Two-pass | yes | no (CRF mode) |
| Saliency ROI | patched -qpfile bridge | -svtav1-params qp-file= |
| ADR | 0279 | 0294 |
SVT-AV1 itself accepts CRF 0..63. The adapter validates the absolute range first and then the 20..50 window, so --crf 10 fails with crf 10 outside Phase A range [20, 50] before FFmpeg starts.
Preset names¶
Both adapters accept the shared x264-style names and translate them:
--preset | libaom -cpu-used | SVT-AV1 -preset |
|---|---|---|
placebo | 0 | 0 |
slowest | 1 | 1 |
slower | 2 | 3 |
slow | 3 | 5 |
medium | 4 (default) | 7 (SVT-AV1 default) |
fast | 5 | 9 |
faster | 6 | 11 |
veryfast | 7 | 13 (fastest) |
superfast | 8 | not accepted |
ultrafast | 9 (fastest) | not accepted |
The SVT-AV1 map is closed and order-stable (ADR-0294).
The argv the adapters emit for a medium CRF-35 cell:
ffmpeg -i ref.y4m -c:v libaom-av1 -cpu-used 4 -crf 35 -an -y out.mkv
ffmpeg -i ref.y4m -c:v libsvtav1 -preset 7 -crf 35 -an -y out.mkv
libaom vs SVT-AV1¶
Both target the AV1 bitstream at different points of the speed and quality curve. Use the table as a rough guide and keep the real numbers in your own sweep output.
| Concern | libaom-av1 | libsvtav1 |
|---|---|---|
| Encode wall time at a matched preset | meaningfully slower | meaningfully faster |
| Quality at slow presets, matched bitrate | slightly higher in AOM benchmarks | slightly lower |
| Quality at fast presets | comparable | comparable, sometimes ahead |
| Best fit | offline, high-quality archive encodes | live, batch, large catalogues |
Corpus rows record the (encoder, preset, crf, vmaf_score, encode_time_ms, bitrate_kbps) tuple, so the predictors can pick whichever encoder dominates the relevant region of the rate-distortion plane for a source. To put both on one report, run vmaf-tune compare --encoders libaom-av1,libsvtav1.
SVT-AV1-HDR variant¶
SVT-AV1-HDR is a BSD-3-Clause-Clear fork of psy-ex/svt-av1-psy that adds perceptual and HDR-oriented rate-distortion features to SVT-AV1. By decision (ADR-0644) there is no svtav1-hdr adapter token ('svtav1-hdr' in known_codecs() is False), because FFmpeg exposes the fork through the same libsvtav1 wrapper as mainline SVT-AV1.
Select it as the runtime variant libsvtav1@svt-av1-hdr and bind that token to an FFmpeg binary linked against the fork:
vmaf-tune compare \
--src hdr_source.mkv --width 3840 --height 2160 --pix-fmt yuv420p10le \
--target-vmafs 94,96 \
--encoders libsvtav1,libsvtav1@svt-av1-hdr \
--ffmpeg-bin /opt/ffmpeg-main/bin/ffmpeg \
--encoder-ffmpeg-bin libsvtav1@svt-av1-hdr=/opt/ffmpeg-svtav1-hdr/bin/ffmpeg \
--json-sidecar \
--output hdr-comparison.html
Mainline and the fork then appear as two curves in one report. The row label stays readable (codec = libsvtav1@svt-av1-hdr) and the provenance records adapter = libsvtav1, runtime_variant = svt-av1-hdr and the bound ffmpeg_bin. Tokens without a binding use the global --ffmpeg-bin. No pinned SVT-AV1-HDR container build ships with the project; adding one is an optional follow-up that needs its own ADR.
The variant inherits the libsvtav1 contract: CRF 20..50 and presets named as above. The fork itself accepts CRF 1..70 in 0.25 steps (default 35) and presets -3..13 (default 4). Those extensions are not reachable from vmaf-tune, because the adapter validates before FFmpeg is invoked.
Passing SVT-AV1-HDR parameters¶
The fork's extra parameters travel as one colon-separated -svtav1-params key=value:key=value string that FFmpeg's libsvtav1 wrapper forwards verbatim. vmaf-tune composes the argv as adapter.ffmpeg_codec_args(...), then adapter.extra_params(), then request.extra_params. There are three places to inject the string:
- Python API:
EncodeRequest(..., extra_params=("-svtav1-params", "tune=0:cdef-scaling=12")). - An adapter subclass whose
extra_params()returns the same pair, registered under its own name. - CLI:
vmaf-tune encode-profile --extra-ffmpeg-arg=-svtav1-params --extra-ffmpeg-arg=tune=0:cdef-scaling=12.
vmaf-tune compare has no raw-argv passthrough flag. A compare sweep runs the fork with its own defaults plus the HDR signalling below.
Two cautions
The HDR path (vmaftune.hdr.hdr_codec_args) already emits -svtav1-params color-primaries=9:transfer-characteristics=16|18:matrix-coefficients=9:color-range=0|1 for libsvtav1, plus mastering-display=...:content-light=... when the source carries them. A second -svtav1-params option on the same command line replaces that value instead of merging, so fold your tuning keys into one string together with the colour keys.
The wrapper parses -svtav1-params last. A crf= or preset= key inside it silently overrides the -crf / -preset the search loop is steering, so never put those two keys in the string.
Tuning knobs¶
Everything below is taken from the upstream README and Docs/Parameters.md at commit 00333404f455471aaa6ee2c927cac3c93efb76e3 (2026-09-01). The fork tracks mainline SVT-AV1 and its defaults move, so re-check those pages before relying on a default.
-svtav1-params key | Range | Default | Purpose |
|---|---|---|---|
tune | 0..5 | 1 | 0 = VQ (perceptual, README recommends it with any CRF, presets 2-6), 1 = PSNR, 2 = SSIM, 3 = IQ (still images, pair with --avif 1), 4 = MS-SSIM, 5 = Film Grain (CRF 20-40, preset 2; equals tune=0:enable-tf=0:enable-restoration=0:enable-cdef=0:complex-hvs=1:tx-bias=1:ac-bias=4.00). |
enable-variance-boost | 0..1 | 1 | Variance-based superblock boost (AQ modes 0 and 2); on by default in the fork, off in mainline. |
variance-boost-strength | 1..4 | 2 | Boost curve strength: 1 mild, 2 gentle, 3 medium, 4 aggressive. |
variance-octile | 1..8 | 5 | Selectivity: how much of a superblock must be low-variance (in eighths) before it is boosted; lower values raise bitrate. |
variance-boost-curve | 0..3 | 0 | 0 default, 1 alternative, 2 still image, 3 HDR PQ curve; 3 is auto-selected when transfer-characteristics=16 (PQ). |
ac-bias | 0.0..8.0 | 1.0 | Psychovisual RD bias preserving high-frequency energy. |
tx-bias | 0..3 | 0 | Sharpness-biased transform decisions: 0 off, 1 full, 2 transform size only, 3 interpolation filter only. |
sharp-tx | 0..1 | 1 | Sharp transform optimisations; on by default to complement ac-bias, upstream recommends 0 when ac-bias=0. |
complex-hvs | 0..1 | 0 | Highest-complexity HVS model for mode decision. |
qp-scale-compress-strength | 0.0..8.0 | 1.0 | Compresses the per-temporal-layer QP range for more consistent quality (0.0 = mainline behaviour). |
hbd-mds | 0..2 | 0 | Mode-decision bit depth: 0 preset default, 1 force 10-bit, 2 adaptive 8/10-bit. |
cdef-scaling | 1..30 | 15 | CDEF strength scale (1 = 0.06x, 30 = 2x); 10..12 reported useful for sharper output. |
noise-adaptive-filtering | 0..4 | 2 | Disable CDEF / restoration on detected noise: 0 off, 1 both, 2 tune default, 3 CDEF only, 4 restoration only. |
noise-norm-strength | 0..4 | 1 | Boost selected AC coefficients on fine textures. |
tf-strength | 0..4 | 1 | Alt-ref temporal filtering strength (each step 2x; 3 equals the mainline default). |
kf-tf-strength | 0..4 | 1 | Same as tf-strength, keyframes only. |
luminance-qp-bias | 0..100 | 0 | Frame-level QP bias from average luma (dark-scene quality). |
sharpness | -7..7 | 1 | Deblocking loop-filter sharpness and RD bias (Docs/Parameters.md prose still says 0; the parameter table and README say 1). |
chroma-qm-min / chroma-qm-max | 0..15 | 8 / 15 | Chroma quantisation-matrix flatness bounds, decoupled from luma. |
max-tx-size | 32, 64 | 64 | Cap on transform block size. |
adaptive-film-grain | 0..1 | 1 | Film-grain block size follows input resolution. |
alt-ssim-tuning | 0..1 | 0 | Alternative SSIM RD path; only acts with tune=2. |
noise | 0..200 | 0 | Synthesised film-grain table strength (50 is roughly --film-grain 50). |
noise-chroma | -1..200 | -1 | Chroma grain strength; -1 = about 60 % of noise, 0 off. |
noise-chroma-from-luma | 0..1 | 0 | Derive chroma grain from the luma plane (grain also on greyscale content). |
noise-size | -1..13 | -1 | Grain particle size; -1 = auto from resolution. |
dolby-vision-rpu / hdr10plus-json | path | none | Dolby Vision RPU / HDR10+ JSON metadata; need the fork built with enable-libdovi / enable-hdr10plus. |
Two-pass and saliency¶
- Two-pass. SVT-AV1 forbids multi-pass in CRF mode (checked against v4.1.0:
Svt[error]: CRF does not support multi-pass. Use single pass.).libsvtav1therefore declaressupports_two_pass = Falseand--two-passruns single-pass.libaom-av1uses FFmpeg's-pass/-passlogfileand does support it. See multi-pass encoding. - Saliency ROI.
libaom-av1uses the patched FFmpeg-qpfilebridge;libsvtav1uses a 64x64 super-block offset map through-svtav1-params qp-file=. See saliency-aware encoding. - HDR. Both adapters get HDR colour tags from
--auto-hdr. See HDR knobs and clip sampling.
See also¶
vmaf-tune.md: the base tool.vmaf-tune-codec-adapters.md: the adapter registry and contract.vmaf-tune-codec-software.mdandvmaf-tune-codec-hardware.md: the other adapter families.- ADR-0644: runtime variants.