Intel VAAPI hardware decoding in Plex Desktop (Flatpak)
Force Plex Desktop Flatpak to use Intel Quick Sync VAAPI decode on a hybrid Intel + NVIDIA laptop, including the render-node and EGL fixes.
Plex Desktop uses mpv for playback. On a hybrid-graphics laptop (Intel iGPU + NVIDIA dGPU) the Flatpak often silently falls back to software decoding even though host VAAPI works. Getting hardware decode requires fixing three separate things:
- Driver path — libva can't find the
iHDdriver inside the sandbox. - Render node — mpv defaults to the NVIDIA node, where the Intel driver can't initialize.
- Render backend — zero-copy VAAPI needs an EGL OpenGL context; plain GLX is refused.
The result is either full software decoding, or (after fixing 1 + 2) hardware copy-back decoding, or (after all three) true zero-copy decoding.
Package:
tv.plex.PlexDesktopConfig dir:~/.var/app/tv.plex.PlexDesktop/data/plex/Applies to X11 sessions. Adjust the EGL step for Wayland (see notes).
1. Confirm host VAAPI works
vainfoYou want va_openDriver() returns 0 and a driver line like Intel iHD driver for Intel(R) Gen Graphics. If the host itself can't do VAAPI, fix that first — nothing below will help.
2. Identify the Intel render node
On hybrid systems the render-node numbering is not fixed — the NVIDIA GPU is often renderD128 and Intel renderD129, but verify:
ls -l /dev/dri/by-path/pci-0000:00:02.0-render -> ../renderD129 # Intel iGPU (bus 00:02.0)
pci-0000:01:00.0-render -> ../renderD128 # NVIDIA dGPU (bus 01:00.0)The Intel iGPU is the one on PCI bus 00:02.0. Note its renderD* number — that's the node you'll pin mpv to below (renderD129 in this example).
Confirm the Intel driver only initializes on the Intel node (this is why the default fails):
# Intel node → succeeds
LIBVA_DRIVER_NAME=iHD vainfo --display drm --device /dev/dri/renderD129
# NVIDIA node → "unsupported drm device by media driver" / va_openDriver() returns 18
LIBVA_DRIVER_NAME=iHD vainfo --display drm --device /dev/dri/renderD1283. Install the VAAPI runtime extension (matching the runtime version)
# find the runtime version, e.g. 23.08
flatpak info tv.plex.PlexDesktop | grep -i runtime
flatpak install flathub org.freedesktop.Platform.VAAPI.Intel//23.08The extension mounts the driver into a subdirectory libva does not search by default:
flatpak run --command=sh tv.plex.PlexDesktop -c \
'find /usr/lib -name "iHD_drv_video.so"'
# → /usr/lib/x86_64-linux-gnu/dri/intel-vaapi-driver/iHD_drv_video.so4. Set the Flatpak environment overrides
flatpak override --user tv.plex.PlexDesktop \
--device=dri \
--env=LIBVA_DRIVER_NAME=iHD \
--env=LIBVA_DRIVERS_PATH=/usr/lib/x86_64-linux-gnu/dri/intel-vaapi-driver \
--env=DRI_PRIME=0 \
--env=QT_XCB_GL_INTEGRATION=xcb_egl| Variable | Why |
|---|---|
LIBVA_DRIVER_NAME=iHD | Use the modern Intel media driver (needed for recent Intel GPUs / AV1) |
LIBVA_DRIVERS_PATH=…/intel-vaapi-driver | Point libva at the subdirectory where the extension puts the .so |
DRI_PRIME=0 | Keep GL rendering on the Intel GPU |
QT_XCB_GL_INTEGRATION=xcb_egl | Force Qt's OpenGL onto EGL — required for zero-copy VAAPI interop (X11 defaults to GLX, which mpv refuses for VAAPI) |
If you previously set
QT_QUICK_BACKEND=openglto fix white/corrupted posters, keep it — these overrides accumulate, they don't replace it.
Verify all of them reach the sandbox:
flatpak run --command=sh tv.plex.PlexDesktop -c 'env | grep -iE "LIBVA|DRI_|QT_"'5. Pin mpv to the Intel node and pick the decode mode
Plex reads ~/.var/app/tv.plex.PlexDesktop/data/plex/mpv.conf before every playback (see mpv.conf.md in the same dir). Set the render node to the Intel node you found in step 2:
# ~/.var/app/tv.plex.PlexDesktop/data/plex/mpv.conf
hwdec=vaapi
vaapi-device=/dev/dri/renderD129Which hwdec value?
| Value | Decode | Frame path | Needs EGL backend? |
|---|---|---|---|
vaapi | Intel GPU | zero-copy (stays in GPU) | Yes |
vaapi-copy | Intel GPU | copied to RAM, then displayed | No |
| (software) | CPU | — | — |
- Use
vaapi(zero-copy) if step 4's EGL override works with your UI — lowest CPU, power, and memory bandwidth. - Fall back to
vaapi-copyif EGL causes UI glitches or interop is refused. Still decodes on the Intel Video engine; only adds a cheap per-frame RAM copy. This is the robust, always-works option. - Do not use
auto-copyon a hybrid system — it may select NVIDIA'scuda-copy(NVDEC) instead of Intel VAAPI.
6. Restart and verify
flatpak kill tv.plex.PlexDesktopReopen Plex, make sure Settings → Player → "Use hardware decoding" is on, and play an H.264/HEVC file.
Check the log — ~/.var/app/tv.plex.PlexDesktop/data/plex/Logs/Plex.log:
grep -iE 'vaapi|hwdec|Using (software|hardware)|only works with' \
~/.var/app/tv.plex.PlexDesktop/data/plex/Logs/Plex.log | tailSuccess (zero-copy) looks like:
vd: Trying hardware decoding via hevc-vaapi.
vd: Using hardware decoding (vaapi).
vf: [out] 1920x1080 vaapi[p010] ...Using hardware decoding (vaapi-copy) is the copy-mode success line. vd: Using software decoding. means it's still failing — check the failure reason on the lines just above.
Check the GPU — the Intel Video engine should be active during playback:
sudo intel_gpu_top # watch the "Video" engine rowTroubleshooting
| Log line | Meaning | Fix |
|---|---|---|
iHD_drv_video.so init failed / va_openDriver() returns 18 | mpv opened the NVIDIA node | Set vaapi-device to the Intel renderD* (step 5) |
Trying to open .../dri/iHD_drv_video.so then software | Driver not found — wrong path | Set LIBVA_DRIVERS_PATH to the intel-vaapi-driver subdir (step 4) |
VAAPI hwdec only works with OpenGL or Vulkan backends | GL context is GLX, not EGL | Add QT_XCB_GL_INTEGRATION=xcb_egl, or use hwdec=vaapi-copy |
| White/corrupted posters after enabling EGL | EGL broke Qt UI rendering | Revert to hwdec=vaapi-copy and unset QT_XCB_GL_INTEGRATION |
Revert to the safe copy-mode:
flatpak override --user --unset-env=QT_XCB_GL_INTEGRATION tv.plex.PlexDesktop
# and in mpv.conf: hwdec=vaapi → hwdec=vaapi-copyNotes
- The NVIDIA GPU provides no VAAPI (it uses NVDEC/VDPAU); VAAPI decode always belongs to the Intel iGPU here.
DRI_PRIMEis for GL render offload, not decode — it does not select the VAAPI device. - Plex Desktop uses mpv, not Chromium/Electron — Chromium VAAPI flags (
--enable-features=VaapiVideoDecoder) do not apply. - Wayland: Qt already uses EGL, so
QT_XCB_GL_INTEGRATIONis unneeded; ensure the Flatpak has Wayland socket access and tryhwdec=vaapidirectly. - If a specific file shows green frames or wrong colors under zero-copy, that's a per-file interop quirk — switch that session to
vaapi-copy.