Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Plex Intel Arrow Lake VAAPI hardware-transcoding fix for Docker

Prebuilt x86-64 Intel media-driver binaries, a pinned-source build recipe, Docker Compose integration guidance, rollback steps, and verification gates for Plex Media Server on Intel Arrow Lake graphics.

Choose your path

Preference Start here
I want the tested binaries Download iHD_drv_video.so and libigdgmm.so.12.10.0, then follow Option A.
I prefer to build everything Review source/Dockerfile, then follow Option B.
I want to validate first Run scripts/verify-binaries.sh and then scripts/verify-runtime.sh.

Purpose

This guide documents a compatibility workaround for Plex Media Server running in Docker on Intel Arrow Lake graphics. It is intended for systems where the GPU is correctly exposed to the container, but Plex still fails to create a VAAPI display or falls back to CPU transcoding.

The companion resource archive supports two approaches:

  1. Use the prebuilt binaries after verifying their checksums and compatibility.
  2. Build the binaries yourself from pinned upstream source revisions.

The archive contains no credentials, tokens, Plex database, media, IP addresses, hostnames, usernames, or installation-specific configuration.

Scope and known-good baseline

Component Tested value
Architecture x86-64
Deployment Proxmox VE 9.2.18 → unprivileged Debian 13 LXC → Docker Compose
Host kernel / GPU driver 7.0.14-16-pve / in-tree i915; no force_probe or DKMS driver required
GPU Intel Arrow Lake-P, PCI ID 8086:7d51
Render device /dev/dri/renderD128, shared through LXC and passed to the Plex container
Intel media-driver 26.1.6, commit 469cbbdd603d1718abacbc0604f2addf82b48ade
Intel gmmlib 22.10.0, commit 676054be32ac9c8df0cb6366a95c96f300b5aa06
Plex-bundled VAAPI ABI 1.22.0 (measured)
Plex-bundled musl 1.2.2 (measured)
Plex version used for acceptance 1.43.4.10903-e5521bd8c
Plex container Official plexinc/pms-docker@sha256:e0ab27395614a8e1a4fdf84c6bc60ac664915cfdde70c52d030c7728a1c48e14
Plex entitlement Plex Pass active
Acceptance test Real 4K HEVC playback forced to H.264: VAAPI hardware decode, zero-copy, and hardware encode passed

This is a tested compatibility workaround, not an official Plex or Intel release. Do not assume it applies to a different GPU, CPU architecture, Plex image, VAAPI ABI, or future Plex release.

Proxmox and LXC describe the tested deployment, but they are not requirements for the driver workaround. A different Docker host may work when it exposes the same render device and the Plex image has a compatible bundled loader and VAAPI ABI.

The problem in simple terms

Two separate faults can look like the same “hardware transcoding does not work” problem:

Fault Symptom Fix
Plex's bundled Intel media driver is too old for the Arrow Lake GPU. Plex cannot initialize the Intel VAAPI device. Load a newer Intel media-driver built to remain compatible with Plex's runtime.
The real Plex process cannot access the render device. A test launched manually may work, while normal Plex playback still uses the CPU. Give the actual Plex process the render-device group as its primary or retained group.

Ordinary shared libraries from another Linux distribution are not a safe drop-in solution. In the tested case they introduced unsupported relocations or symbols, including __isoc23_sscanf. The supplied build avoids RELR and statically includes the required C++ runtime while continuing to use Plex's own libva loader.

Before changing anything

Confirm all of the following:

  • Plex Pass is active; Plex hardware transcoding requires it.
  • The render device exists on the Docker host, normally /dev/dri/renderD128.
  • The Plex container receives that device.
  • You have a backup of the Plex configuration and current Compose files.
  • You know how to restore the currently working Plex image.
  • The GPU PCI ID and system architecture match the tested scope, or you accept that rebuilding and additional validation may be required.

Record the render-device group number on the Docker host:

stat -c '%g' /dev/dri/renderD128

Call that number <RENDER_GID> below. Do not blindly copy a numeric group ID from another system.

Option A — use the prebuilt binaries

  1. Extract the resource archive.
  2. Verify the archive manifest and binary checksums before use:
sha256sum -c PACKAGE-MANIFEST.sha256
(cd binary && sha256sum -c SHA256SUMS)
  1. Ensure the standard binutils package is installed, then run the static binary checks:
sh scripts/verify-binaries.sh
  1. Copy the two versioned files and create the GMM symlinks in a persistent host directory of your choice:
install -d -m 0755 <DRIVER_DIRECTORY>
install -m 0555 binary/iHD_drv_video.so <DRIVER_DIRECTORY>/iHD_drv_video.so
install -m 0555 binary/libigdgmm.so.12.10.0 <DRIVER_DIRECTORY>/libigdgmm.so.12.10.0
ln -sfn libigdgmm.so.12.10.0 <DRIVER_DIRECTORY>/libigdgmm.so.12
ln -sfn libigdgmm.so.12 <DRIVER_DIRECTORY>/libigdgmm.so

Do not place the driver only in the container's writable layer; it will disappear when the container is recreated.

Option B — build from pinned source

The archive's source/Dockerfile pins the base image digest, libva development package version, and exact Intel source commits. Docker BuildKit and Internet access are required. Other Alpine build packages are not snapshot-pinned, so this is a repeatable pinned-source recipe rather than a guarantee of bit-for-bit output forever.

docker build -t plex-arrow-lake-vaapi:local source
mkdir -p rebuilt-binary
container_id=$(docker create plex-arrow-lake-vaapi:local)
docker cp "$container_id:/opt/vaapi/." rebuilt-binary/
docker rm "$container_id"

Run the same static checks against the rebuilt output:

VAAPI_DIR="$PWD/rebuilt-binary" sh scripts/verify-binaries.sh

The rebuilt hashes may match the supplied binaries when the complete build environment remains unchanged, but a valid rebuild can differ because not every toolchain package is snapshot-pinned. Treat a hash difference as a reason to run all static and runtime gates, not by itself as proof of compromise or correctness.

Docker Compose integration

Merge the following into the existing Plex service. Replace every angle-bracketed placeholder with a value from the local system:

services:
  <PLEX_SERVICE>:
    devices:
      - /dev/dri/renderD128:/dev/dri/renderD128
    environment:
      PLEX_GID: "<RENDER_GID>"
      LIBVA_DRIVER_NAME: iHD
      LIBVA_DRIVERS_PATH: /vaapi
    volumes:
      - <DRIVER_DIRECTORY>:/vaapi:ro
      - <DRIVER_DIRECTORY>/iHD_drv_video.so:/config/Library/Application Support/Plex Media Server/Cache/va-dri-linux-x86_64/iHD_drv_video.so:ro

Why both mounts are present: Plex may override LIBVA_DRIVERS_PATH for a transcode job and look in its driver-cache directory. The second read-only bind ensures that the same verified driver is used there.

PLEX_GID was essential with the official image in the tested environment. A Compose group_add entry alone looked correct in a manual test but did not survive Plex's startup identity change for the real server process. Other Plex images may handle identities differently, so inspect the real running process rather than assuming this variable applies universally.

Validate Compose before recreating Plex:

docker compose config --quiet
docker compose up -d --force-recreate <PLEX_SERVICE>

Runtime verification

Set local values and run the non-destructive checks:

PLEX_CONTAINER=<PLEX_CONTAINER> \
RENDER_DEVICE=/dev/dri/renderD128 \
DRIVER_MOUNT=/vaapi \
sh scripts/verify-runtime.sh

Then perform the acceptance test:

  1. Play media you own that requires video transcoding—for example, force a 4K HEVC item to a lower H.264 resolution or bitrate.
  2. Open the Plex Dashboard and expand the active session.
  3. Confirm that video transcoding is marked (hw).
  4. Confirm the Plex logs identify VAAPI hardware decode and h264_vaapi hardware encode on the render device.
  5. Confirm CPU use is materially lower than a software transcode and playback is stable.

Static checks and a healthy container are not sufficient. A real Plex playback that performs both hardware decode and encode is the acceptance gate.

Rollback

If Plex becomes unhealthy or the real-media test fails:

  1. Restore the saved Compose configuration.
  2. Remove the custom driver mounts and related environment entries.
  3. Recreate only the Plex service.
  4. If the failure followed a Plex update, restore the previously recorded Plex image digest.
  5. Preserve sanitized logs for diagnosis; redact every token and account value.

Do not delete the Plex database or media as part of this rollback.

Updating Plex later

A Plex update does not necessarily break this workaround because the driver lives outside the container image. After any Plex update:

Step Required check
1 Confirm the container starts and remains healthy.
2 Run verify-runtime.sh.
3 Perform a real forced hardware transcode.
4 Keep the update only when the real test passes.
5 If it fails, restore the previous image first; do not rebuild blindly.

Happy Plexing!

About

Plex hardware transcoding fix for Intel Arrow Lake graphics in Docker using VAAPI

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages