Enable Intel iGPU hardware transcode by default for jellyfin-ha
ci/woodpecker/pr/vector-test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful

The pod already requests gpu.intel.com/i915 and joins the render/video
groups, but Jellyfin transcodes in software until hardware acceleration
is turned on in its encoding config, which the fork does not template.

Seed /config/config/encoding.xml from the init container so VAAPI on the
injected Intel render node (/dev/dri/renderD128) is active on first boot:
HardwareAccelerationType vaapi, EnableHardwareEncoding, h264/hevc decode,
tonemapping left off. Rename the init container to inject-config and write
each seed file only when absent, so admin changes persisted to the shared
RWX /config are never clobbered on restart.
This commit is contained in:
Ben Vincent
2026-08-11 07:23:38 +10:00
parent f89e1c8260
commit ceb2114467
+44 -9
View File
@@ -44,10 +44,12 @@ spec:
app: jellyfin
topologyKey: kubernetes.io/hostname
initContainers:
# Select the fork's experimental PostgreSQL provider by writing
# database.xml before Jellyfin starts. Runs as root to chown into the
# shared config volume; mirrors the fork Helm chart's inject-db-config.
- name: inject-db-config
# Seed the fork's PostgreSQL provider (database.xml) and Intel iGPU
# hardware transcode settings (encoding.xml) before Jellyfin starts.
# Runs as root to chown into the shared config volume; mirrors the fork
# Helm chart's inject-db-config. Each file is written only when absent so
# admin changes persisted to the shared RWX /config survive pod restarts.
- name: inject-config
image: busybox:1.37.0
command:
- sh
@@ -56,15 +58,47 @@ spec:
mkdir -p /config/config
chown 1000:1000 /config/config
chmod 775 /config/config
cat > /config/config/database.xml << 'DBEOF'
if [ ! -e /config/config/database.xml ]; then
cat > /config/config/database.xml << 'DBEOF'
<?xml version="1.0" encoding="utf-8"?>
<DatabaseConfigurationOptions>
<DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
<LockingBehavior>NoLock</LockingBehavior>
</DatabaseConfigurationOptions>
DBEOF
chown 1000:1000 /config/config/database.xml
chmod 664 /config/config/database.xml
chown 1000:1000 /config/config/database.xml
chmod 664 /config/config/database.xml
fi
# VAAPI on the Intel render node the device plugin injects
# (/dev/dri/renderD128 — ffmpeg's default DRM node, reachable via
# the render/video supplementalGroups). Without this the attached
# iGPU is idle and every transcode runs in software. Omitted
# elements fall back to the fork's EncodingOptions defaults.
if [ ! -e /config/config/encoding.xml ]; then
cat > /config/config/encoding.xml << 'ENCEOF'
<?xml version="1.0" encoding="utf-8"?>
<EncodingOptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<EncodingThreadCount>-1</EncodingThreadCount>
<HardwareAccelerationType>vaapi</HardwareAccelerationType>
<VaapiDevice>/dev/dri/renderD128</VaapiDevice>
<EnableHardwareEncoding>true</EnableHardwareEncoding>
<AllowHevcEncoding>true</AllowHevcEncoding>
<AllowAv1Encoding>false</AllowAv1Encoding>
<EnableIntelLowPowerH264HwEncoder>false</EnableIntelLowPowerH264HwEncoder>
<EnableIntelLowPowerHevcHwEncoder>false</EnableIntelLowPowerHevcHwEncoder>
<EnableTonemapping>false</EnableTonemapping>
<EnableVppTonemapping>false</EnableVppTonemapping>
<HardwareDecodingCodecs>
<string>h264</string>
<string>hevc</string>
<string>vc1</string>
<string>vp9</string>
</HardwareDecodingCodecs>
</EncodingOptions>
ENCEOF
chown 1000:1000 /config/config/encoding.xml
chmod 664 /config/config/encoding.xml
fi
resources:
requests:
cpu: 10m
@@ -156,8 +190,9 @@ spec:
memory: 6Gi
# Intel iGPU (QSV/VA-API) slot. Requesting it pins the pod to a
# GPU-labelled node and injects /dev/dri/renderD* automatically, so
# no /dev/dri hostPath or privileged container is needed. Enable
# QSV/VA-API once in the Jellyfin admin UI; it persists to /config.
# no /dev/dri hostPath or privileged container is needed. VA-API is
# pre-enabled via the seeded encoding.xml (see inject-config), so
# transcodes use the iGPU on first boot with no manual UI step.
gpu.intel.com/i915: "1"
securityContext:
runAsUser: 1000