Repository navigation
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 | videotoolboxDefault is off. auto probes NVENC → VAAPI → QSV and takes the first that
validates.
Before reaching for a GPU, know that Obelo picks one of three tiers per client:
- Direct play — the client handles the file as-is. No work at all.
- Direct stream (remux) — only the container changes. Cheap.
-
Transcode — full re-encode. This is the expensive one, and the only tier
OBELO_MAX_CONCURRENT_TRANSCODESbounds (default3,0for unlimited).
If your CPU is idle and playback still stutters, the problem is probably not encoding — check the network path first.
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.
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 \
obeloWith 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.
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 \
obeloSwap 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-addbefore 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.
OBELO_HARDWARE_ACCEL=videotoolbox applies when running the binary natively on
macOS. It is not reachable from the Linux Docker image.
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.
-
0means unlimited, which is a choice about how you would rather fail — every stream degrading together, instead of the fourth one being refused.
Getting started
Reference
Going further
Plugins
Sharing with another household
Reaching it from away
When it breaks