Skip to content

Hardware Transcoding

Brandon Johnson edited this page Sep 7, 2026 · 3 revisions

Hardware Transcoding

Transcoding is the one operation that can peg a box. CPU (libx264) always works; NVENC, VAAPI, Quick Sync and VideoToolbox move that work to the GPU.

OBELO_HARDWARE_ACCEL=off | auto | nvenc | vaapi | qsv | videotoolbox

Default is off. auto probes NVENC → VAAPI → QSV and takes the first that validates.


Not every playback transcodes

Before reaching for a GPU, know that Obelo picks one of three tiers per client:

  1. Direct play — the client handles the file as-is. No work at all.
  2. Direct stream (remux) — only the container changes. Cheap.
  3. Transcode — full re-encode. This is the expensive one, and the only tier OBELO_MAX_CONCURRENT_TRANSCODES bounds (default 3, 0 for unlimited).

If your CPU is idle and playback still stutters, the problem is probably not encoding — check the network path first.


OBELO_HARDWARE_ACCEL is a preference, not an instruction

At startup the server validates it against the host in two steps — the encoder must be compiled into ffmpeg, and a one-frame test encode must succeed — then logs the outcome. Read that line first when a GPU seems idle:

obelo: hardware acceleration: using configured hardware backend nvenc (h264_nvenc validated)
obelo: hardware acceleration: WARNING — configured backend nvenc did not validate
       (encoder missing or no working device); falling back to CPU libx264

The warning is never fatal — playback keeps working on CPU libx264. The server also advertises the resolved tier to clients at startup, so what clients believe and what the server can do stay in agreement.


NVIDIA (NVENC)

Requires the NVIDIA Container Toolkit on the host. Nothing else: the toolkit injects the driver libraries, and the image already requests the video capability that carries libnvidia-encode.

docker run -d --name obelo --gpus all -p 8080:8080 \
  -e OBELO_HARDWARE_ACCEL=nvenc \
  -v "$PWD/data:/data" \
  -v /path/to/your/media:/media:ro \
  obelo

GPU telemetry

With NVENC resolved and active, the admin Transcoding tab shows best-effort GPU telemetry — utilization, VRAM, encoder sessions, driver version. It shells out to nvidia-smi, which the container toolkit injects along with the driver.

Without --gpus all, or on any non-NVENC backend, the GPU block reads "unavailable" — that is expected, not a defect. The rest of the tab (resolved backend and live load) works regardless.


Intel / AMD (VAAPI, QSV)

Pass the DRM render node through and add the host's render GID. The image puts its runtime user in a render group, but GIDs are host-specific, so the in-image group alone will usually not match the device's owner:

docker run -d --name obelo -p 8080:8080 \
  --device /dev/dri:/dev/dri \
  --group-add "$(getent group render | cut -d: -f3)" \
  -e OBELO_HARDWARE_ACCEL=vaapi \
  -v "$PWD/data:/data" \
  -v /path/to/your/media:/media:ro \
  obelo

Swap vaapi for qsv on Intel if you want Quick Sync specifically.

A backend that validates when run as root but not as the normal user is the group-permission problem above, not a driver problem. Check --group-add before anything else.

Intel's intel-media-va-driver-non-free decodes a few extra formats, but it lives in Debian's non-free component and is deliberately not baked into the image. Add it yourself in a derived image if you need it.


VideoToolbox (macOS)

OBELO_HARDWARE_ACCEL=videotoolbox applies when running the binary natively on macOS. It is not reachable from the Linux Docker image.


Tuning concurrency

OBELO_MAX_CONCURRENT_TRANSCODES (default 3) is a conservative cap that keeps a single host from being saturated by CPU re-encodes and leaves headroom for the rest of the server.

  • On a GPU, encoding is cheap but your card has a hard limit on simultaneous encoder sessions. Raise the cap toward that limit, not past it.
  • On CPU, watch the Transcoding tab under real household load before raising it.
  • 0 means unlimited, which is a choice about how you would rather fail — every stream degrading together, instead of the fourth one being refused.

Obelo

Home

Getting started

Reference

Going further

Plugins

Sharing with another household

Reaching it from away

When it breaks

Clone this wiki locally