Skip to content

Hardware acceleration

When a video has to be transcoded, the server re-encodes it while you watch. By default that happens on the CPU. If your server has a supported graphics card, Credenza can encode on it instead, which is much faster and uses far less power, so more people can watch at once.

Nothing here is required: without a graphics card, everything still plays, encoded on the CPU.

Hardware Encoder Where it works
NVIDIA NVENC (h264_nvenc) Linux, Windows, and Docker on Linux or Windows
AMD and Intel VA-API (h264_vaapi) Linux, and Docker on Linux
AMD AMF (h264_amf) Only when the server runs directly on Windows, not in Docker. Needs ffmpeg 8.0 or later. The native Windows version is not released yet.
Intel Quick Sync (h264_qsv) Only when the server runs directly on Windows, not in Docker. Needs ffmpeg 8.0 or later. The native Windows version is not released yet.
Apple VideoToolbox (h264_videotoolbox) Only when the server runs directly on a Mac, not in Docker. The native Mac version is not released yet.
Any CPU Software (libx264) Everywhere; always the fallback

A few things to know before you set it up:

  • Decoding and scaling happen on the graphics card too. If the card can’t decode a particular source format, that video is decoded on the CPU and the rest of the work still happens on the card.
  • Docker on a Mac cannot use the GPU. Docker Desktop runs containers in a Linux virtual machine with no access to the Mac’s hardware, so a Mac running Credenza in Docker always encodes in software.
  • Docker on Windows can only use NVIDIA. AMD and Intel cards are not exposed to Linux containers on Windows in a form VA-API can use.
  • The output is always H.264 whichever encoder you use, because that is what every browser plays.

At Settings → Server → Transcoding, the Video encoder choice has two options:

  • Hardware when available (the default) — use a working hardware encoder if there is one, otherwise software.
  • Software only — always encode on the CPU, even with a supported GPU.

Credenza doesn’t guess from your operating system or hardware what will work. For each hardware encoder, it checks that your copy of ffmpeg includes it, then runs a short trial encode. Only an encoder that passes the trial is used. That is what catches the usual problems: a card that isn’t passed into the container, a missing driver, or a missing permission.

The same page shows the result:

  • Currently encoding with names the encoder in use, and whether it is hardware or software.
  • Hardware encoders on this server lists each hardware encoder as available, or unavailable with the reason, for example “h264_vaapi is not compiled into this ffmpeg build”, “not supported on this operating system” or the error from the failed trial encode.

Check this page after any change to your setup. If a card you expected is listed as unavailable, the reason tells you where to look.

A change to the encoder, or to any setting it depends on, applies to the next video started. Anything already playing keeps the encoder it began with.

Docker: give the container your graphics card

Section titled “Docker: give the container your graphics card”

The standard Docker setup doesn’t give the container access to a GPU, so a server with a perfectly good graphics card encodes on its CPU until you add one. Save the file for your card as docker-compose.override.yml beside your docker-compose.yml, then run docker compose up -d again. Docker Compose merges the two files automatically.

The container image already includes an ffmpeg with NVENC and VA-API support, plus the AMD and Intel VA-API drivers, so you don’t need to install anything inside it.

You need NVIDIA’s driver and the NVIDIA Container Toolkit installed on the host. This works on Windows too, under Docker Desktop.

services:
credenza:
environment:
NVIDIA_DRIVER_CAPABILITIES: compute,utility,video
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu, video]

Linux only. The container needs the render device and membership of the group that owns it. First add that group’s ID to your .env file:

Terminal window
echo "RENDER_GID=$(stat -c %g /dev/dri/renderD128)" >> .env

Then save the override file:

services:
credenza:
devices:
- /dev/dri:/dev/dri
group_add:
- "${RENDER_GID:?set RENDER_GID in .env}"

Run docker compose up -d, then open Settings → Server → Transcoding to confirm the encoder is listed as available.

The Linux installer runs Credenza as its own credenza user and has already added that user to the video and render groups where your system has them, which is what gives it access to the graphics card. What’s left is the driver:

  • AMD: install your distribution’s Mesa VA-API driver (on Debian and Ubuntu, mesa-va-drivers).
  • Intel: install Intel’s VA-API driver (on Debian and Ubuntu, intel-media-va-driver).
  • NVIDIA: install NVIDIA’s proprietary driver.

Then restart the service and check the transcoding page:

Terminal window
sudo systemctl restart credenza

If the page reports that an encoder is not compiled into this ffmpeg build, your distribution’s ffmpeg was built without it. Install an ffmpeg build that includes it and restart.

NVIDIA beside Intel or AMD: if both NVENC and VA-API pass their trials, NVENC is used.

On Windows: AMF always uses the AMD card and Quick Sync always uses the Intel one, so there’s nothing to set. The exception is two cards from the same maker, such as Intel graphics beside an Intel Arc card. Credenza then uses whichever one Windows lists first, which is usually the built-in one, and there’s no setting to change that yet. If more than one passes its trial, NVENC is used first, then AMF, then Quick Sync. That puts a discrete card ahead of the processor’s built-in graphics.

Two cards for VA-API: VA-API encodes on the card set in VAAPI device, which defaults to /dev/dri/renderD128, the first card. To use the second, set it to its render node, usually /dev/dri/renderD129. Changing it re-runs the trial encode, so the page tells you straight away whether the new card works.

Consumer NVIDIA cards (GeForce) will only run a limited number of encodes at once, set by the driver: typically 2 on older drivers, 3 on most, and 5 or more on recent ones. The driver doesn’t report its limit; it simply refuses the next session.

So Credenza asks you. NVENC session limit (default 2) is how many streams it sends to the card. Streams beyond that are encoded on the CPU rather than refused. With the defaults, the first two viewers are encoded on the card and the next two on the CPU. When a limit is set, the page says so: “…which encodes 2 streams at once. Anything beyond that is encoded by the CPU, up to the concurrent stream limit below.”

Raise it if you know your driver allows more. Set it to 0 for no limit, for professional and datacenter cards, which have none. A stream that started on the CPU stays there until it stops, even if the card frees up.

Below the encoder choice, the Quality and limits section sets how every transcode behaves. Each box shows the value the server is currently configured with. Type over it to change it, or clear it and save to go back to the configured value.

Setting Default What it does
Concurrent streams 4 How many videos are transcoded at once, on any encoder. The only limit that turns a viewer away. Direct-play streams don’t count. 0 means no limit.
Encoder preset veryfast Speed against quality, fastest first. Slower presets give smaller streams at the same quality but cost more CPU per stream. Hardware encoders translate it as best they can.
Quality (CRF) 21 Lower is better quality and larger streams; 18 to 28 is the usual range. Hardware encoders approximate it or rely on the bitrate ceiling instead.
Bitrate ceiling 8M The most any transcode will send. Every quality in the player’s menu is capped to it. Write it as megabits (8M), kilobits (800k) or bits per second (8000000).
Audio bitrate 192k For audio at Original quality. Audio is always re-encoded to stereo AAC.
Segment length 6 seconds Shorter means faster seeking and more files; longer means a seek waits for more video to encode.
Idle timeout 300 seconds A stream nobody has requested anything from for this long is stopped.
Segment timeout 30 seconds How long the player waits for a piece of video before giving up. Raise it on a slow machine that stutters after seeking.
Lookahead tolerance 3 segments How far ahead of the encoder a request can be before the server restarts the encode there instead of waiting.
Transcoding folder see below Where segments are written while someone watches.
NVENC session limit 2 See NVIDIA session limits.
VAAPI device /dev/dri/renderD128 See More than one graphics card.

Most settings apply to the next video started. Concurrent streams, Idle timeout and Transcoding folder apply immediately.

While someone watches a transcoded video, its segments are written to the transcoding folder. That’s roughly a gigabyte per hour of 1080p, per viewer. They’re deleted when the stream stops, and anything left behind by a crash or power cut is cleaned up the next time the server starts.

Install Default folder
Docker /tmp/credenza inside the container. It deliberately isn’t on your data volume, because nothing there is worth keeping.
Linux packages /var/cache/credenza/transcode

To move it, set Transcoding folder to an absolute path, typing it or using the folder browser. The server checks that it can write there before saving. In Docker, the path is inside the container, so mount the directory you want into the container first.

Speed matters more than size here: every segment is written and then read back within seconds, so fast local storage is worth much more than a large, slow disk or a network share.

Credenza always falls back to software encoding rather than failing. That happens when:

  • no hardware encoder passes its trial, for example because the card isn’t passed into the container or the driver is missing;
  • Software only is selected;
  • an NVIDIA card is already running as many streams as NVENC session limit allows.

In every case the video plays, just with more CPU. The transcoding page, and the Encoder row in the playback stats panel, tell you which encoder a stream is really using.