使用シーンの説明#
元々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 ハードデコード設定#
ここでは特に言うことはありません。条件が整ったらすべてチェックを入れます。
結語#
これで 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 |
+---------------------------------------------------------------------------------------+
比較すると、ユーザーがウェブクライアントで再生を行っているとき、jellyfin サーバーがグラフィックカードを使用してデコードを行っており、グラフィックカードのメモリ使用量が 29MiB から 257MiB に変化していることがわかります。このとき実行されているプロセスは ffmpeg です。
したがって、この記事の推論は比較的正しいとまとめることができます。ハードウェアデコードの方法を通じて、jellyfin クライアントで「このクライアントはメディアと互換性がありません。サーバーは互換性のあるメディア形式を送信していません」というメッセージを消すことができます。
また、グラフィックカードがない場合、jellyfin サーバーはデコードを行うことができず、動画デコードの方法はクライアントのローカルで行われるため、ウェブでは再生できないがクライアントアプリでは再生できるという状況が生じることも示しています。このことから、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 ダウンロード