Skip to content

VAAPI

current

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 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.

Terminal window
vainfo --display drm --device /dev/dri/renderD128

Look 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.

Terminal window
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mkv -vf 'format=nv12,hwupload' -c:v hevc_vaapi -global_quality 24 -c:a copy output.mkv

VAAPI 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:

Terminal window
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.mkv

AV1 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.

Terminal window
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.

Terminal window
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.mkv

Decode, 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.

OptionWhat it does
-global_qualityConstant-quality target (ICQ or CQP). h264_vaapi and hevc_vaapi also have -qp, which forces CQP.
-rc_modeForce CQP, CBR, VBR, ICQ, QVBR or AVBR. Default auto.
-b:v, -maxrate, -bufsizeBitrate constraints.
-compression_levelSpeed/quality trade-off passed to the driver as its quality level; higher is faster and worse. The range is driver-specific.
-bf, -b_depthB-frames and B-pyramid depth. Some drivers ignore or reject them.
-low_power 1Use the fixed-function low-power encoder. Fewer features; some other options may be rejected.
-g, -idr_intervalGOP length; -idr_interval N makes only every Nth I-frame an IDR (open GOP).
-async_depthFrames in flight.
  • A profile with only a decode entry point cannot encode. Check vainfo before blaming FFmpeg.
  • hwupload needs 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_mode or -global_quality changes on AMD.

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.

ParameterTypeDefaultMeaningRange / named values
-idr_intervalint0Number of non-key I-frames between key frames; 0 makes every I-frame a key frame.0 to INT_MAX
-b_depthint1B-frame reference depth: 1 = flat B-frames, higher builds a hierarchy. Needs -bf.1 to INT_MAX
-async_depthint2Frames in flight on the GPU; raise it for single-stream throughput.1 to 64
-low_powerbooleanfalseUse the low-power encode entrypoint (VDEnc on Intel). Some GPUs have only this one, and it can lack features.0 to 1
-max_frame_sizeint0Largest encoded frame, in bytes; 0 = no limit.0 to 2.68435e+08
-rc_modeintautoRate 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
-blbrcbooleanfalseBlock-level rate control (finer bit allocation within a frame) where the driver supports it.0 to 1
-profileint-99AV1 profile: main, high, professional. -99 chooses from the input format.-99 to 255; main=0, high=1, professional=2
-tierintmainAV1 tier: main or high.0 to 1; main=0, high=1
-levelint-99AV1 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
-tilesimage_sizenot exposedTile layout as columns×rows, e.g. 2x2; unset uses the minimum the resolution needs.—
-tile_groupsint1Number 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 parameterDefault
-b0
-bf2
-g120
-qmin1
-qmax255
-refs0