Installation
Hardware acceleration
Which GPU paths Fliks supports, how it picks one automatically, and how to give it access on each platform.
How detection works#
Fliks probes for hardware acceleration once, at server startup, by actually running a one-frame encode through FFmpeg for each candidate and seeing which one succeeds. It never assumes a GPU path works just because a device file exists; whichever probe passes first wins, and if none do, it falls back to CPU (software) encoding. The probe order is fixed per platform:
| Platform | Probe order |
|---|---|
| Linux | Intel QSV → VAAPI → NVIDIA NVENC → CPU |
| Windows | Intel QSV → AMD AMF → NVIDIA NVENC → CPU |
| macOS | Apple VideoToolbox → CPU |
You don't choose a path yourself; you give the server access to a device (see below) and it
takes care of the rest. The server log records each probe at startup (HW accel test passed: qsv, or HW accel test failed: ... with FFmpeg's reason), and the
Transcoding dashboard shows which path an active stream
is actually using. Change the device setup, then restart the server so it probes again.
Codec support by path#
| Codec | CPU | Intel QSV | VAAPI | NVIDIA NVENC | AMD AMF | VideoToolbox |
|---|---|---|---|---|---|---|
| H.264 | Yes | Yes | Yes | Yes | Yes | Yes |
| HEVC | Yes | Yes | Yes | Yes | Yes | Yes |
| AV1 | Yes | Yes | Yes | Yes | Yes | No |
A "Yes" means Fliks has an encoder for that path. Whether the hardware actually encodes a codec depends on the GPU generation (AV1 needs a recent one); when it can't, Fliks falls back.
HDR10, HLG and Dolby Vision are tone-mapped to SDR automatically when the receiving device can't render HDR itself, on whichever path is active (including CPU). Keeping HDR through a transcode is narrower: only HEVC on QSV and NVENC, and AV1 on NVENC, write HDR metadata in hardware, and every other backend hands an HDR transcode to the CPU encoder. See HDR and Dolby Vision.
Docker: Intel QSV / VAAPI#
Pass the render node through as a device. This also covers AMD GPUs, which go through VAAPI:
services:
fliks:
devices:
- /dev/dri:/dev/driThe container runs as root by default, which can open the device. If you pinned a non-root
user: (see Running as a specific user), that user
also needs the host group owning /dev/dri/renderD128, usually render. Find its numeric id
with getent group render on the host and add it next to 0:
group_add: ['0', '<render gid>']Docker: NVIDIA NVENC#
Needs the NVIDIA Container Toolkit installed on the host:
services:
fliks:
runtime: nvidia
environment:
NVIDIA_VISIBLE_DEVICES: all
# video = NVENC/NVDEC, compute = the CUDA filters (scale_cuda),
# utility = nvidia-smi
NVIDIA_DRIVER_CAPABILITIES: compute,video,utilityThe fliks service in the example file already has an environment: block: add the two
NVIDIA_ lines to it rather than writing a second environment: key.
Docker: architecture note#
The Intel and NVIDIA stacks are amd64-only. On arm64 (a Raspberry Pi 5, an ARM NAS), the
image still pulls and runs fine, but every transcode falls back to CPU.
Windows and macOS#
Both native builds detect hardware automatically at launch: QSV, AMF or NVENC on Windows
(NVENC needs an NVIDIA driver 570 or newer), VideoToolbox on macOS. Nothing to configure; see
Windows and macOS.
Multi-GPU hosts#
On a Linux host with more than one GPU, Settings > Streaming shows a GPU device picker (hidden when only one GPU is detected) listing every render node Fliks found, so you can pin transcoding to a specific adapter instead of letting it auto-pick.
Two related low-level knobs, only worth touching when the automatic pick lands on the wrong device:
| Variable | What it does |
|---|---|
FLIKS_OPENCL_DEVICE |
Pins the platform.device OpenCL selector (e.g. 0.0) used for HDR tone-mapping on the NVENC/CPU path, when auto-pick chooses the wrong vendor on a mixed Intel+NVIDIA host. |
THUMB_HWACCEL_DEVICE |
Which render node generates thumbnails during a scan: off to force software, or a specific render node. |
Subtitle burn-in and cropping#
Two situations force a step down from the detected hardware path, by design rather than as a bug:
- Burning subtitles into the video needs the frame in regular CPU memory (the library that draws them can't reach GPU surfaces), so any stream that burns in subtitles runs on CPU, except on VideoToolbox, whose decode already lands in CPU-accessible buffers.
- Cropping black bars on Intel QSV sometimes requires a detour through VAAPI on Linux, because QSV's own frame pool can't take the variably-sized output crop produces in every situation.
Both fall back automatically; you won't see an error, just a different path in the Transcoding dashboard than you might expect.
See also#
- Streaming and transcoding for how Fliks decides between Direct Play, Direct Stream and Transcode in the first place.
- Transcoding dashboard to see which path each active stream is actually using.
- Environment variables for the full list, including the streaming tunables that live in Settings > Streaming instead.