banner
Aki

Aki

太阳能维修,月亮可更换,星星不闪包退换。
twitter

Docker container GPU passthrough - Jellyfin hardware decoding

Use Case Description#

Originally, Jellyfin was deployed in a server's k8s environment without a dedicated graphics card. Relying solely on the CPU made it difficult to achieve server-side hardware decoding, resulting in a message stating "This client is incompatible with the media, and the server did not send a compatible media format" when watching media through a browser on any platform.

After installing Ubuntu on my desktop at home, I had the sudden idea to use it as a server, completely separating it from my work and entertainment environment. After installing Docker and deploying Jellyfin through Docker, I wanted to enable Jellyfin to achieve hardware decoding capabilities through PCI hardware.

I never expected that I hadn't installed the graphics card driver yet, nor had I allocated the graphics card to the container. This led to this article documenting the troubleshooting process.

Situation Analysis#

The client prompts "This client is incompatible with the media, and the server did not send a compatible media format." The suspected reason is that the server's own conditions are limited, requiring the client to perform hardware decoding to support video playback. If the browser does not have the corresponding video format decoding capability, this message will appear.
Perhaps one could try installing a browser extension to support client decoding (feasibility unverified).

Based on personal experience, the original Jellyfin in the k8s environment displayed the above message when playing any video in the PC's browser. However, decoding through apps like PotPlayer, Jellyfin Client, and iOS's Fileball worked normally. This situation also occurred with Emby.

Thus, it is inferred that the reason for the browser's inability to play is fundamentally due to the server's lack of decoding capability.

Solution#

Applicable scenario: Linux server (I am using Ubuntu 22.04), k8s environment (not Unraid or Synology).

Graphics Card Driver Installation — Taking NVIDIA GTX 1660 Ti as an Example#

For AMD solutions, please Google or Baidu how to install drivers. The methods are the same.

Method 1 (Offline Installation):

Download the driver installation package from the official website, upload it to the server, and install it using dpkg -i, requiring a pure command-line installation. If the lightdm desktop environment is enabled, it needs to be manually closed.

# Note: Log in as the root user
> systemctl stop lightdm
# Enter pure command-line mode
> init 3
> dpkg -i <downloaded NVIDIA driver package with .deb suffix>

# After installation, reboot to restore. If it does not restore, please execute the following command and then reboot
> init 5
> systemctl set-default graphical.target

Method 2 (Online Installation, Recommended):

  1. Driver
# First, check if the computer can recognize the PCI graphics card
> lspci | grep -i nvidia
26:00.0 VGA compatible controller: NVIDIA Corporation TU116 [GeForce GTX 1660 Ti] (rev a1)
26:00.1 Audio device: NVIDIA Corporation TU116 High Definition Audio Controller (rev a1)
26:00.2 USB controller: NVIDIA Corporation TU116 USB 3.1 Host Controller (rev a1)
26:00.3 Serial bus controller: NVIDIA Corporation TU116 USB Type-C UCSI Controller (rev a1)

# Check the currently supported drivers in the system
> ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:03.1/0000:26:00.0 ==
modalias : pci:v000010DEd00002182sv000019DAsd00003539bc03sc00i00
vendor   : NVIDIA Corporation
model    : TU116 [GeForce GTX 1660 Ti]
driver   : nvidia-driver-525 - distro non-free
driver   : nvidia-driver-470-server - distro non-free
driver   : nvidia-driver-535-open - distro non-free
driver   : nvidia-driver-418-server - distro non-free
driver   : nvidia-driver-525-open - distro non-free
driver   : nvidia-driver-525-server - distro non-free
driver   : nvidia-driver-450-server - distro non-free
driver   : nvidia-driver-535 - distro non-free recommended
driver   : nvidia-driver-470 - distro non-free
driver   : xserver-xorg-video-nouveau - distro free builtin

## Install the latest driver support
> apt-get install nvidia-driver-535.54.03

## After rebooting, execute to check graphics card information
> nvidia-smi
Mon Jul  3 00:05:19 2023       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.54.03              Driver Version: 535.54.03    CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce GTX 1660 Ti     Off | 00000000:26:00.0 Off |                  N/A |
| 46%   41C    P8              13W / 120W |     29MiB /  6144MiB |      0%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A      3283      G   /usr/lib/xorg/Xorg                           25MiB |
|    0   N/A  N/A     26860      G   xfwm4                                         1MiB |
+---------------------------------------------------------------------------------------+
  1. CUDA
    The above CUDA Version indicates the installable version information, not that it has been installed. The installation method is as follows (commands from NVIDIA official):
> wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
> dpkg -i cuda-keyring_1.1-1_all.deb
> apt-get update
> apt-get -y install cuda

After execution, set the environment variables by adding the following to the end of the ~/.bashrc file:

> vim ~/.bashrc
# Add the following content, pay attention to the version number
export PATH=/usr/local/cuda-12.2/bin${PATH:+:${PATH}}

# Confirm whether the nvidia-persistenced daemon is enabled
> systemctl status nvidia-persistenced
● nvidia-persistenced.service - NVIDIA Persistence Daemon
     Loaded: loaded (/lib/systemd/system/nvidia-persistenced.service; static)
     Active: active (running) since Sun 2023-07-02 05:43:54 CST; 18h ago
    Process: 1937 ExecStart=/usr/bin/nvidia-persistenced --user nvidia-persistenced --no-persistence-mode --verbose (code=exited, status=0/SUCCESS)
   Main PID: 1947 (nvidia-persiste)
      Tasks: 1 (limit: 47904)
     Memory: 568.0K
        CPU: 3ms
     CGroup: /system.slice/nvidia-persistenced.service
             └─1947 /usr/bin/nvidia-persistenced --user nvidia-persistenced --no-persistence-mode --verbose

Regardless of which method is used to install the graphics card driver, a reboot is required afterward.

Docker Pass-Through#

  1. Install nvidia-docker2 and nvidia-container-runtime
    When mounting the graphics card to Docker, an error occurs, causing the container to remain in the create state.
# Add apt source
> distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
      && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
      && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
            sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
            sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

> apt update
> apt-get install -y nvidia-docker2 nvidia-container-runtime
  1. Run the container to mount the graphics card driver
    Using docker-compose as an example:
version: "3.7"
services:
  jellyfin:
    container_name: jellyfin
    image: "jellyfin/jellyfin:latest"
    environment:
        - PUID=0
        - GUID=0
        - NVIDIA_DRIVER_CAPABILITIES=all
        - NVIDIA_VISIBLE_DEVICES=all
    ports:
        - "10029:8096"
    volumes:
        - "/root/jellyfin/config:/config"
        - "/mnt/media:/media"
    restart: always
    user: root
    devices:
        - "/dev/dri:/dev/dri"
    deploy:
        resources:
            reservations:
                devices:
                  - capabilities: ["gpu"]

Jellyfin Hardware Decoding Settings#

There isn't much to say here; just check all the options if conditions allow.

image

Conclusion#

At this point, the hardware pass-through for Jellyfin is complete. It has been tested that browsers that previously did not support video playback can now play media. Furthermore, when a user is playing media, it is evident to observe the actual memory usage changes of the graphics card.

Mon Jul  3 00:47:21 2023       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.54.03              Driver Version: 535.54.03    CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA GeForce GTX 1660 Ti     Off | 00000000:26:00.0 Off |                  N/A |
| 46%   44C    P2              31W / 120W |    257MiB /  6144MiB |      3%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|    0   N/A  N/A      3725      G   /usr/lib/xorg/Xorg                           13MiB |
|    0   N/A  N/A      6735      C   /usr/lib/jellyfin-ffmpeg/ffmpeg             238MiB |
+---------------------------------------------------------------------------------------+

It is observed that when a user plays through the web client, the Jellyfin server is using the graphics card for decoding, with the graphics card memory usage changing from 29MiB to 257MiB, where the running process is ffmpeg.

Thus, it can be concluded that the inference in this article is relatively correct. The hardware decoding method can eliminate the prompt "This client is incompatible with the media, and the server did not send a compatible media format" that appears on the Jellyfin client.

This also indirectly indicates that without a graphics card, the Jellyfin server cannot perform decoding, and video decoding is done locally by the client, which explains why playback is not possible on the web but works on client apps. It can also be inferred that in this case, whether or not third-party ffmpeg clients are set on Jellyfin does not affect local decoding by the client, and the error message appears solely due to insufficient decoding capability on the server.

Aside
NVIDIA-docker2 is NVIDIA's support component for Docker containers. If you do not deploy services using Docker, you can skip this installation. The same method can be applied to the stable diffusion Docker project for remote processing 🫠

References#

  1. Installing NVIDIA GPU Drivers, CUDA, cuDNN, and Docker GPU Support (nvidia-docker2) on Pop!_OS 22.04 (Ubuntu 22.04)
  2. CUDA Toolkit 12.1 Downloads
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.