Running a server
Transcoding and hardware acceleration
When Wren TV transcodes, which GPUs it uses, and how to pass a GPU through to Docker.
Wren TV avoids transcoding. Most plays are direct play or a lossless remux, which use almost no CPU. Transcoding only happens when:
- the player can't decode the video codec at all (for example HEVC in a browser without HEVC support),
- the player can't show HDR, so the video must be tone-mapped to SDR, or
- the viewer picked a lower quality than the file's bitrate.
A transcode produces 8-bit SDR H.264 video in HLS. Seeking starts a new encode from the new position.
Hardware acceleration
With hwaccel: auto (the default), the server tries the likely GPUs for the platform at start-up, runs a tiny test
encode on each, and uses the first that works. If none works, it uses software encoding (libx264).
| Platform | Tried in order |
|---|---|
| macOS | VideoToolbox |
| Linux | NVIDIA (NVENC), Intel (Quick Sync), VAAPI (Intel and AMD) |
| Windows | NVIDIA (NVENC), Intel (Quick Sync), AMD (AMF) |
The Manage status page shows which encoder is in use. To pin one, set Hardware acceleration in
Manage → Settings, transcode.hwaccel, or WRENTV_HWACCEL:
| Value | Uses |
|---|---|
auto | Detect (the default) |
videotoolbox | Apple VideoToolbox |
nvenc | NVIDIA NVENC |
qsv | Intel Quick Sync |
vaapi | VAAPI on Linux (Intel or AMD). The device is transcode.vaapi_device, default /dev/dri/renderD128 |
amf | AMD AMF on Windows |
none | Software only |
Decoding also runs on the GPU when it can, so 4K HEVC sources don't load the CPU.
HDR to SDR tone mapping
When an HDR10 or Dolby Vision file has to be transcoded for an SDR screen, its colours are tone-mapped so it doesn't look washed out:
- On the GPU with VideoToolbox, Quick Sync and VAAPI.
- On the CPU otherwise, with ffmpeg's
zscaleand the Hable curve. This needs an ffmpeg built with zimg, which jellyfin-ffmpeg and most distribution builds have.
Docker
The Docker image bundles jellyfin-ffmpeg, which supports every method above. You only need to give the container the GPU.
Intel and AMD (Quick Sync, VAAPI)
yaml devices:
- /dev/dri:/dev/dri
If it doesn't get picked up, check that the user running Docker's containers can read /dev/dri/renderD128 (it usually
belongs to the render group).
NVIDIA (NVENC)
Install the NVIDIA Container Toolkit on the host, then:
yaml deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu, video, compute, utility]
Native installs
- Linux: the service user needs to be in the
renderandvideogroups for/dev/dri. The provided systemd unit does that. Use an ffmpeg with your GPU's support built in. jellyfin-ffmpeg is a good choice. - macOS: VideoToolbox works with Homebrew's ffmpeg.
- Windows: use the jellyfin-ffmpeg portable build, and an up-to-date GPU driver.
Scratch space
Transcoded segments are written to <data>/transcode and cleaned up when playback stops. Put it on a fast disk, or in
RAM, with transcode.scratch_dir. With Docker you can mount it:
yaml volumes:
- /dev/shm/wrentv:/config/transcode
ffmpeg location
The server looks for ffmpeg and ffprobe on the PATH. Point it elsewhere with transcode.ffmpeg_path and
transcode.ffprobe_path, or WRENTV_FFMPEG and WRENTV_FFPROBE.