banner
Aki

Aki

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

dockerコンテナGPUパススルー——jellyfinハードウェアデコード

使用シーンの説明#

元々jellyfin はサーバーの k8s 環境内に展開されており、独立したグラフィックカードがなく、CPU だけではサーバー側のハードウェアデコードを実現するのが難しく、任意のプラットフォームでブラウザを通じてメディアを視聴する際に「このクライアントはメディアと互換性がありません。サーバーは互換性のあるメディア形式を送信していません」と表示されることがありました。

自宅のデスクトップに ubuntu をインストールした後、サービスサーバーとして利用することを思いつき、完全に作業やエンターテイメント環境から切り離しました。そこで docker をインストールし、docker を通じて jellyfin を展開した後、pci ハードウェアを介して jellyfin にハードデコードの能力を持たせたいと考えました。

まさか、まだグラフィックカードのドライバーをインストールしておらず、グラフィックカードをコンテナに割り当てていないとは思いませんでした。これが、このプロセスを記録するための記事を書くことになった理由です。

状況分析#

クライアントは「このクライアントはメディアと互換性がありません。サーバーは互換性のあるメディア形式を送信していません」と表示します。推測される理由は、サーバー自体の条件が制限されており、クライアントにハードウェアデコードを要求して動画再生をサポートする必要があるためであり、ブラウザに対応する動画形式のデコード能力がない場合にこのメッセージが表示されます。
おそらく、ブラウザ拡張をインストールしてクライアントのデコードをサポートすることを試みることができるかもしれません(実現可能性は未確認)。

個人的な体験に基づく推測では、元の k8s 環境下の jellyfin は PC のブラウザで任意の動画を再生する際に上記のメッセージが表示されました。しかし、potplayer やjellyfin クライアント、iOS 端の fileball などのアプリを使用してデコードすることで正常に再生できました。この状況は emby でも同様に発生しています。

したがって、ブラウザが再生できない原因を推測します。根本的には、サーバー側にデコード能力が不足しているためです。

解決策#

適用シーン:linux サーバー(私が使用しているのは ubuntu22.04)、k8s 環境(unraid や群晖ではない)

グラフィックカードドライバーのインストール ——NVIDIA GTX1660TI を例に#

amd のドライバーのインストール方法は自分で Google や百度で調べてください。方法は同じです。

方法一(オフラインインストール):

公式サイトからドライバーインストールパッケージをダウンロードし、サーバーにアップロードして、dpkg -i の方法でインストールします。純粋なコマンドラインでのインストールが必要です。lightdm デスクトップ環境を有効にしている場合は、手動で終了する必要があります。

# rootユーザーでログインすることに注意
> systemctl stop lightdm
# 純粋なコマンドラインモードに入る
> init 3
> dpkg -i <ダウンロードしたnvidiaドライバーパッケージ、deb拡張子>

# インストールが終了したら再起動できます。復元できない場合は、以下のコマンドを実行してから再起動してください。
> init 5
> systemctl set-default graphical.target

方法二(オンラインインストール、推奨):

1、ドライバー

# まず、コンピュータがpciグラフィックカードを認識できるか確認します。
> lspci | grep -i nvidia
26:00.0 VGA互換コントローラー: NVIDIA Corporation TU116 [GeForce GTX 1660 Ti] (rev a1)
26:00.1 オーディオデバイス: NVIDIA Corporation TU116 ハイディフィニションオーディオコントローラー (rev a1)
26:00.2 USBコントローラー: NVIDIA Corporation TU116 USB 3.1 ホストコントローラー (rev a1)
26:00.3 シリアルバスコントローラー: NVIDIA Corporation TU116 USB Type-C UCSI コントローラー (rev a1)

# 現在のシステムがサポートしているドライバーを確認します。
> 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 推奨
driver   : nvidia-driver-470 - distro non-free
driver   : xserver-xorg-video-nouveau - distro free builtin

## 最新のドライバーをインストールします。
> apt-get install nvidia-driver-535.54.03

## 再起動後に実行し、グラフィックカード情報を確認します。
> nvidia-smi
Mon Jul  3 00:05:19 2023       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.54.03              Driver Version: 535.54.03    CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  名称                 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 |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| プロセス:                                                                            |
|  GPU   GI   CI        PID   タイプ   プロセス名                            GPUメモリ |
|        ID   ID                                                             使用量      |
|=======================================================================================|
|    0   N/A  N/A      3283      G   /usr/lib/xorg/Xorg                           25MiB |
|    0   N/A  N/A     26860      G   xfwm4                                         1MiB |
+---------------------------------------------------------------------------------------+

2、CUDA
上記の CUDA Version はインストール可能なバージョン情報であり、すでにインストールされていることを示すものではありません。インストール方法は以下の通りです(コマンドは英伟达公式からのものです):

> 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

実行後、環境変数を設定し、~/.bashrc ファイルの末尾に以下を追加します。

> vim ~/.bashrc
#以下の内容を追加します。バージョン番号に注意してください。
export PATH=/usr/local/cuda-12.2/bin${PATH:+:${PATH}}

#nvidia-persistencedデーモンが起動しているか確認します。
> 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

どの方法でグラフィックカードドライバーをインストールしても、インストール後に再起動が必要です。

docker パススルー#

1、nvidia-docker2 と nvidia-container-runtime をインストールします。
グラフィックカードを docker にマウントするとエラーが発生し、コンテナが常に create 状態になります。

# aptソースを追加します。
> 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

2、コンテナを実行してグラフィックカードドライバーをマウントします。
docker-compose を例にします。

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 ハードデコード設定#

ここでは特に言うことはありません。条件が整ったらすべてチェックを入れます。

image

結論#

これで jellyfin のハードウェアパススルーが完了したことになります。実際にテストしたところ、元々動画再生がサポートされていなかったブラウザでもメディア再生が可能になりました。
また、ユーザーがメディアを再生しているとき、グラフィックカードの実際のメモリ使用量の変化を明確に観察できます。

Mon Jul  3 00:47:21 2023       
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.54.03              Driver Version: 535.54.03    CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  名称                 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 |
+-----------------------------------------+----------------------+----------------------+
                                                                                         
+---------------------------------------------------------------------------------------+
| プロセス:                                                                            |
|  GPU   GI   CI        PID   タイプ   プロセス名                            GPUメモリ |
|        ID   ID                                                             使用量      |
|=======================================================================================|
|    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 |
+---------------------------------------------------------------------------------------+

比較してみると、ユーザーが Web クライアントで再生を行っているとき、jellyfin サーバーがグラフィックカードを使用してデコードを行っており、グラフィックカードのメモリ使用量が 29MiB から 257MiB に変化していることがわかります。このとき実行されているプロセスは ffmpeg です。

したがって、この記事の推論は比較的正しいとまとめることができます。ハードウェアデコードの方法を通じて、jellyfin クライアントで「このクライアントはメディアと互換性がありません。サーバーは互換性のあるメディア形式を送信していません」というメッセージを解消することができます。

また、グラフィックカードがない場合、jellyfin サーバーはデコードを行うことができず、動画デコードの方法はクライアントのローカルで行われるため、Web では再生できないがクライアントアプリでは再生できるという状況が生じることも示しています。このことから、jellyfin 上でサードパーティの ffmpeg クライアントが設定されていても、クライアントのローカルデコードには影響を与えず、エラーメッセージが表示されるのは単にサーバーのデコード能力が不足しているためであることがわかります。

余談
nvidia-docker2 は nvidia が docker コンテナをサポートするためのコンポーネントであり、docker 方式でサービスを展開しない場合はインストールする必要はありません。
同様の方法は stable diffusion の docker プロジェクトにも適用でき、リモートでの生成を実現できます🫠

参考資料#

1、Pop!_OS 22.04(Ubuntu 22.04)に Nvidia GPU ドライバー、CUDA、cuDNN、および Docker GPU サポート(nvidia-docker2)をインストールする
2、CUDA Toolkit 12.1 ダウンロード

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。