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

81 lines
4.6 KiB
Markdown

# `[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.