Plex never hardware-transcoded on esh-pve-nas LXC 105 despite correct passthrough, cgroups, group membership, authenticated HuC firmware, a lifetime Plex Pass, HardwareAcceleratedCodecs=1, and the Arc already selected as HardwareDevicePath. Root cause sat below all of that: intel-media-va-driver 22.3.1 (Apr 2023, stock jammy) predates Arc/DG2 support and exports only __vaDriverInit_1_14, against the libva 2.22 that Plex bundles and loads via RPATH rather than the system one. A half-finished prior attempt at the same fix was also present -- libva and libva-drm hand-installed at 2.22 with libva-x11 left at 2.14, breaking every X11 VA-API consumer on va_fool_postp. Fixed with Intel's client-GPU repo: iHD 24.3.4 (__vaDriverInit_1_22, an exact ABI match) plus a consistent libva 2.22.0.2-87 set, which also brings the orphaned manual install back under dpkg. The repo track is rolling, so the six packages are pinned in /etc/apt/preferences.d/intel-gpu-pin and apt-mark held; verified by a simulated upgrade that moves 152 packages and touches none of them. Two findings worth more than the fix: pct snapshot refuses on a guest with a bind mount and still exits 0, so a script guarding a change with it proceeds without the rollback point it believes it has. The ZFS dataset snapshot is the working path, verified by reading it back. A synthetic Plex Transcoder invocation is not a valid test of Plex's transcode path. Plex bundles its own libc among 61 libraries; the harness produced three distinct failure modes that were artifacts of not reproducing that runtime, and it failed identically before and after a fix that worked. With no positive control its negatives carried no information. Only a forced transcode settles it, and PASS is recognisable by Plex naming the device. The original empty decoder/encoder line was an absence of evidence rather than evidence of failure -- TranscodeSession was 0. Jellyfin LXC 107 has the same stale stack and the same Arc available; left alone per the operator, and it ships its own ffmpeg so this may not transfer verbatim.
4.6 KiB
[2026-09-11] Plex never hardware-transcoded on the Arc, and every setting said it should
Operator: "I believe plex is running but I guess it's using cpu quicksync — anything to gain by moving it to a gpu?" The premise had a fold in it (Quick Sync is a GPU — it's the iGPU's media engine), and the real answer was that the GPU was already wired up and Plex had been unable to use it.
The configuration was correct the entire time
Plex is LXC 105 (vm-plex) on esh-pve-nas, 10.0.50.56. Verified good before any
change: Arc A580 present with DMC/GuC/HuC authenticated for all workloads; both
render nodes bind-mounted into the LXC with cgroup allows; plex in video(44) +
render(104); Plex 1.43.2; lifetime Plex Pass; HardwareAcceleratedCodecs=1; and
HardwareDevicePath already pointed at the Arc (…@0000:03:00.0), not the iGPU.
⚠ HardwareAcceleratedCodecs is ABSENT from Preferences.xml when it is ENABLED —
Plex only persists non-defaults. I read its absence as "off" and was wrong; the API
(GET /:/prefs) reported 1. Read Plex settings from the API, never the file.
Root cause, one layer below every setting
intel-media-va-driver 22.3.1 (Apr 2023, stock jammy) — predates Arc/DG2 support
entirely and exports only __vaDriverInit_1_14, against the libva 2.22 that Plex
bundles and loads via RPATH (/usr/lib/plexmediaserver/lib/libva.so.2), not the
system one.
⚠ And a half-finished prior attempt at this same fix was sitting there: libva and
libva-drm hand-installed at 2.22 (not dpkg-owned), libva-x11 left at 2.14, so every
X11 VA-API consumer died on undefined symbol: va_fool_postp. Upgrading a library
without its companions is how you get a stack that is broken in a way no single package
version explains.
Fix + pin
Intel client-GPU repo (https://repositories.intel.com/gpu/ubuntu jammy client, a
rolling track) → intel-media-va-driver-non-free 24.3.4 (__vaDriverInit_1_22,
exact ABI match for Plex's libva), libva set 2.22.0.2-87, libigdgmm12 22.5.2. The
orphaned manual libva is now dpkg-owned. Pinned in
/etc/apt/preferences.d/intel-gpu-pin and apt-mark hold, verified by a simulated
upgrade moving 152 packages and touching none of the six.
⚠⚠ Two footguns, both of the silent-wrong class
pct snapshot REFUSES on a guest with a bind mount AND STILL EXITS 0. LXC 105 has
mp0: /tank/media, so Proxmox printed snapshot feature is not available and returned
rc=0. A script trusting that exit code believes it has a backup it does not have. The
rootfs is on ZFS, so the working path is zfs snapshot nvme/subvol-105-disk-0@<tag> —
and read it back, per feedback_unfalsifiable_at_write_time.
A synthetic Plex Transcoder invocation is NOT a valid test of Plex's transcode
path, and I burned several rounds proving it. Plex bundles its own libc among 61
libraries; running its ffmpeg from a shell produced three different failure modes
(unknown libva error, then a libstdc++ __wmemmove_chk relocation error) that were
artifacts of the harness, and it failed identically before and after a fix that
worked. No positive control existed, so its negatives carried no information — the
exact shape of the tag-detection specimen in the measurement-discipline rule.
What actually settles it
A forced transcode, reading Plex's own log. PASS names the device:
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
plus [FFMPEG] - Format 0x… -> bgra surface enumeration, which only follows a
successful vaInitialize. FAIL is final decoder: , final encoder: with the device
never named. ⚠ And an empty-fields line is also what a server that never transcoded
emits — TranscodeSession count was 0, so the original log was an absence of
evidence, not evidence of failure. I called it failure first and had to withdraw that.
vainfo is a secondary check only (now: iHD 24.3.4, H.264/HEVC VLD and EncSliceLP
on the Arc) — it exercises the system libva, so it can pass while Plex fails.
Runbook: docs/runbooks/plex-arc-vaapi-jammy.md.
Rollback: pct stop 105; zfs rollback nvme/subvol-105-disk-0@pre-vaapi-20260911; pct start 105.
Left alone: Jellyfin LXC 107 on the same host has the same stale stack and the same Arc available — operator 2026-09-11: not actively used. It ships its own ffmpeg so this fix may not transfer verbatim. LXC 105 also has 152 unrelated pending package upgrades.