
Jellyfinとは、自宅のサーバーやNASに保存した動画・音楽・写真を、テレビやスマホ、ブラウザから再生できるようにする無料・オープンソースのメディアサーバーです。作品名やポスター画像を自動で取得してライブラリを作り、再生する端末が対応していない形式は、サーバー側で変換(トランスコード)して届けます。
この記事では、Docker版のJellyfin 12.1.0(執筆時点のイメージ)を使い、Composeでの起動、フォルダの命名規則、初期設定、Intel内蔵GPUでのハードウェアトランスコード、家の外から見る方法までを説明します。初期設定とライブラリの読み込みは実際に動かして確認しました。検証用のサーバーにはGPUがないため、ハードウェアトランスコードは執筆時点の設定項目と確認コマンドの説明にとどめています。
この記事でわかること
- Jellyfin・Plex・Embyの違いと、ハードウェア選びを左右する「トランスコードするかどうか」
- Docker Composeでの起動と、使うポート(8096・8920・7359/udp)
- 作品を正しく認識させるフォルダ構成と命名規則
- Intel Quick Sync(VA-API)でのハードウェアトランスコードの有効化と確認方法
- 外出先から見る方法の選び方と、字幕の文字化け・権限エラーの直し方
Jellyfinとは:Plex・Embyとの違い
Jellyfinは、2018年にEmbyのソースコード公開が止まったことをきっかけに、その公開部分から分かれて始まったプロジェクトで、サーバーはGPLv2で公開されています。アカウント登録も有料プランもなく、ハードウェアトランスコードを含むすべての機能を無料で使えるのが最大の特徴です。
| 項目 | Jellyfin | Plex | Emby |
|---|---|---|---|
| ソースコード | 公開(GPLv2) | 非公開 | 非公開 |
| 利用に必要なアカウント | サーバー内のローカルユーザーだけ | Plexのアカウントでサインイン | サーバー内のユーザー(一部機能は有料登録) |
| ハードウェアトランスコード | 無料 | 有料プランが必要 | 有料プランが必要 |
| 外部の認証基盤への依存 | なし | Plexのサービスに依存 | 任意(Emby Connect) |
| 対応端末の幅 | 主要な端末に公式・非公式アプリ | 最も広い | 広い |
Plexは、テレビや古い端末まで含めたアプリの完成度では一歩先を行きますが、執筆時点では外出先での再生などにも有料プランが必要で、サインインにPlexのサービスを使います。技術に詳しくない家族が多種類のテレビで見るならPlex、インターネット上のサービスに依存せず無料ですべての機能を使いたいならJellyfin、という分け方がわかりやすい基準です。再生側は、ブラウザのほか、Android、Android TV、iOS向けの公式アプリと、Kodi用のアドオンなどが使えます。
ハードウェアの選び方:トランスコードするかどうかで決まる
再生の方式は3段階あります。端末がファイルの形式にそのまま対応していれば、サーバーはファイルを送るだけの「ダイレクト再生」になり、CPUはほとんど使いません。映像はそのままで入れ物(コンテナ形式)や音声だけを変える「ダイレクトストリーム」は、軽い処理で済みます。映像の形式や解像度、ビットレートを変える「トランスコード」だけが重い処理で、CPUだけで行うと4K HDRのHEVCを1本変換するのにも高性能なCPUが必要です。
| 使い方 | 必要な性能の目安 | 向く機器 |
|---|---|---|
| 家の中で、端末が対応する形式だけ再生 | ダイレクト再生が中心で、性能はほぼ不要 | Raspberry Pi、ARMのNAS、古いPC |
| 外出先のモバイル回線で、画質を落として見る | トランスコードが必須 | Intel内蔵GPU(Quick Sync)のミニPC |
| 4K HDRを、HDR非対応の端末で見る | トランスコードとトーンマッピング(HDRをSDRの色に直す処理) | 第12世代以降のIntel内蔵GPU、または専用GPU |
迷ったら、Intelの内蔵GPUを持つミニPCを選ぶのが無難です。Quick Sync(Intel内蔵GPUの動画処理回路)は、少ない電力で複数本のトランスコードをこなします。どの世代がどの形式(HEVC 10bit、AV1など)のデコードとエンコードに対応するかは世代ごとに違うので、購入前にJellyfinの公式ドキュメントにあるハードウェアアクセラレーションの対応表で確認してください。Raspberry Pi 5はH.264のハードウェアエンコーダーを持たないため、ダイレクト再生専用と考えます。
メディアファイル本体は、サーバーのディスクでもNASでも構いません。NASに置く場合は、NFSやSMBでホストにマウントし、そのディレクトリを読み取り専用でコンテナに渡します。コンテナの中からネットワーク共有をマウントするより、切り分けがしやすくなります。NASの選び方はNASの選び方の記事にまとめています。
Docker Composeで起動する
メディアを /srv/media に置き、サーバーのLAN側アドレスを 192.168.10.30 とした例です。コンテナを一般ユーザー(UID 1000)で動かすため、設定とキャッシュのディレクトリを先に作っておきます。
sudo mkdir -p /srv/jellyfin/config /srv/jellyfin/cache
sudo chown -R 1000:1000 /srv/jellyfin
getent group render
# render:x:993: ← 3番目の数字がGID(例。環境ごとに違う)services:
jellyfin:
image: jellyfin/jellyfin:12.1
user: "1000:1000"
group_add:
- "993" # renderグループのGID(getent group renderの値に合わせる)
ports:
- "8096:8096/tcp" # Web画面とアプリの接続
- "7359:7359/udp" # LAN内のアプリからの自動検出
volumes:
- /srv/jellyfin/config:/config
- /srv/jellyfin/cache:/cache
- /srv/media:/media:ro
devices:
- /dev/dri:/dev/dri # Intel/AMDの内蔵GPU(ハードウェアトランスコード用)
environment:
JELLYFIN_PublishedServerUrl: http://192.168.10.30:8096
restart: unless-stoppedcd ~/stacks/jellyfin
docker compose up -d
curl -s http://127.0.0.1:8096/health公式イメージは、設定を /config、キャッシュとトランスコード中の一時ファイルを /cache(中の transcodes)に保存し、同梱のffmpeg(/usr/lib/jellyfin-ffmpeg/ffmpeg、執筆時点で8.1.2-Jellyfin)を使います。/health は準備ができると Healthy を返します。JELLYFIN_PublishedServerUrl は、LAN内のアプリが自動検出したときに案内されるアドレスで、指定しないとコンテナ内部のアドレス(172.17.0.x など)が案内されてしまいます。検証では、この変数を設定すると公開情報の LocalAddress が指定したURLに変わりました。
/media は読み取り専用(:ro)でマウントしています。メタデータや画像をメディアのフォルダに保存する設定を後から有効にすると書き込みに失敗しますが、既定ではJellyfinは取得した情報を /config 側に保存するので問題ありません。万一の誤操作や不具合で、大切な動画ファイルが書き換わる経路を最初から断っておく方が安全です。
フォルダ構成と命名規則:作品を正しく認識させる
Jellyfinはファイル名とフォルダ名から作品を推測し、TMDbなどのデータベースで情報を探します。名前の付け方が崩れていると、別の作品のポスターが付いたり、シーズンがまとまらなかったりします。映画は「作品名 (公開年)」のフォルダに同じ名前のファイルを、ドラマやアニメは「作品名 (年)/Season 01/」の下に S01E01 の形式で置くのが基本です。
movies/
Test Pattern (2024)/
Test Pattern (2024).mkv
作品名 (2019)/
作品名 (2019).mkv
作品名 (2019).ja.srt
shows/
シリーズ名 (2021)/
Season 01/
シリーズ名 (2021) S01E01.mkv
シリーズ名 (2021) S01E02.mkv
music/
アーティスト名/
アルバム名/
01 - 曲名.flac検証では、movies/Test Pattern (2024)/Test Pattern (2024).mkv を置いて映画ライブラリを作ると、作品名 Test Pattern (2024)、公開年 2024 として登録されました。日本語のファイル名もそのまま使えます。同名の作品が複数ある場合は、フォルダ名に [tmdbid-12345] のようにデータベースのIDを添えると、確実にその作品として認識させられます。字幕ファイルは動画と同じ名前に .ja.srt のような言語コードを付けておくと、字幕の言語が正しく表示されます。
ライブラリは種類ごとに分けて作ります。家族のビデオを映画のライブラリに混ぜると、存在しない映画の情報を探しに行ってしまうので、「ホームビデオと写真」(Home Videos and Photos)の種類で別に作ってください。
初期設定ウィザード
http://192.168.10.30:8096 を開くと初期設定ウィザードが始まります。表示言語を日本語にし、管理者ユーザーを作り、ライブラリを追加し、メタデータの言語と国を「日本語」「日本」にします。ウィザードの既定は英語・米国(en・US)なので、ここを変えないと作品の説明文やポスターが英語版になります。
管理者のユーザー名の入力欄には、コンテナをrootのまま動かしている場合 root が最初から入っています(実行しているOSのユーザー名が使われるため)。そのまま使わず、家族が推測しにくい名前に変えてください。ウィザードの最後にある「リモート接続を許可」は、LANの外から来た接続を受け付けるかどうかの設定で、既定で有効です。外出先からは後述するVPN経由で見る前提なら、有効のままでもインターネットに直接さらされることはありません。
テレビのアプリでのログインは、サーバー側でクイックコネクトが有効になっていれば、それを使うと楽です。テレビ側に表示されたコードを、ログイン済みのスマホやPCの画面で入力すれば、テレビのリモコンでパスワードを打たずに済みます。
ハードウェアトランスコードを有効にする(Intel Quick Sync / VA-API)
まず、ホストに /dev/dri/renderD128 があり、コンテナからGPUが見えることを確かめます。公式イメージには、GPUの対応形式を表示する vainfo が同梱されています。
ls -l /dev/dri
docker compose exec jellyfin /usr/lib/jellyfin-ffmpeg/vainfo --display drm --device /dev/dri/renderD128vainfo の出力に VAProfileH264Main、VAProfileHEVCMain10 のようなプロファイルと、VAEntrypointVLD(デコード)、VAEntrypointEncSlice または VAEntrypointEncSliceLP(エンコード)が並べば、コンテナからGPUを使えます。何も表示されずにエラーになる場合は、次の章のつまずきポイントを確認してください。
続いて、管理画面の再生(Playback)にあるトランスコードの設定で、ハードウェアアクセラレーションを選びます。執筆時点の設定ファイル encoding.xml の初期値と、変える項目は次のとおりです。
| 設定(encoding.xmlの項目名) | 初期値 | 変える内容 |
|---|---|---|
ハードウェアアクセラレーション(HardwareAccelerationType) | none | Intelなら「Intel QuickSync(QSV)」または「VA-API」 |
デバイス(VaapiDevice) | /dev/dri/renderD128 | GPUが複数あるときだけ変える |
ハードウェアデコードの対象形式(HardwareDecodingCodecs) | 2つの形式だけ選択済み | vainfo に出た形式にだけチェックを入れる |
ハードウェアエンコード(EnableHardwareEncoding) | 有効 | そのまま |
HEVCでのエンコード(AllowHevcEncoding) | 無効 | 端末がHEVCに対応しているなら有効に |
トーンマッピング(EnableTonemapping) | 無効 | HDRの作品をSDRの端末で見るなら有効に |
低電力エンコーダー(EnableIntelLowPowerH264HwEncoder) | 無効 | GPUの世代とドライバが対応している場合だけ有効に |
ハードウェアデコードの対象には、vainfo で確認できた形式だけを選びます。GPUが対応していない形式にチェックを入れると、その形式の再生時に変換が失敗します。低電力エンコーダーは、Intelの比較的新しい世代で使える省電力の回路ですが、世代とカーネルのファームウェア設定によっては初期化に失敗するため、まずは無効のまま動作を確認し、あとから試すのが安全です。
設定が効いているかは、再生中の画面で確かめます。スマホのアプリで画質を「720p・2Mbps」のように低く指定して再生し、管理画面のダッシュボードのアクティブなセッションに「トランスコード」と表示され、ホストで sudo intel_gpu_top(パッケージ intel-gpu-tools)を実行してVideoの使用率が上がれば、GPUで変換しています。
家の外から見る方法
外出先から見る方法は3つ考えられますが、おすすめはTailscaleでのリモート接続です。スマホとサーバーの両方にTailscaleを入れれば、http://100.x.y.z:8096 のようなアドレスでJellyfinのアプリから接続でき、ルーターのポート開放もいりません。
| 方法 | 手間 | 注意点 |
|---|---|---|
| Tailscaleなどのメッシュ型VPN | 見る端末ごとにアプリを入れる | 家族の端末には入れやすいが、実家のテレビには入れにくい |
| リバースプロキシ+ポート開放(HTTPS) | ドメインと証明書、ルーターの設定 | ログイン画面がインターネットに出る。強いパスワードとロックアウトの設定が前提 |
| Cloudflare Tunnel | ドメインとCloudflareの設定 | 動画の大量配信はCDNの規約上の制限にかかりうる(執筆時点) |
リバースプロキシで公開する場合は、Jellyfinのネットワーク設定の「既知のプロキシ」(KnownProxies)にプロキシのアドレスを登録します。登録しないと、Jellyfinはすべてのアクセスをプロキシのアドレスから来たものとして扱い、ログのIPも、LAN内かどうかの判定も正しくなりません。また、ユーザーごとの設定にはログインに何回失敗したらアカウントをロックするかの項目があるので、外から使うユーザーは値を確認しておきます。Cloudflare Tunnelの規約の考え方はCloudflare Tunnelのガイドを参照してください。
執筆時点のJellyfinには、多要素認証の標準機能がありません。ログイン画面をインターネットに直接出すと、守りはパスワードだけになります。家族だけで見るなら、VPNの内側に置く構成を基本にしてください。
つまずきポイント
ハードウェアトランスコードにすると再生が始まらない
再生画面に This client isn't compatible with the media and the server isn't sending a compatible media format. のようなエラーが出る場合は、変換の段階で失敗しています。/config/log/ にある FFmpeg.Transcode- で始まるログを開き、Failed to initialise VAAPI connection や No VA display found for device /dev/dri/renderD128 があれば、コンテナからGPUを開けていません。compose.yamlの devices と、group_add のGIDがホストの getent group render と一致しているかを確認します。GIDがずれていると、デバイスは見えていても開く権限がありません。
ライブラリに作品が表示されない
ログに Access to the path '/media/...' is denied. があれば、UID 1000からメディアのフォルダを読めません。sudo -u '#1000' ls /srv/media/movies で読めるかを確かめ、読めなければ sudo chmod -R o+rX /srv/media のように読み取り権限を付けます。NASをマウントしている場合は、マウントオプションのUIDや共有側の権限も確認します。
字幕の日本語が四角(□)で表示される
ASS形式などの字幕を映像に焼き込むトランスコードでは、サーバー側のフォントで文字を描きます。日本語のフォントがないと文字が四角になります。再生の設定でフォールバックフォントを有効にし(EnableFallbackFont、初期値は無効)、Noto Sans CJK JPなどの日本語フォントを置いたフォルダを指定します。フォントのフォルダはコンテナ内から見える場所(例:/config/fonts)に置きます。
初回のスキャンが終わらない、CPUが張り付く
作品数が多いと、画像の取得やチャプター画像の抽出に時間がかかります。ライブラリの設定でトリックプレイ画像(シークバーのサムネイル)の抽出を有効にしていると、動画ごとに映像を読み込むのでCPUを長時間使います。性能の低い機器では、この抽出を無効にするか、スケジュールされたタスクの実行時間を夜間に寄せます。
動作確認
curl -s http://127.0.0.1:8096/health
curl -s http://127.0.0.1:8096/System/Info/Public
docker compose logs jellyfin | tail -20/health が Healthy を返し、/System/Info/Public のJSONに "ProductName":"Jellyfin Server"、"Version":"12.1.0"(執筆時点の版)、"StartupWizardCompleted":true が含まれていれば、サーバーは起動して初期設定も済んでいます。LocalAddress が JELLYFIN_PublishedServerUrl に書いたアドレスになっていることも確認します。最後に、スマホのアプリからサーバーが自動検出されること、動画を1本再生して再生情報に「ダイレクト再生」または「トランスコード」と意図どおりに表示されることを確かめます。
よくある質問
ジェリーフィンとは何ですか?
読み方は「ジェリーフィン」で、自宅のサーバーに置いた動画や音楽を、テレビやスマホで再生できるようにする無料のメディアサーバーです。オープンソースで、アカウント登録や有料プランがなく、ハードウェアトランスコードも無料で使えます。自宅のサーバーで動き、視聴履歴などのデータも外部のサービスに預けません。
Jellyfinのポートはいくつですか?
Web画面とアプリの接続はHTTPの8096番、HTTPSを有効にした場合は8920番です。LAN内のアプリがサーバーを自動検出するのにUDPの7359番を使います。DLNAで家電から再生する場合は、DLNAのプラグインを入れたうえでUDPの1900番も使います。外部に公開する場合は、これらを直接開けずにVPNかリバースプロキシを使います。
UbuntuでのJellyfinとは何ですか?
Ubuntuに入れたJellyfinも中身は同じメディアサーバーで、動かし方が2通りあります。公式のAPTリポジトリからパッケージを入れてsystemdのサービスとして動かす方法と、この記事のようにDockerで動かす方法です。更新や別のサーバーへの引っ越しが楽なのはDockerの方で、設定とキャッシュのディレクトリを移すだけで済みます。
Jellyfinの使い方は?
サーバーに動画を「作品名 (年)」のフォルダ構成で置き、管理画面でそのフォルダをライブラリとして登録します。あとはブラウザや、テレビ・スマホのJellyfinアプリからサーバーに接続すれば、ポスター付きの一覧から再生できます。家族ごとにユーザーを分けると、視聴履歴や続きからの再生が人ごとに管理されます。
まとめ
Jellyfinは、フォルダの命名規則を守ってライブラリを作り、メタデータの言語を日本語にすれば、ほぼ手間なく家族のメディアセンターになります。機器選びの分かれ目はトランスコードの有無で、家の中のダイレクト再生だけなら低性能な機器でも足り、外出先で画質を落として見るならIntel内蔵GPUのミニPCが扱いやすい選択です。外からの視聴はVPN経由を基本にし、ログイン画面をインターネットに出さない構成で運用してください。