{
  "schemaVersion": 1,
  "contentVersion": "ca42e61ede0a24f789d7287a0001244ad22f4abf",
  "id": "docs/tools/hardware-encoders/vaapi",
  "collection": "docs",
  "title": "VAAPI",
  "description": "VAAPI is the Linux hardware encoding API for Intel and AMD GPUs, used from FFmpeg as h264_vaapi, hevc_vaapi and av1_vaapi.",
  "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/",
  "apiUrl": "https://encode.wiki/api/v1/documents/docs/tools/hardware-encoders/vaapi.json",
  "markdownUrl": "https://encode.wiki/api/v1/markdown/docs/tools/hardware-encoders/vaapi.md",
  "status": "current",
  "tags": [],
  "license": "CC BY-SA 4.0",
  "dates": {
    "lastVerified": "2026-10-08T00:00:00.000Z"
  },
  "authors": [],
  "sources": [
    {
      "title": "FFmpeg 9.0.2 common VAAPI encoder code and rate-control selection",
      "url": "https://github.com/FFmpeg/FFmpeg/blob/n9.0.2/libavcodec/vaapi_encode.c",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "FFmpeg 9.0.2 AV1 VAAPI options",
      "url": "https://github.com/FFmpeg/FFmpeg/blob/n9.0.2/libavcodec/vaapi_encode_av1.c",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "FFmpeg 9.0.2 encoder documentation (VAAPI encoders)",
      "url": "https://github.com/FFmpeg/FFmpeg/blob/n9.0.2/doc/encoders.texi",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    },
    {
      "title": "Mesa VA-API frontend (supported rate-control modes)",
      "url": "https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/gallium/frontends/va/config.c",
      "accessedAt": "2026-10-08T00:00:00.000Z"
    }
  ],
  "headings": [
    {
      "depth": 2,
      "text": "Hardware or software encoder?",
      "anchor": "hardware-or-software-encoder"
    },
    {
      "depth": 2,
      "text": "Check what your GPU can encode",
      "anchor": "check-what-your-gpu-can-encode"
    },
    {
      "depth": 2,
      "text": "Quality-oriented encode",
      "anchor": "quality-oriented-encode"
    },
    {
      "depth": 3,
      "text": "Bitrate-targeted",
      "anchor": "bitrate-targeted"
    },
    {
      "depth": 2,
      "text": "Full-GPU pipeline",
      "anchor": "full-gpu-pipeline"
    },
    {
      "depth": 2,
      "text": "Options that matter",
      "anchor": "options-that-matter"
    },
    {
      "depth": 2,
      "text": "Pitfalls",
      "anchor": "pitfalls"
    },
    {
      "depth": 2,
      "text": "Full option reference",
      "anchor": "full-option-reference"
    },
    {
      "depth": 3,
      "text": "Private options",
      "anchor": "private-options"
    },
    {
      "depth": 3,
      "text": "Codec-specific generic initialization overrides",
      "anchor": "codec-specific-generic-initialization-overrides"
    }
  ],
  "sections": [
    {
      "id": "_preamble",
      "title": "Page introduction",
      "depth": 0,
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/_preamble.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/_preamble.md",
      "checksum": "aa9a1b7f29e53188ef31e767ab4cbabb41625d8020a380d7ffe11542a63564a8",
      "bytes": 682
    },
    {
      "id": "hardware-or-software-encoder",
      "title": "Hardware or software encoder?",
      "depth": 2,
      "anchor": "hardware-or-software-encoder",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#hardware-or-software-encoder",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/hardware-or-software-encoder.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/hardware-or-software-encoder.md",
      "checksum": "83b57013bdde3352b742048b0fc8f882dd000c734ef7425b1e4369d07cfb07c8",
      "bytes": 456
    },
    {
      "id": "check-what-your-gpu-can-encode",
      "title": "Check what your GPU can encode",
      "depth": 2,
      "anchor": "check-what-your-gpu-can-encode",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#check-what-your-gpu-can-encode",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/check-what-your-gpu-can-encode.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/check-what-your-gpu-can-encode.md",
      "checksum": "46a4263e8054a41ba55f9d3a11edfeab2d5624db698532f88cdbf20ef5def250",
      "bytes": 667
    },
    {
      "id": "quality-oriented-encode",
      "title": "Quality-oriented encode",
      "depth": 2,
      "anchor": "quality-oriented-encode",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#quality-oriented-encode",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/quality-oriented-encode.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/quality-oriented-encode.md",
      "checksum": "2357db10626709e5546f0b03df713365bfce55063d22a2d388e561158544df70",
      "bytes": 1444
    },
    {
      "id": "bitrate-targeted",
      "title": "Bitrate-targeted",
      "depth": 3,
      "anchor": "bitrate-targeted",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#bitrate-targeted",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/bitrate-targeted.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/bitrate-targeted.md",
      "checksum": "9ae9c88ceee7e2f65a5d09a3fc96a5bba3175e7ede1e82f4e7cced936de1f9c4",
      "bytes": 511
    },
    {
      "id": "full-gpu-pipeline",
      "title": "Full-GPU pipeline",
      "depth": 2,
      "anchor": "full-gpu-pipeline",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#full-gpu-pipeline",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/full-gpu-pipeline.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/full-gpu-pipeline.md",
      "checksum": "022157ffd6eb17e7c7bdf5317507bb8896be10498f9467371347ebd83c59f8ca",
      "bytes": 457
    },
    {
      "id": "options-that-matter",
      "title": "Options that matter",
      "depth": 2,
      "anchor": "options-that-matter",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#options-that-matter",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/options-that-matter.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/options-that-matter.md",
      "checksum": "cbbc6280502b61320917a44c9d8249cb4ddf57c97081caa3dce05852a87c0066",
      "bytes": 836
    },
    {
      "id": "pitfalls",
      "title": "Pitfalls",
      "depth": 2,
      "anchor": "pitfalls",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#pitfalls",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/pitfalls.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/pitfalls.md",
      "checksum": "eb29109c0bd99f377b89f27ff68d3d9b7730e7c9f70a3303284a71f7f2f551f6",
      "bytes": 462
    },
    {
      "id": "full-option-reference",
      "title": "Full option reference",
      "depth": 2,
      "anchor": "full-option-reference",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#full-option-reference",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/full-option-reference.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/full-option-reference.md",
      "checksum": "02d1bb15b7118a36f0b7f4fb90d3a9bc91a7e4b021f5f999a601c722c5f6eeb9",
      "bytes": 2733
    },
    {
      "id": "private-options",
      "title": "Private options",
      "depth": 3,
      "anchor": "private-options",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#private-options",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/private-options.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/private-options.md",
      "checksum": "e3891d310b82bcd8eabd8f48d39848cf6f364446b46de3e314774453fbbf6eb3",
      "bytes": 2041
    },
    {
      "id": "codec-specific-generic-initialization-overrides",
      "title": "Codec-specific generic initialization overrides",
      "depth": 3,
      "anchor": "codec-specific-generic-initialization-overrides",
      "canonicalUrl": "https://encode.wiki/tools/hardware-encoders/vaapi/#codec-specific-generic-initialization-overrides",
      "apiUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/codec-specific-generic-initialization-overrides.json",
      "markdownUrl": "https://encode.wiki/api/v1/sections/docs/tools/hardware-encoders/vaapi/codec-specific-generic-initialization-overrides.md",
      "checksum": "dd3c223e884447960b87054d1908b9f1b4dc1e720df85c406358e5d89ed4ab83",
      "bytes": 449
    }
  ],
  "outboundReferences": [
    "/tools/hardware-encoders/amf/",
    "/tools/hardware-encoders/amf/#which-hardware-supports-what",
    "/tools/hardware-encoders/nvenc/",
    "/tools/hardware-encoders/nvenc/#hardware-or-software-encoder",
    "/tools/hardware-encoders/qsv/",
    "/tools/hardware-encoders/qsv/#which-hardware-supports-what",
    "/tools/software-encoders/svt-av1/",
    "/tools/software-encoders/x264/",
    "/tools/software-encoders/x265/"
  ],
  "checksum": "01c46a915c21bd2b82294cbee8b1f7bdf40ec4f2e794c3995f4277fdc0ea318b",
  "contentFormat": "markdown",
  "markdown": "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](/tools/hardware-encoders/nvenc/).\n\nUnlike 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](/tools/hardware-encoders/qsv/) and for AMD, where [AMF](/tools/hardware-encoders/amf/) is awkward on Linux.\n\n## Hardware or software encoder?\n\nHardware encoders are quick and cheap on power but lose to [x264](/tools/software-encoders/x264/), [x265](/tools/software-encoders/x265/) and [SVT-AV1](/tools/software-encoders/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](/tools/hardware-encoders/nvenc/#hardware-or-software-encoder).\n\n## Check what your GPU can encode\n\n```sh\nvainfo --display drm --device /dev/dri/renderD128\n```\n\nLook 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`.\n\nAV1 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](/tools/hardware-encoders/qsv/#which-hardware-supports-what) and [AMF](/tools/hardware-encoders/amf/#which-hardware-supports-what) for the generation lists.\n\n## Quality-oriented encode\n\n```sh\nffmpeg -vaapi_device /dev/dri/renderD128 -i input.mkv -vf 'format=nv12,hwupload' -c:v hevc_vaapi -global_quality 24 -c:a copy output.mkv\n```\n\nVAAPI 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.\n\nFor AV1:\n\n```sh\nffmpeg -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\n```\n\nAV1 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`.\n\n### Bitrate-targeted\n\n```sh\nffmpeg -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\n```\n\n`-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.\n\n## Full-GPU pipeline\n\n```sh\nffmpeg -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\n```\n\nDecode, 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.\n\n## Options that matter\n\n| Option | What it does |\n| --- | --- |\n| `-global_quality` | Constant-quality target (ICQ or CQP). `h264_vaapi` and `hevc_vaapi` also have `-qp`, which forces CQP. |\n| `-rc_mode` | Force `CQP`, `CBR`, `VBR`, `ICQ`, `QVBR` or `AVBR`. Default `auto`. |\n| `-b:v`, `-maxrate`, `-bufsize` | Bitrate constraints. |\n| `-compression_level` | Speed/quality trade-off passed to the driver as its quality level; higher is faster and worse. The range is driver-specific. |\n| `-bf`, `-b_depth` | B-frames and B-pyramid depth. Some drivers ignore or reject them. |\n| `-low_power 1` | Use the fixed-function low-power encoder. Fewer features; some other options may be rejected. |\n| `-g`, `-idr_interval` | GOP length; `-idr_interval N` makes only every Nth I-frame an IDR (open GOP). |\n| `-async_depth` | Frames in flight. |\n\n## Pitfalls\n\n- A profile with only a decode entry point cannot encode. Check `vainfo` before blaming FFmpeg.\n- `hwupload` needs a device: use `-vaapi_device` (or `-init_hw_device`/`-filter_hw_device`) when decoding in software.\n- Pick the right render node (`/dev/dri/renderD128`, `renderD129`, …) on systems with an iGPU and a discrete GPU.\n- Behaviour differs across drivers. A command tuned on Intel may need `-rc_mode` or `-global_quality` changes on AMD.\n\n## Full option reference\n\nEvery 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.\n\n{/* ffmpeg-parameters:start */}\n\n### Private options\n\n| Parameter | Type | Default | Meaning | Range / named values |\n| --- | --- | --- | --- | --- |\n| `-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` |\n| `-b_depth` | `int` | `1` | B-frame reference depth: 1 = flat B-frames, higher builds a hierarchy. Needs `-bf`. | `1` to `INT_MAX` |\n| `-async_depth` | `int` | `2` | Frames in flight on the GPU; raise it for single-stream throughput. | `1` to `64` |\n| `-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` |\n| `-max_frame_size` | `int` | `0` | Largest encoded frame, in bytes; 0 = no limit. | `0` to `2.68435e+08` |\n| `-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` |\n| `-blbrc` | `boolean` | `false` | Block-level rate control (finer bit allocation within a frame) where the driver supports it. | `0` to `1` |\n| `-profile` | `int` | `-99` | AV1 profile: `main`, `high`, `professional`. -99 chooses from the input format. | `-99` to `255`; `main`=`0`, `high`=`1`, `professional`=`2` |\n| `-tier` | `int` | `main` | AV1 tier: `main` or `high`. | `0` to `1`; `main`=`0`, `high`=`1` |\n| `-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` |\n| `-tiles` | `image_size` | `not exposed` | Tile layout as columns×rows, e.g. `2x2`; unset uses the minimum the resolution needs. | — |\n| `-tile_groups` | `int` | `1` | Number of tile groups per frame. | `1` to `4096` |\n\n### Codec-specific generic initialization overrides\n\nThe wrapper replaces these generic FFmpeg defaults for this encoder. `-b` is in bits/s; `-g` and\n`-bf` count frames. `-1`, and `0` for `-b` and `-refs`, leave the value to the preset, driver or\nrate-control logic.\n\n| Generic parameter | Default |\n| --- | --- |\n| `-b` | `0` |\n| `-bf` | `2` |\n| `-g` | `120` |\n| `-qmin` | `1` |\n| `-qmax` | `255` |\n| `-refs` | `0` |\n\n{/* ffmpeg-parameters:end */}\n"
}
