VAAPI
VA-API (Video Acceleration API) is a Linux-only hardware acceleration interface supported by Intel and AMD GPUs. Sovereign uses VAAPI for a full hardware pipeline: decode and encode share the same device context, so there’s no round trip through the CPU between stages. A downscale runs on the GPU too. Because every step has to run there, a transcode that needs a step VAAPI doesn’t do on the GPU (padding the frame for a strict decoder, or deinterlacing an SDR source, where the software filter gives a cleaner picture) goes to the next option instead: Quick Sync on Intel, or the CPU.
The host must be running Linux with the GPU’s kernel driver loaded (i915 or xe for Intel, amdgpu for AMD). The /dev/dri device group must be exposed to the container. The userspace VA-API drivers ship inside the Sovereign image: Intel’s iHD and Mesa’s radeonsi for AMD. Sovereign picks the right one for the GPU it finds, so the same image runs on either vendor. You can verify VA-API is working from inside the container with:
vainfo --display drm --device /dev/dri/renderD128The driver line in the output names the vendor: Intel iHD driver on Intel, Mesa Gallium driver ... (radeonsi, ...) on AMD. On an Intel host using the newer xe kernel driver, the vainfo in the image doesn’t recognise it and fails to pick a driver on its own. Run it as LIBVA_DRIVER_NAME=iHD vainfo ... there. Sovereign itself isn’t affected.
Giving the Container the GPU
Section titled “Giving the Container the GPU”You can share the device in one of two ways. Sharing the whole /dev/dri directory is simpler; sharing just the render node is more restrictive.
Option A - share the entire /dev/dri directory
docker run --name sovereign \ --device /dev/dri:/dev/dri \ -v sovereign-data:/sovereign-data \ -v /path/to/media:/media:ro \ -p 5000:5000 \ --env-file sovereign.env \ <sovereign-image>:<version>Option B - share only the render node
Use this to limit the container to a single device. Replace renderD128 with the output of ls /dev/dri on the host.
docker run --name sovereign \ --device /dev/dri/renderD128:/dev/dri/renderD128 \ -v sovereign-data:/sovereign-data \ -v /path/to/media:/media:ro \ -p 5000:5000 \ --env-file sovereign.env \ <sovereign-image>:<version>You can share the device in one of two ways. Sharing the whole /dev/dri directory is simpler; sharing just the render node is more restrictive.
Option A - share the entire /dev/dri directory
services: server: image: <sovereign-image>:<version> env_file: - sovereign.env ports: - 5000:5000 devices: - /dev/dri:/dev/dri volumes: - sovereign-data:/sovereign-data - /path/to/media:/media:ro
volumes: sovereign-data:Option B - share only the render node
Use this to limit the container to a single device. Replace renderD128 with the output of ls /dev/dri on the host.
services: server: image: <sovereign-image>:<version> env_file: - sovereign.env ports: - 5000:5000 devices: - /dev/dri/renderD128:/dev/dri/renderD128 volumes: - sovereign-data:/sovereign-data - /path/to/media:/media:ro
volumes: sovereign-data:A container can only open the render device (/dev/dri/renderD128) if that device is on the
container’s device cgroup allowlist. There are two ways to grant that access; pick one.
Option A - GPU device plugin (recommended)
Install the Intel GPU Device Plugin (Intel) or the AMD GPU Device Plugin (AMD). The plugin advertises the GPU as a schedulable resource and configures the device cgroup and permissions for you, with no elevated privileges. Then request the matching resource:
Intel
containers: - name: sovereign image: <sovereign-image>:<version> resources: limits: gpu.intel.com/i915: 1 envFrom: - secretRef: name: sovereign-secretsAMD
containers: - name: sovereign image: <sovereign-image>:<version> resources: limits: amd.com/gpu: 1 envFrom: - secretRef: name: sovereign-secretsOption B - privileged container
If you can’t install a device plugin, run the container privileged and expose /dev/dri. A
privileged container bypasses the device cgroup entirely. This grants broad host access, so prefer
Option A for production.
containers: - name: sovereign image: <sovereign-image>:<version> securityContext: privileged: true envFrom: - secretRef: name: sovereign-secrets volumeMounts: - name: dri mountPath: /dev/drivolumes: - name: dri hostPath: path: /dev/driHDR Tone Mapping
Section titled “HDR Tone Mapping”When an HDR source has to be transcoded for a client that can’t display it, VAAPI converts it to SDR on the GPU. How it does that depends on the driver.
On Intel, the iHD driver’s own tone-map does the conversion. Its curve isn’t adjustable, and on the hardware this was measured against it lands dark: bright material comes out about right while shadows crush to black. Sovereign corrects for that by lifting the HDR picture on its way into the curve, with a brightness offset and a matching gain:
Sovereign__Transcoding__VaapiToneMapBrightness=19Sovereign__Transcoding__VaapiToneMapContrast=0.95Because the correction acts on the HDR input rather than the SDR output, a contrast below 1.0 is normal, and raising the brightness also moves the picture onto a different part of the driver’s curve, so more than the brightness changes. The defaults are fitted to one Intel iGPU and one version of the iHD driver, so another card or a newer driver may sit somewhere else. Compare a few frames against the same title played back without the correction, on a dim interior scene and a bright exterior one, and adjust from there. Brightness takes -100 to 100 and contrast 0 to 10; a value outside those ranges is clamped to the nearest end.
Setting brightness to 0 and contrast to 1.0 turns the correction off completely, which is what you want if a future driver ships a curve that needs none.
AMD’s radeonsi driver has no tone-map of its own. On AMD, Sovereign decodes an H.265 HDR source with the GPU’s Vulkan driver (which ships in the image), tone-maps it there, and hands the SDR picture back to VAAPI to encode, so the conversion still stays on the GPU. This also applies a Dolby Vision Profile 5 file’s reshaping data, so those titles convert with the right colours. The libplacebo row under the VAAPI tab of the GPU Capabilities admin page shows whether this route passed its startup check. An HDR source in any other codec, or a host where the route failed, is tone-mapped on the CPU instead.
The brightness and contrast settings apply only to the Intel tone-map, and only to a transcode that actually tone-maps. Direct play never touches them, and neither does the Vulkan route on AMD, NVENC or QSV.
Supported Codecs
Section titled “Supported Codecs”| Codec | Encoder | Decoder | Notes |
|---|---|---|---|
| H.264 | h264_vaapi |
-hwaccel vaapi |
Supported on most Intel and AMD GPUs |
| H.265 | hevc_vaapi |
-hwaccel vaapi |
Supported on Intel Skylake+ and AMD Polaris (RX 400) or newer |
| AV1 | av1_vaapi |
-hwaccel vaapi |
Requires Intel Arc / Meteor Lake, or AMD RDNA 3 (RX 7000, Radeon 760M/780M) or newer |
VAAPI has no named *_vaapi decoders in FFmpeg. Decode runs through -hwaccel vaapi, sharing the encoder’s device context. A working encoder doesn’t mean the GPU can decode every codec, though. Decode support depends on the codec and the GPU generation: AMD GPUs decode VP9 but can’t encode it, AV1 decode needs AMD RDNA 2 or Intel Tiger Lake and newer, and an older Intel iGPU encodes H.264 and H.265 but decodes neither VP9 nor AV1.
So at startup Sovereign also decodes a short test clip of each codec through VAAPI, and uses VAAPI for a transcode only when the source’s codec passed. The results appear as decoder rows named like hevc_vaapi or vp9_vaapi on the admin GPU page. A source whose codec failed, or whose codec Sovereign doesn’t recognise, is transcoded by the next option instead: Quick Sync on Intel, or the CPU. The test clips are 8-bit, so this check can’t catch a GPU that decodes 8-bit H.265 but not 10-bit.
See Hardware Acceleration Overview for the full detection and troubleshooting reference.
Titles, artwork, people and descriptions shown in screenshots are fictional and were created for illustration. Sovereign doesn't include or supply any media: it plays the library you bring.