目次 — 知りたいところから読む

動画・音楽のストリーミング配信には、オープンソースのメディアサーバーであるJellyfinを使っている。ここではその構成、特にGPUを使ったハードウェアトランスコードの仕組みを記す。

JellyfinJellyfin
NVIDIANVIDIA

画像: Jellyfinロゴ(CC BY-SA 4.0) / NVIDIAロゴ(Apache 2.0)、Wikimedia Commons

図1 · ボタンで表示を切り替え
Jellyfinがクライアントの対応能力に応じ、互換性のある動画を直接配信する経路と、NVENCでコーデックやビットレートを変換して配信する経路を選ぶ仕組み

図: Duskcoil作成。Direct PlayとGPUハードウェアトランスコードの分岐を示している。

Jellyfin: セルフホスト型メディアサーバー

Jellyfinは、対応する各種クライアントアプリ(スマートフォン・スマートTV・ブラウザ)から、家庭内サーバーに保管した動画・音楽ライブラリへアクセスできるメディアサーバーソフトウェアである。商用サービスと異なり、視聴履歴やライブラリの内容が外部へ送信されることはない。

GPUハードウェアトランスコード

クライアント側の再生環境(解像度・対応コーデック・回線帯域)によっては、元の動画ファイルをそのまま送るのではなく、再生時にリアルタイムでコーデック変換(トランスコード)する必要がある。この処理をCPUで行うと非常に重く、同時再生数や画質の制約になる。

そこで、NVIDIA GPUのハードウェアエンコーダ(NVENC)をコンテナに直接渡し(GPUパススルー)、トランスコード処理をGPU側で行わせている。具体的には、コンテナのランタイムにNVIDIAドライバのデバイスをgpu/compute/videoの3つのケイパビリティで予約させ、コンテナ内から物理GPUの動画エンコード機能を直接呼び出せるようにしている。CPUトランスコードと比較して消費電力・処理時間の両面で有利であり、複数クライアントからの同時アクセスにも余裕を持って対応できる。

ネットワークモードとメモリ上限の選択

Jellyfinはコンテナのネットワークをホストと共有するモードで動かしている。ローカルネットワーク上のクライアント(スマートTVやスマートフォンアプリ)がJellyfinサーバーを自動検出するための仕組み(UDPブロードキャストによるディスカバリ)が、通常のブリッジネットワークだと正しく機能しないためで、動画配信という用途上、自動検出の利便性を優先した判断である。あわせて、メモリ使用量の上限をコンテナ単位で明示的に設定し、大きなライブラリのスキャンやトランスコード処理が他のコンテナのメモリを圧迫しないよう分離している。

公開範囲の見落としと修正

サーバー全体の待受設定を横断点検した際、Jellyfinもループバック限定ではなく同一ネットワーク内の全端末から直接到達可能な状態になっていたことが判明した。この設定はGUI側の管理画面からは変更できない項目で、コンテナ内部の設定ファイルを直接編集してループバックアドレスを許可リストに加える形で対処している。動画・音楽ライブラリという性質上、視聴履歴や保有コンテンツの一覧が外部から見えてしまうリスクがあり、他の自己ホスト型サービス群と同じ基準で修正した。

もう一点、外部公開用のリバースプロキシ/トンネル側の設定を別サービスの作業中に誤って上書きしてしまい、Jellyfinへの外部からのアクセスが一時的に不能になった事故もあった。復旧の過程で判明したのは、外部公開用のリスナーとJellyfin自身の待受ポートを同じ番号にしていると、TLSハンドシェイクの段階でエラーになるという制約である。以降は、外部から見える番号とコンテナ内部で実際に使う番号を意図的に分離する構成にしている。この「外部/内部ポート分離」は、このサーバーの他のサービス全般に共通するパターンでもある。

なお、この整理作業の中で、統合ダッシュボード上のJellyfinへのリンクが、ポート番号を指定し忘れたまま別サービス(一般公開しているホームオートメーション基盤)の公開先と偶然一致してしまっていたという設定ミスも見つかっている。動作確認を怠ると、リンク自体はエラーにならず単に別のサービスに繋がってしまうため、しばらく気づかれずに残っていた。

唯一サブパス配信に対応していたアプリ

複数のサービスを1つの公開ポートに集約する取り組み(アクセス制御の記事を参照)の中で、Jellyfinは数少ない例外として、公式にBase URL設定(配信パスの先頭に任意のプレフィックスを付ける機能)を持っていることが分かった。他の大半の自己ホスト型アプリはサブパス配信を公式サポートしていないため、この方式を汎用的な解決策として使うことはできなかったが、Jellyfinと統合ダッシュボードの2つだけは、この機能のおかげで1つの公開ポートに同居させられている。

理解を確かめる
動画を再生できれば全端末で同じ負荷になる?

直接再生とトランスコードでは負荷が違う。端末の対応形式、字幕、通信条件を確認する。

参考リンク

#Jellyfin