Skip to content

0038. Upgrade Jellyfin to 12.0-rc2 for B580 VA-API Transcoding

  • Status: accepted
  • Date: 2026-07-19
  • Deciders: lusoris
  • Related: PR #2639

Context

Jellyfin failed to transcode on the B580 (k8s-worker-home-3): VA-API never initialised and every playback raised a player error. The B580 verdict audit (.workingdir2/cluster-2/audits/jellyfin-b580-transcode-verdict-2026-07-18.md) ruled the node healthy with live evidence — HuC media firmware RUNNING, ReBAR on, a single passed-through B580, and a working compute path on the same card.

The audit placed the fault container-side and below iHD: ffmpeg -init_hw_device drm is pure libdrm, and it failed with ffmpeg's synthetic AVERROR(EINVAL) raised when drmGetVersion() (DRM_IOCTL_VERSION) returns NULL. The working hypothesis is a libdrm 2.4.131 ↔ kernel-7.0 xe uAPI skew on the VA-API path; the compute path uses a different userspace (Level-Zero) and is unaffected. Because libdrm is pinned at 2.4.131 across every jellyfin-ffmpeg build (7.1.4 → 8.1.2 → master), the audit concluded that an image bump alone is most likely insufficient. The decisive in-pod measurement (the real DRM_IOCTL_VERSION errno) could not be taken: the container has no strace, python or gcc, and kubectl debug node is Kyverno-blocked.

Separately and independently of the outage, the configure-arc-transcode init set HardwareDecodingCodecs to include vc1, which Arc/Battlemage has no hardware decoder for.

Decision

Ship jellyfin/jellyfin:12.0-rc2 (jellyfin-ffmpeg 8.x, iHD 26.2.4) as a home-only canary on the B580 node, digest-pinned, and drop vc1 from HardwareDecodingCodecs. HardwareAccelerationType stays qsv.

The bump is taken as a diagnostic canary, not as the expected fix: it is option 2 of the audit's three ranked options and is predicted to fail. Its value is that failing confirms the libdrm diagnosis and promotes option 1 (a custom overlay image with a newer libdrm) from hypothesis to indicated fix.

Alternatives considered

  1. Custom overlay image — base jellyfin/jellyfin:10.11.11 with a newer libdrm (+ iHD 26.x) matching the node's xe stack, the same pattern already used for paperclip. Ranked highest-confidence by the audit and keeps Jellyfin on a stable release, but it was gated on a confirmatory LD_PRELOAD test that could not be run in-pod. Not rejected — deferred, and indicated if this canary fails.
  2. Node kernel pin to a release whose xe DRM_IOCTL_VERSION works with libdrm 2.4.131. Rejected: conflicts with the deliberate bleeding-edge posture of the Ubuntu 26.04 / kernel 7.0 nodes.
  3. Environment-variable workarounds (e.g. LIBVA_DRIVER_NAME). Rejected as doubly inert: the failure is pre-enumeration, and jellyfin-ffmpeg patches libva to ignore LIBVA_DRIVER_NAME (renamed LIBVA_DRIVER_NAME_JELLYFIN) and hardcodes LIBVA_DRIVERS_PATH.

Consequences

  • Rollback is not a tag revert. 10.11 → 12.0 migrates the Jellyfin library database, so backing this out requires restoring the config PVC, not merely pinning the old tag. This is the main cost of the canary.
  • Pre-release software on a home-facing service, which departs from the pin-to-stable rule; scoped to home-only to bound the blast radius.
  • Dropping vc1 is correct regardless of the transcode outcome — the hardware has no VC1 decoder, so advertising it could only produce failed hardware decodes.
  • The canary is diagnostically decisive either way: transcode working refutes the libdrm hypothesis, and transcode still broken confirms it and authorises the overlay-image work.

References

  • PR #2639 — fix(jellyfin): 12.0-rc2 canary (iHD 26.2.4) for B580 xe transcode + drop vc1
  • .workingdir2/cluster-2/audits/jellyfin-b580-transcode-verdict-2026-07-18.md — B580 transcode verdict: node-health evidence, libdrm/DRM root-cause analysis, and the three ranked fix options