Files
esh-pfi-infrastructure/persistent-memory.d/2026-09-11-plex-arc-vaapi.md
T
vh 88e171bea6 fix(esh): Plex hardware transcoding on the Arc A580, and the two ways it hid
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.
2026-09-11 22:03:52 -07:00

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.