メインコンテンツへスキップ
50% off 全プラン対象、期間限定。月額 $2.48/mo
11 min left
ゲームとメディア

VPS で yt-dlp をヘッドレス運用し、個人アーカイブを作る

S 著者 Sajjad 11 分で読めます
yt-dlp running headless on a VPS, feeding scheduled downloads into an organized video library that a media server can scan

yt-dlp を VPS で動かすと、ノート PC を閉じたあとも オンラインのままの、長時間ダウンロード向けのマシンが手に入ります。さらに、スケジュール実行によるチャンネル取得から、Jellyfin が読み取れるメディアライブラリまでの道筋もすっきりします。

サーバー化によってワークフローの 3 つの部分が変わります。インストールには現行の YouTube 向け依存関係が必要で、アカウントが要る動画には安全な Cookie の受け渡しが必要で、自動化にはリクエスト間隔の意図的な調整が必要です。以下の構成はこの 3 つすべてに対応しますが、すべてのダウンロードに Cookie や Web インターフェース、PO Token プロバイダーが要るとは前提していません。

要約

  • yt-dlp は Python の仮想環境に、ffmpeg、ffprobe、yt-dlp-ejs、サポート対象の JavaScript ランタイムとあわせて導入します。プロジェクトが現在推奨しているランタイムは Deno です。
  • まずはアカウントの Cookie なしで始めてください。追加するのは、非公開の再生リスト、年齢制限つき動画、メンバー限定コンテンツなど、アカウントが必要な場合だけです。
  • 計測に基づく理由が出てくるまでは、yt-dlp の既定であるフラグメント 1 本の挙動のままにしておきましょう。リクエストの負荷を抑えるには、待機系のオプションと時間をずらしたスケジュールを使います。
  • 素の CLI と systemd の組み合わせが、最も単純で頼れる構成です。手をかけずにチャンネル単位のルールを回すなら Pinchflat、ブラウザー上のキューなら MeTube、検索できる視聴画面なら Tube Archivist を選んでください。
  • サイジングの主役はストレージだと考えてください。アーカイブ全体分のディスク容量を購入する前に、代表的なサンプルで試しましょう。

yt-dlp は責任を持って使う

メディアをアーカイブしてよいのは、許諾があり、かつ利用がプラットフォームの規約と適用法令に沿っている場合だけです。

  • 適した対象は、自分でアップロードした動画、パブリックドメインの作品、権利者がダウンロードを許可している素材などです。
  • YouTube Premium に加入していること自体は、YouTube が用意した機能の外で動画を複製する許諾にはなりません。
  • YouTube の許諾と制限に関する規定 は、サービス側または該当する権利者が許可しないかぎり、ダウンロードと自動化されたアクセスを制限しています。
  • このチュートリアルでは、DRM の回避、商業的な再配布、プラットフォームの取り締まりを逃れる方法は扱いません。

始める前に必要なもの

基本のインストールは小さくても、メディアファイルはそうではありません。チャンネル全体をダウンロードする前に、サーバーと保存先のパスを用意しておきましょう。

  • SSH でアクセスできる、Ubuntu 22.04 以降または現行の Debian リリースの VPS
  • Python 3.10 以降
  • 代表的なサンプルを置ける容量に加え、途中ファイルと後処理のための余裕
  • アカウントの Cookie が必要な場合にかぎり、別途用意するローカルのブラウザー
  • 任意: Jellyfin、Emby、またはアーカイブのディレクトリを読み取れる別のメディアサーバー

なぜ yt-dlp を VPS に置くのか

普段使いのパソコンとは切り離してジョブを走らせ続けたいときに、VPS が役立ちます。ダウンローダーに常駐プロセスと予測しやすいファイルシステム、そしてノート PC がスリープしてもネットワークが変わっても止まらないスケジューラーを与えてくれます。

トレードオフは重要です。アーカイブを外へ配信し直すときには、サーバーの月間転送量が上限になり得ますし、VPS の IP は自宅回線より早くリクエスト制限に当たることがあります。アップデート、認証情報の扱い、バックアップ、ストレージの整理、メディアサーバーのセキュリティも自分の担当になります。一度きりのダウンロードならノート PC のほうが簡単です。定期的な取得や共有のメディアライブラリなら、VPS のほうが運用しやすくなります。

ストレージと再生を軸に VPS を見積もる

yt-dlp VPS sizing guide: starting allocations of 2 vCPU and 2 GB RAM for raw yt-dlp with systemd, 2 vCPU and 4 GB RAM for MeTube or Pinchflat, and 4 vCPU and 8 GB RAM for Tube Archivist, beside a method for projecting storage from a sample download

yt-dlp はメディアをダウンロードして再多重化するもので、通常はすべてのファイルをトランスコードしません。そのためダウンローダー自体が常時必要とする CPU とメモリは控えめで、一方でディスク使用量は動画の長さ・解像度・コーデック・選んだフォーマットによって変わります。

以下の割り当ては公式な最小要件ではなく、控えめな出発点として使ってください:

セットアップ初期割り当てストレージの考え方最適
素の yt-dlp と systemd2 vCPU, 2 GB RAMサンプルから見積もるUI なしのスケジュール実行
MeTube または Pinchflat2 vCPU, 4 GB RAMサンプルから見積もるブラウザーのキューまたはチャンネル購読
Tube Archivist4 vCPU, 8 GB RAM増加分の余裕を持たせたローカルディスク検索できるアーカイブと内蔵の再生機能

小規模なテストにはおよそ 2 GB、中〜大規模の構成にはおよそ 4 GB の空きメモリが必要です。出典は Tube Archivist のデプロイガイドです。この下限より上から始めておくと、OS、Docker、Elasticsearch の動作、さらに Jellyfin のような別サービスの分の余裕が残ります。

アーカイブ全体を見積もる前に、選んだ解像度で代表的なひとまとまりをシミュレートするかダウンロードしてみてください。できたディレクトリを du で確認し、完了した動画の本数で割り、極端に長い動画の分も見込んでおきます。

du -sh ~/archive
find ~/archive -type f \( -name '*.mp4' -o -name '*.mkv' \) | wc -l
df -h ~/archive

サンプルのほうが、動画 1 本あたり何ギガバイトといった一般的な見積もりより役立ちます。そのチャンネルの実際の長さとフォーマットの構成が反映されるからです。

yt-dlp と現行の依存関係を導入する

yt-dlp プロジェクトは Python 3.10 以降に対応しています。 yt-dlp の依存関係一覧 では、YouTube に完全対応するために ffmpeg、ffprobe、yt-dlp-ejs、サポート対象の JavaScript ランタイムが強く推奨されています。

まずはシステムのパッケージと、隔離された Python 環境から始めます:

sudo apt update
sudo apt install -y python3 python3-venv ffmpeg curl nano
python3 -m venv ~/yt-dlp-venv
source ~/yt-dlp-venv/bin/activate
python -m pip install -U --pre "yt-dlp[default]"

Deno は yt-dlp で既定で有効になっており、プロジェクトの EJS ガイド EJS ガイドが現在推奨しているランタイムです。インストールしてシェルの PATH に追加し、各コンポーネントを確認します:

curl -fsSL https://deno.land/install.sh | sh
export PATH="$HOME/.deno/bin:$PATH"
echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.profile
yt-dlp --version
ffmpeg -version | head -1
deno --version
yt-dlp --simulate --verbose "https://www.youtube.com/watch?v=VIDEO_ID"

詳細出力には、yt-dlp が認識できている依存関係が並びます。ffmpeg がない場合、yt-dlp は警告を出し、別々に取得した最高品質の映像と音声を結合したり、いくつかの後処理を実行したりできません。

pip でインストールした場合は、仮想環境の中で pip をもう一度実行して更新します。組み込みの yt-dlp -U コマンドはリリース版バイナリ向けで、pip パッケージ向けではありません。

source ~/yt-dlp-venv/bin/activate
python -m pip install -U --pre "yt-dlp[default]"

アップデートチャンネルについては yt-dlp の更新に関する説明をご覧ください。stable、nightly、master のいずれも利用でき、一般的な利用者にプロジェクトが勧めているのは nightly です。抽出器の修正が次の安定版より先に届くためです。

Cookie はアカウントが必要なコンテンツにだけ追加する

まずは対象の URL を Cookie なしで試してください。yt-dlp の YouTube ガイドによれば、Cookie が必要なのはアカウントを要するコンテンツ、つまり非公開の再生リスト、年齢制限つき動画、メンバー限定コンテンツだけです。OAuth によるログインは、yt-dlp ではすでに利用できません。

Cookie がどうしても必要な場合は、手元のパソコンで専用の YouTube セッションをエクスポートします。プロジェクトの Cookie エクスポート手順 では、プライベートウィンドウを使います。開いたままの通常タブで YouTube がエクスポート済みのセッションを入れ替えてしまわないようにするためです:

  1. プライベートウィンドウ(シークレットウィンドウ)を 1 つだけ開き、YouTube にログインします。
  2. 同じタブで、YouTube の robots.txt ファイルを開きます。
  3. yt-dlp の FAQ に挙げられている拡張機能のいずれかを使い、youtube.com の Cookie だけを Netscape 形式でエクスポートします。
  4. プライベートウィンドウを閉じ、そのセッションは二度と開かないでください。
  5. そのファイルを VPS にコピーし、パーミッションを絞ります。
scp cookies.txt your-user@your-vps-ip:~/cookies.txt
ssh your-user@your-vps-ip 'chmod 600 ~/cookies.txt'

アカウントが必要な URL でファイルをテストします:

~/yt-dlp-venv/bin/yt-dlp \
  --cookies ~/cookies.txt \
  --simulate \
  "https://www.youtube.com/watch?v=VIDEO_ID"

Cookie ファイルはセッションの認証情報であり、ブラウザー拡張は慎重に選ぶ必要があります。出典は yt-dlp の Cookie に関する FAQ です。YouTube 抽出器のガイドは、yt-dlp でアカウントを使うと一時的または恒久的な利用停止につながり得るとも警告しています。Cookie は対象が要求するときだけ使い、ファイルは非公開に保ち、メインの Google アカウントではなく別アカウントを使ってください。

対象の大半が公開コンテンツなら、--cookies をグローバル設定に入れないでください。設定ファイルをもう 1 つ用意するか、必要なジョブにだけこのオプションを付けます。

PO Token は条件付きのトラブルシューティングと考える

yt-dlp access troubleshooting flow: simulate the URL first, then branch to no cookies needed for a working public video, a cookie export for account-gated content, or a dependency update and PO Token check when failures continue

Proof of Origin Token は、インストール時に必ず要るものではありません。YouTube は現在、クライアントとリクエストの一部の組み合わせについてこのトークンを要求しており、その対応表も変化し続けています。

既定のクライアントで失敗する場合は、mweb クライアント向けのプロバイダープラグインが推奨されます。出典は yt-dlp の PO Token ガイドです。そこでは bgutil-ytdlp-pot-provider が主な選択肢の 1 つとして挙げられていますが、このプラグインにはトークンプロバイダーと yt-dlp 用プラグインの両方が必要です。Python パッケージを入れただけでは設定は完了しません。

YouTube のダウンロードが失敗したときは、この順序で進めます:

  1. yt-dlp、yt-dlp-ejs、JavaScript ランタイムを更新します。
  2. --verbose を付け、余計なクライアント指定はせずに失敗を再現します。
  3. その動画にアカウントが必要な場合にかぎり、Cookie を追加します。
  4. エラーが PO Token の強制を示している場合は、公式ガイドからリンクされている最新のプロバイダー手順に従ってください。

こうしておけば、変わりやすい回避策を、それ以外は安定している基本構成の外に置いておけます。

ワークフローでフロントエンドを選ぶ

重要なのは、どのインターフェースの機能一覧が長いかではありません。ブラウザーのキューが要るのか、ルールに基づく購読が要るのか、それとも YouTube のようなローカルの完全なライブラリが要るのかを決めてください。

オプションデプロイメント得意なこと主なトレードオフ
素の CLIフロントエンドなしスクリプト、設定ファイル、systemd、オプションの厳密な制御ブラウザー UI なし
MeTubeDocker コンテナー 1 つブラウザーからのダウンロードに加え、チャンネルと再生リストの購読ダウンロード後のライブラリ管理は限定的
PinchflatDocker コンテナー 1 つチャンネルと再生リストのルール、RSS、保存期間、メディアセンター向けの出力アプリ内での視聴ではなく、ダウンロード管理のために作られている
Tube Archivistアプリ、Redis、Elasticsearch のコンテナー検索、メタデータ、キュー、チャンネルページ、再生メモリ消費と運用の手間が最も大きい

ブラウザーで軽く回したい場合、MeTube はチャンネルや再生リストの購読に対応しており、新着を定期的に確認して自動でキューに入れます。Web のフォームとダウンロードキューがあれば十分というときは、これが最も簡単な選択肢です。

Jellyfin、Plex、Kodi、あるいは RSS クライアントで見る前提でチャンネルを継続的にアーカイブするなら、Pinchflat が最も適しています。単体で完結し、ソースを定期的に確認し、保存期間のルールにも対応し、再生はあえて別のアプリケーションに任せています。

アーカイブそのものを検索できる動画サイトのように振る舞わせたいなら、Tube Archivist は追加のサービス群に見合う価値があります。再生画面をすでに Jellyfin が担っているなら、まず素の CLI か Pinchflat から始め、その検索とメタデータの仕組みが実際の困りごとを解決してくれるとわかった時点で Tube Archivist を足してください。

繰り返し使えるアーカイブ設定を作る

長く変えない設定は 1 つのファイルにまとめ、チャンネルの URL はコマンドラインかスケジューラーから渡します。この例では出力を 1080p までに制限し、完了した動画の ID を記録し、リクエストの間隔を少し空け、yt-dlp の外でも役立つメタデータを書き出します。

ディレクトリと設定ファイルを作成します:

mkdir -p ~/.config/yt-dlp ~/archive
nano ~/.config/yt-dlp/archive.conf

次のオプションを追加します:

-P "~/archive"
-o "%(channel)s/%(upload_date>%Y-%m-%d)s - %(title)s [%(id)s].%(ext)s"
-f "bv*[height<=1080]+ba/b[height<=1080]"
--merge-output-format mp4
--download-archive ~/archive/downloaded.txt
--sleep-requests 1
--sleep-interval 5
--max-sleep-interval 10
--write-info-json
--write-thumbnail
--write-subs
--write-auto-subs
--sub-langs en.*
--embed-subs
--embed-thumbnail
--embed-metadata
--sponsorblock-mark all

チャンネル全体を yt-dlp に渡す前に、動画 1 本でテストします:

~/yt-dlp-venv/bin/yt-dlp \
  --config-location ~/.config/yt-dlp/archive.conf \
  "https://www.youtube.com/watch?v=VIDEO_ID"

続いて、同じ設定でチャンネルまたは再生リストの URL を実行します:

~/yt-dlp-venv/bin/yt-dlp \
  --config-location ~/.config/yt-dlp/archive.conf \
  "https://www.youtube.com/@CHANNEL/videos"

--download-archive のファイルにはダウンロードに成功した ID が記録されるため、次回以降の実行ではそれらがスキップされます。最初のうちは既定の --concurrent-fragments 1 のままにしてください。yt-dlp の YouTube ガイドは、セッションがリクエスト制限に達したときは動画の間に間隔を置くよう勧めていますが、VPS の IP に共通して安全といえるフラグメント並列数の上限は示していません。

systemd でダウンロードをスケジュールする

ユーザー単位の systemd タイマーを使うと、cron に長いコマンドを書かずに、ジョブへ永続的なスケジュールとログを与えられます。ランダムな遅延によって、スケジュールしたすべてのソースが同じ秒に走り出すのも防げます。ユーザーマネージャーの PATH に依存しないよう、このサービスでは yt-dlp から Deno の既定のインストール先を直接指定しています。

サービスを作成します:

mkdir -p ~/.config/systemd/user
nano ~/.config/systemd/user/yt-dlp-archive.service
[Unit]
Description=Archive a YouTube channel with yt-dlp

[Service]
Type=oneshot
ExecStart=%h/yt-dlp-venv/bin/yt-dlp --js-runtimes deno:%h/.deno/bin/deno --config-location %h/.config/yt-dlp/archive.conf https://www.youtube.com/@CHANNEL/videos

タイマーを作成します:

nano ~/.config/systemd/user/yt-dlp-archive.timer
[Unit]
Description=Run the yt-dlp archive daily

[Timer]
OnCalendar=*-*-* 04:00:00
RandomizedDelaySec=30m
Persistent=true

[Install]
WantedBy=timers.target

タイマーを有効化し、ログインしていないときでもユーザーサービスが動くようにします:

systemctl --user daemon-reload
systemctl --user enable --now yt-dlp-archive.timer
sudo loginctl enable-linger "$USER"
systemctl --user list-timers
journalctl --user -u yt-dlp-archive.service -n 100 --no-pager

チャンネルが複数ある場合は、チャンネルごとにサービスのインスタンスを作るか、タイマーを分けてください。大きな取得を同時に走らせるのではなく、時間をずらしましょう。

アーカイブを Jellyfin につなぐ

同じ ~/archive ディレクトリを Jellyfin にマウントするか参照できるようにし、ライブラリとして追加します。チャンネル/日付そのままの構成には、Jellyfin の Music Videos ライブラリ ライブラリなら、入れ子のフォルダーや任意のファイル名を、オンラインでのメタデータ照合なしに受け入れられます。音楽以外のアーカイブにはラベルとしてしっくりきませんが、シリーズとシーズンのフォルダーに SxxEyy 形式のエピソード名を求める「Shows」タイプより、ファイル構成の相性は上です。メタデータの結果が当てにならない場合があるという Jellyfin の警告を受け入れるのでなければ、Mixed Content は避けてください。

yt-dlp の設定にあるメタデータ・サムネイル・字幕のオプションは、役立つ情報を各ファイルのそばや内部に残します。それでも Jellyfin 側では手作業でのメタデータ調整が必要になることがあります。YouTube のチャンネルは、テレビシリーズのデータベースにきれいには当てはまらないからです。

手作業を減らしつつ Jellyfin 向けのファイル名とメタデータがほしい場合は、Pinchflat にこのワークフロー用のメディアセンター向けプリセットがあります。メディアサーバー同士のより大きな選択については、当社の Jellyfin と Plex の比較記事 が、再生・リモートアクセス・トランスコードのトレードオフを扱っています。

この構成を常時稼働のサーバーに置く

小さなテストセットでワークフローがうまくいったら、それを移します。移行先は CloudzyのLinux VPS です。こうすれば、スケジュール実行のダウンロードとメディアライブラリを、普段使いのパソコンを占有せずにオンラインのまま保てます。さらに、次のものも導入できます: ワンクリックアプリ版の Jellyfin そのライブラリを yt-dlp の出力ディレクトリに向けます。

Linuxプランを見る

root権限、NVMe、AMD EPYCのパワーを備えたLinux VPSで開発を。

Linuxプランを見る

よくある質問

VPS 上の yt-dlp に GPU は必要か

いいえ。yt-dlp は GPU がなくてもメディアのダウンロードと再多重化ができます。GPU が関係してくるのは、Jellyfin などのメディアサーバーが、非対応のクライアントや帯域の細い回線のために動画をトランスコードしなければならない場面です。ダイレクト再生であれば、その変換は必要ありません。

yt-dlp は中断したダウンロードを再開できるか

はい。yt-dlp は既定で部分ファイルと再開を有効にしているため、あとから実行すれば通常はダウンロード済みのフラグメントから再開し、最初からやり直しません。この挙動を保ちたいなら、--no-continue、--no-part、--force-overwrites は付けないでください。

yt-dlp と Jellyfin は 1 台の VPS に同居させてよいか

ストレージ、CPU、外向きの転送量が両方の仕事に足りているなら、1 台の VPS を共有できます。分けたほうがよいのは、再生やトランスコードが大きなダウンロードと資源を奪い合う場合、メンテナンス時間帯を別々にしたい場合、あるいはアーカイブをストリーミングサーバーより安価なストレージに置きたい場合です。

共有

ブログの他の記事

読み進める。

デプロイの準備はできましたか? 月額2.48ドルから。

2008年から独立運営のクラウド。AMD EPYC、NVMe、40 Gbps。14日間返金保証。