# Plex hardware transcoding on the Arc A580 (esh-pve-nas, LXC 105) **Fixed 2026-09-11.** Plex never hardware-transcoded on the Arc A580 despite every setting being correct. The fault was one layer below the settings, and the whole diagnosis is reusable for any Intel-GPU VA-API consumer on Ubuntu 22.04. ## The symptom, and why it misleads Plex logged, on every transcode decision: TPU: hardware transcoding: final decoder: , final encoder: Both fields empty. That reads like "hardware transcoding failed", but on its own it is **also** what you get when nothing transcoded at all — and `TranscodeSession` count was zero, so the log was not evidence of failure. Twenty of those lines landed inside one second on one thread: a capability probe loop, not twenty sessions. ⚠ **Do not diagnose this from configuration.** Every one of these read correct while hardware transcoding was dead: | checked | state | |---|---| | Arc A580 present, DMC/GuC/HuC firmware | ✅ HuC "authenticated for all workloads" | | LXC passthrough: both render nodes + cgroup allows | ✅ | | `plex` user in `video(44)` + `render(104)` | ✅ | | Plex 1.43.2, lifetime Plex Pass | ✅ | | `HardwareAcceleratedCodecs=1` (via API, not the file) | ✅ | | `HardwareDevicePath` = `…@0000:03:00.0` (the Arc) | ✅ already selected | ⚠ `HardwareAcceleratedCodecs` is **absent from `Preferences.xml` when enabled** — Plex only persists non-defaults. Read it from the API, never from the file: curl -s "http://127.0.0.1:32400/:/prefs?X-Plex-Token=$TOKEN" ## Root cause `intel-media-va-driver` **22.3.1** (Apr 2023, stock jammy) — predates Arc/DG2 support entirely, and exports only `__vaDriverInit_1_14` against Plex's **bundled** libva 2.22 (`/usr/lib/plexmediaserver/lib/libva.so.2`, loaded via RPATH, not the system one). Compounding it: someone had previously hand-installed libva 2.22 over the packaged 2.14 and left `libva-x11` behind at 2.14, so `vainfo` died with `undefined symbol: va_fool_postp` — a half-finished run at this same fix. ## The fix ```bash # 1. Snapshot. `pct snapshot` REFUSES on a guest with a bind mount (mp0: /tank/media) # AND STILL EXITS 0 — snapshot the ZFS dataset directly and read it back. zfs snapshot nvme/subvol-105-disk-0@pre-vaapi-20260911 zfs list -t snapshot nvme/subvol-105-disk-0@pre-vaapi-20260911 # VERIFY, don't trust rc # 2. Intel client-GPU repo (inside LXC 105) curl -fsS https://repositories.intel.com/gpu/intel-graphics.key \ | gpg --yes --dearmor -o /usr/share/keyrings/intel-graphics.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/intel-graphics.gpg] \ https://repositories.intel.com/gpu/ubuntu jammy client" \ > /etc/apt/sources.list.d/intel-gpu-jammy.list apt-get update # 3. Consistent set — the driver AND all four libva packages together apt-get install -y intel-media-va-driver-non-free libva2 libva-drm2 libva-x11-2 # 4. Pinned + held, because `jammy client` is a ROLLING track # /etc/apt/preferences.d/intel-gpu-pin + apt-mark hold systemctl restart plexmediaserver ``` Landed: iHD **24.3.4** (`__vaDriverInit_1_22`), libva set **2.22.0.2-87**, libigdgmm12 22.5.2 — and the orphaned manual libva is now dpkg-owned. ## Verification — behaviour, not config ⚠ **A synthetic `Plex Transcoder` invocation is not a valid test.** Running it from a shell produced three different failure modes (`unknown libva error`, then a libstdc++ `__wmemmove_chk` relocation error) that were **artifacts of not reproducing Plex's bundled Conan runtime** — Plex ships its own libc among 61 bundled libraries. It failed identically before and after a fix that worked. No positive control existed, so its negatives were worthless. Force a real transcode and read Plex's own log: ```bash TOKEN=$(sed -n 's/.*PlexOnlineToken="\([^"]*\)".*/\1/p' \ "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Preferences.xml") KEY=/all> curl -s -o /dev/null "http://127.0.0.1:32400/video/:/transcode/universal/start.m3u8\ ?path=%2Flibrary%2Fmetadata%2F$KEY&mediaIndex=0&partIndex=0&protocol=hls\ &directPlay=0&directStream=0&videoQuality=20&maxVideoBitrate=1500\ &X-Plex-Token=$TOKEN&X-Plex-Client-Identifier=vaapi-verify&session=vaapiverify1" sleep 12 grep -i "hardware transcoding: testing API" "…/Logs/Plex Media Server.log" | tail -3 curl -s -o /dev/null "http://127.0.0.1:32400/video/:/transcode/universal/stop\ ?session=vaapiverify1&X-Plex-Token=$TOKEN" ``` PASS looks like this — the device is **named**, and both encoder and decoder are tested: Codecs: testing h264_vaapi (encoder) Codecs: hardware transcoding: testing API vaapi for device '/dev/dri/renderD129' (Intel DG2 [Arc A580]) Codecs: testing h264 (decoder) with hwdevice vaapi followed by `[FFMPEG] - Format 0x… -> bgra` surface enumeration, which only occurs after a successful `vaInitialize`. FAIL is the empty `final decoder: , final encoder:`. `vainfo --display drm --device /dev/dri/renderD129` is a useful *secondary* check (it now reports iHD 24.3.4 with H.264/HEVC VLD **and** EncSliceLP) but it exercises the system libva, not Plex's bundled one — so it can pass while Plex fails. ## Rollback pct stop 105 zfs rollback nvme/subvol-105-disk-0@pre-vaapi-20260911 pct start 105 ## Not done - **Jellyfin (LXC 107)** on the same host has the same stale stack and the same Arc available. Left alone 2026-09-11 — operator: not actively used. It ships its own ffmpeg, so this fix may not transfer verbatim. - LXC 105 has **152 packages pending upgrade** unrelated to this work.