VAAPI
VAAPI is the Linux API for GPU video encoding and decoding. Intel GPUs use the intel-media-driver (iHD) backend and AMD GPUs use Mesa’s radeonsi backend. FFmpeg’s wrappers are h264_vaapi, hevc_vaapi, vp9_vaapi, av1_vaapi and a few older codecs. Which of them work depends on the GPU, not on FFmpeg. NVIDIA GPUs have no VAAPI encoder; use NVENC.
Unlike NVENC and AMF, VAAPI is a common API over different hardware, so the same command can behave differently on Intel and AMD. It is the usual Linux route for Intel Quick Sync and for AMD, where AMF is awkward on Linux.
Hardware or software encoder?
Section titled “Hardware or software encoder?”Hardware encoders are quick and cheap on power but lose to x264, x265 and SVT-AV1 at slow presets in quality per bit. Use VAAPI for fast transcodes, recording and streaming. Use a software encoder for archival work. More in NVENC: hardware or software.
Check what your GPU can encode
Section titled “Check what your GPU can encode”vainfo --display drm --device /dev/dri/renderD128Look for the profile with VAEntrypointEncSlice, for example VAProfileHEVCMain : VAEntrypointEncSlice. VAEntrypointEncSliceLP is the low-power engine, which is what -low_power 1 selects. A profile listed only as VAEntrypointVLD is decode-only. vainfo ships in libva-utils.
AV1 encode needs an Intel Arc or Meteor Lake-or-newer GPU, or an AMD RDNA 3 or newer GPU (or a Phoenix-or-newer APU). See QSV and AMF for the generation lists.
Quality-oriented encode
Section titled “Quality-oriented encode”ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mkv -vf 'format=nv12,hwupload' -c:v hevc_vaapi -global_quality 24 -c:a copy output.mkvVAAPI only accepts frames in GPU memory, so hwupload after a format=nv12 conversion is required with software-decoded input. -global_quality alone is enough for constant quality: FFmpeg tries ICQ and falls back to CQP when the driver has no ICQ, as with Mesa on AMD. Lower is better. Do not combine it with -b:v, which asks for QVBR instead. The numbers are not comparable to CRF.
For AV1:
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mkv -vf 'format=nv12,hwupload' -c:v av1_vaapi -rc_mode CQP -global_quality 100 -c:a copy output.mkvAV1 uses the 0–255 quantizer, so values run higher than for HEVC, and the explicit -rc_mode CQP stops FFmpeg from picking ICQ, whose scale is 1–51. For 10-bit use format=p010le,hwupload.
Bitrate-targeted
Section titled “Bitrate-targeted”ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mkv -vf 'format=nv12,hwupload' -c:v hevc_vaapi -b:v 6M -maxrate 9M -bufsize 12M -c:a copy output.mkv-b:v with a larger -maxrate is VBR; equal values give CBR. A bare -b:v with no -bufsize tries AVBR first, which ignores buffer constraints. Force a mode with -rc_mode CQP|CBR|VBR|ICQ|QVBR|AVBR when the automatic choice is wrong. Drivers support only a subset, and FFmpeg errors out if you request an unsupported one.
Full-GPU pipeline
Section titled “Full-GPU pipeline”ffmpeg -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device /dev/dri/renderD128 -i input.mkv -vf scale_vaapi=w=1920:h=1080 -c:v hevc_vaapi -global_quality 24 output.mkvDecode, scale and encode stay on the GPU. Filters that are not VAAPI filters need hwdownload,format=nv12 first. The decoder must support the input codec and profile, or the command fails at decode; fall back to the software-decode command above.
Options that matter
Section titled “Options that matter”| Option | What it does |
|---|---|
-global_quality | Constant-quality target (ICQ or CQP). h264_vaapi and hevc_vaapi also have -qp, which forces CQP. |
-rc_mode | Force CQP, CBR, VBR, ICQ, QVBR or AVBR. Default auto. |
-b:v, -maxrate, -bufsize | Bitrate constraints. |
-compression_level | Speed/quality trade-off passed to the driver as its quality level; higher is faster and worse. The range is driver-specific. |
-bf, -b_depth | B-frames and B-pyramid depth. Some drivers ignore or reject them. |
-low_power 1 | Use the fixed-function low-power encoder. Fewer features; some other options may be rejected. |
-g, -idr_interval | GOP length; -idr_interval N makes only every Nth I-frame an IDR (open GOP). |
-async_depth | Frames in flight. |
Pitfalls
Section titled “Pitfalls”- A profile with only a decode entry point cannot encode. Check
vainfobefore blaming FFmpeg. hwuploadneeds a device: use-vaapi_device(or-init_hw_device/-filter_hw_device) when decoding in software.- Pick the right render node (
/dev/dri/renderD128,renderD129, …) on systems with an iGPU and a discrete GPU. - Behaviour differs across drivers. A command tuned on Intel may need
-rc_modeor-global_qualitychanges on AMD.
Full option reference
Section titled “Full option reference”Every private option of av1_vaapi in FFmpeg 9.0.2. The driver may support fewer rate-control modes and profiles than FFmpeg can name; vainfo lists them. INT_MAX is 2147483647.
Private options
Section titled “Private options”| Parameter | Type | Default | Meaning | Range / named values |
|---|---|---|---|---|
-idr_interval | int | 0 | Number of non-key I-frames between key frames; 0 makes every I-frame a key frame. | 0 to INT_MAX |
-b_depth | int | 1 | B-frame reference depth: 1 = flat B-frames, higher builds a hierarchy. Needs -bf. | 1 to INT_MAX |
-async_depth | int | 2 | Frames in flight on the GPU; raise it for single-stream throughput. | 1 to 64 |
-low_power | boolean | false | Use the low-power encode entrypoint (VDEnc on Intel). Some GPUs have only this one, and it can lack features. | 0 to 1 |
-max_frame_size | int | 0 | Largest encoded frame, in bytes; 0 = no limit. | 0 to 2.68435e+08 |
-rc_mode | int | auto | Rate control: CQP, CBR, VBR, ICQ, QVBR, AVBR. auto uses CQP with -q:v, ICQ with -global_quality (QVBR if -b:v is also set), CBR when -b:v equals -maxrate, otherwise AVBR or VBR; with no rate options, ICQ or CQP. | 0 to 6; auto=0, CQP=1, CBR=2, VBR=3, ICQ=4, QVBR=5, AVBR=6 |
-blbrc | boolean | false | Block-level rate control (finer bit allocation within a frame) where the driver supports it. | 0 to 1 |
-profile | int | -99 | AV1 profile: main, high, professional. -99 chooses from the input format. | -99 to 255; main=0, high=1, professional=2 |
-tier | int | main | AV1 tier: main or high. | 0 to 1; main=0, high=1 |
-level | int | -99 | AV1 level (seq_level_idx); -99 chooses automatically. | -99 to 31; 2.0=0, 2.1=1, 3.0=4, 3.1=5, 4.0=8, 4.1=9, 5.0=12, 5.1=13, 5.2=14, 5.3=15, 6.0=16, 6.1=17, 6.2=18, 6.3=19 |
-tiles | image_size | not exposed | Tile layout as columns×rows, e.g. 2x2; unset uses the minimum the resolution needs. | — |
-tile_groups | int | 1 | Number of tile groups per frame. | 1 to 4096 |
Codec-specific generic initialization overrides
Section titled “Codec-specific generic initialization overrides”The wrapper replaces these generic FFmpeg defaults for this encoder. -b is in bits/s; -g and
-bf count frames. -1, and 0 for -b and -refs, leave the value to the preset, driver or
rate-control logic.
| Generic parameter | Default |
|---|---|
-b | 0 |
-bf | 2 |
-g | 120 |
-qmin | 1 |
-qmax | 255 |
-refs | 0 |