SparkBox/Guides/Jellyfin transcoding

Jellyfin transcoding suddenly went slow (or won't start at all)

You play a movie and Jellyfin pins every CPU core, buffers, and shows "transcoding" instead of "direct play" — or the container won't come up at all. In almost every case the culprit is the /dev/dri hardware device: it dropped out after a restart, it was never mapped for your GPU brand, or it was hardcoded on a box that doesn't have it.

Jellyfin home screen on a SparkBox server
Jellyfin home screen on a SparkBox server

Rather not hand-edit compose files? SparkBox layers the hardware-acceleration overlay automatically — only on hosts that actually have the device — so Jellyfin starts either way. See the walkthrough →

The 10-second version: Hardware transcoding rides on a device called /dev/dri passed into the container. If a dashboard restart dropped it, re-apply the hardware overlay from the host with sparkbox up media. If Jellyfin won't start on a GPU-less machine, that device must be in an optional overlay, never hardcoded into the base config.

First, what "transcoding" actually means

Transcoding is the server converting a video file into a format your device can play — different codec, resolution, or bitrate. Software transcoding does this on the CPU and is slow and power-hungry. Hardware transcoding (also called hardware acceleration) offloads the work to a dedicated video chip, which is far faster and cooler.

On Linux, that chip is exposed as a device node at /dev/dri ("Direct Rendering Infrastructure"). For a container to use it, the device has to be passed through — mapped into the container. VAAPI is the API Jellyfin uses to talk to Intel and AMD graphics through that device. If /dev/dri isn't inside the container, Jellyfin has no hardware to use and silently falls back to software.

Cause 1 — Hardware transcoding drops after a dashboard restart (open)

This is the most common report. Everything works, you tap the "restart" button for the media module in the dashboard UI, and afterwards playback that used to direct-play or hardware-transcode is suddenly software-transcoding and choking the CPU.

Homarr — a home dashboard for all your self-hosted apps
Homarr — a home dashboard for all your self-hosted apps
SparkBox dashboard home with app launcher tiles and system stats
SparkBox dashboard home with app launcher tiles and system stats

Fixed as of v1.6.489. This used to be real: the dashboard restart brought the container back without re-applying the hardware overlay, so the /dev/dri passthrough was lost and Jellyfin kept running with no GPU. The dashboard button now goes through the same host-side path as the command line, which re-detects your GPU's group and re-applies the overlay. If you are on an older release, update first — the workaround below is no longer needed once you have.

Fix

  1. Open a terminal on the host machine (not the dashboard).
  2. Re-apply the media stack with the hardware overlay:
    sparkbox up media
    This brings the module back up and re-layers the hardware config, restoring /dev/dri.
  3. In Jellyfin, start a title that would need transcoding and confirm the dashboard shows hardware transcoding rather than software.

Still not using the GPU after a restart? Run sudo sparkbox doctor — the Hardware Transcoding section tells you directly whether the container has GPU access, and whether it joined the right group for your distribution. That group number differs between NAS firmware, Debian and Ubuntu, and a mismatch fails silently with exactly this "fatal player error".

Cause 2 — Your GPU is Nvidia, and it's not being used (open)

If you have an Nvidia card and hardware transcoding never kicks in no matter what, this is why. The hardware overlay (modules/media/docker-compose.hw.yml, loaded when JELLYFIN_HW_ACCEL is set and /dev/dri exists) maps only /dev/dri plus the video and render group IDs. That path is Intel Quick Sync and AMD/Intel VAAPI. Nvidia devices are present on your box but simply aren't wired into the overlay, so they're never handed to Jellyfin.

Nvidia is supported. Set Hardware Transcoding to nvidia in Settings. It needs the NVIDIA driver plus nvidia-container-toolkit installed on the host and registered with Docker — SparkBox checks for that and falls back to software transcoding rather than failing to start if it is missing. sudo sparkbox doctor reports whether the runtime is registered, and gives you the exact command if it is not.

What you can do today

  1. Rely on direct play where possible. Match your client and files so Jellyfin serves the original stream without converting it — no transcoding, no GPU needed.
  2. Reduce transcode demand. Keep libraries in codecs and containers your main devices play natively, so software transcoding is rare rather than constant.
  3. If Intel/AMD hardware is available elsewhere in your setup, that path works today; Nvidia does not.

Cause 3 — Jellyfin (or Plex/Emby) won't start on a box with no Intel/AMD GPU

Symptom: the container refuses to create, often with a Docker error about /dev/dri not existing, and the app never comes online — a classic "won't start" / "connection refused" situation on a VPS with no integrated graphics.

The root cause is how the device is declared. A compose devices: mapping is a hard requirement — if the device doesn't exist, Docker fails container creation outright. It does not silently ignore it. Plex and Emby previously put - /dev/dri:/dev/dri directly and unconditionally in their devices: block, so any host without an Intel/AMD chip hard-failed on start.

Jellyfin already does this correctly: it gates /dev/dri behind the optional docker-compose.hw.yml overlay, applied only when JELLYFIN_HW_ACCEL is set and the device exists. So on a GPU-less host Jellyfin just starts.

Fix

  1. If you're on Jellyfin and it won't start, the hardcoded-device problem shouldn't apply — check Cause 4 or 5 below, or your reverse proxy for a "refused" error.
  2. If you're editing compose yourself, move /dev/dri out of the base docker-compose.yml and into a separate docker-compose.hw.yml overlay, mirroring Jellyfin. Apply that overlay only on hosts that have the device. GPU hosts still get hardware transcoding; GPU-less hosts start clean.
  3. On SparkBox this is already handled: the base compose for each media module no longer hardcodes the device, and the hardware overlay is layered only when the device is present. Verified live on a GPU-less VPS that previously failed to start.

Cause 4 — Jellyfin asked you to set up again, or your admin password stopped working

If Jellyfin suddenly acts like a fresh install — no libraries, admin locked out, password rejected — this was a separate bug in the restart path, now fixed. A non-root sparkbox restart could misread permission-protected database directories as empty (because the running user couldn't read them) and fire a false restore from backup, clobbering your live state.

SparkBox dashboard login screen
SparkBox dashboard login screen

Fix

  1. Update to a build where this is patched — the restore path is now root-gated with an unreadable-directory guard, so a directory it can't read is no longer treated as empty and won't trigger a restore.
  2. If you were hit before updating, restore your genuine backup (or reconfigure the admin account) once, then update so it can't recur.

Why this looks like a "password" problem: the false restore replaces the account database, so your old admin login and password no longer match anything. It isn't a password bug per se — it's the restore that reset the state.

Cause 5 — Dashboard crashloops and takes Jellyfin's management with it

If the dashboard kept restarting (crashlooping) around a migration or export, this was an out-of-memory (OOM) kill: the migration export walked Jellyfin's image cache — potentially gigabytes of thumbnails — and blew past the dashboard's 128 MB memory limit.

Fix

  1. Update to a build with the patched export. The export is now capped at 10 MB per file with real binary detection, metadata and transcode directories are skipped, and the dashboard memory limit was raised to 256 MB.
  2. After updating, retry the migration/export; it should no longer walk the cache or OOM.

Frequently asked

Why did Jellyfin start transcoding slowly after I restarted it?

Fixed in v1.6.489 — the dashboard restart now re-applies the hardware overlay itself, so the /dev/dri passthrough survives. It used to be dropped, which left Jellyfin software-transcoding on the CPU. If you are on an older release, update; if it persists afterwards, sudo sparkbox doctor will tell you whether the container actually has GPU access.

Does Jellyfin hardware transcoding work with an Nvidia GPU?

Not here yet. The hardware overlay maps only /dev/dri, which is Intel Quick Sync and AMD/Intel VAAPI. Nvidia devices aren't wired into the overlay, so an Nvidia card won't be used for transcoding. Favor direct play in the meantime.

Why does Jellyfin fail to start on a VPS with no GPU?

A hardcoded /dev/dri in the container's devices: block makes Docker refuse to create the container when the device is absent. Jellyfin gates it behind an optional overlay, so it should start; Plex and Emby used to hardcode it and hard-failed until the device was moved to an overlay.

Why did Jellyfin lose my admin login or ask me to set up again?

A non-root restart could misread permission-protected database directories as empty and trigger a false restore from backup, wiping account state. That path is now root-gated with an unreadable-directory guard so it no longer fires by accident. Update and restore your real backup once if you were affected.

Skip the compose-overlay fiddling

SparkBox layers the Jellyfin hardware overlay only when the device is actually present, so your server starts on any box and uses the GPU where it can.

Get SparkBox → Or read the media-server walkthrough →

Questions, or did this not match your box?

Every guide here came from a real problem someone hit. If yours behaves differently, say so — that is how these get corrected, and how the fix gets prioritised.

Ask in the community →

We answer there rather than in a comment box, because that is where the people who have already solved it are.

About this guide: Written and tested by the SparkBox team on a UGREEN DXP4800 Plus and a $7/month Hostinger VPS, both running SparkBox 1.6.314. The causes above are the real ones we've diagnosed in d/sparkbox. If something doesn't match, tell us on YouTube.