MeTubeは、yt-dlpをブラウザから操作できるようにするセルフホスト型のWeb UIだ。CLIを触らない家族やチームメンバーとダウンロード環境を共有したいときの最短手段で、GitHubで★14,437を集めている。にもかかわらず日本語の解説はほぼ存在せず、検索しても英語のセルフホスト系ブログとDocker Hubが並ぶだけだ。本記事では起動手順・yt-dlpオプションの3層合成・そして信頼境界を、READMEとソースの両方を確認して整理する。
この記事はyt-dlpのセルフホストWeb UI「MeTube」を解説します。自動化ツール全体の地図はAI自動化ツール|ノーコードからコードまで2026年版の比較と選び方をご覧ください。
30秒でわかる MeTube
・yt-dlpをDockerコンテナ1つでWeb UI化する。CLIを知らない人にも渡せる
・yt-dlpオプションはグローバル → プリセット → 個別上書きの3層で合成され、具体的な層が勝つ
・認証機構は無い。既定はHOST=0.0.0.0 PORT=8081なので、外に出すなら手前で必ず絞る
・ALLOW_YTDL_OPTIONS_OVERRIDESの既定はfalse。公式がコンテナ内での任意コード実行になりうると明記している
・ライセンスはAGPL-3.0。改造して提供する場合は条項の確認が要る
MeTubeとは:yt-dlpの「共有しづらさ」を埋める層
yt-dlpは強力だが、CLIである以上「使える人」が限られる。SSHもターミナルも使わない相手に渡すには、何らかのUIを被せるしかない。MeTubeはそこを埋める。公式の表現は「YouTubeと他の数十のサイトからメディアをダウンロードするための、yt-dlpのセルフホスト型Web UI」だ。
似た立ち位置のツールと比べると、性格の違いがはっきりする。
| 観点 | MeTube |
|---|---|
| 形態 | Dockerコンテナ1つのWebアプリ |
| 中身 | yt-dlp(同梱)+ Angular製UI + Python製バックエンド |
| 既定の待受 | HOST=0.0.0.0 / PORT=8081 |
| 認証 | 無し(手前のリバースプロキシ等で担保する) |
| ライセンス | AGPL-3.0 |
| GitHub ★ | 14,437(2026-08-19時点) |
| 最新リリース | 2026.08.18 |
「yt-dlpのラッパー」と一言でまとめると取り違えやすいのは、MeTubeが独自のダウンロード実装を持たない点だ。実行しているのはyt-dlpのPython APIであり、MeTubeが提供しているのはキュー・進捗・保存先・オプション管理というオーケストレーション層である。だから「yt-dlpでできないことがMeTubeでできる」ことは原則として無いし、逆にyt-dlp側の仕様変更はそのまま効いてくる。
Docker一行で起動する
導入は非常に短い。公式が示す最短の起動はDockerの1コマンドだ。
# ダウンロード先をホストの ./downloads に置いて起動する
docker run -d \
-p 8081:8081 \
-v /path/to/downloads:/downloads \
ghcr.io/alexta69/metube
継続運用するならCompose化しておく。
# docker-compose.yml
services:
metube:
image: ghcr.io/alexta69/metube
container_name: metube
restart: unless-stopped
ports:
- "127.0.0.1:8081:8081" # ← まずループバックに閉じる
volumes:
- ./downloads:/downloads
environment:
- UID=1000
- GID=1000
- OUTPUT_TEMPLATE=%(title)s.%(ext)s
ポート公開を127.0.0.1:8081:8081にしている点が重要だ。既定の-p 8081:8081は全インターフェースで待ち受けるため、そのままLANや、場合によってはインターネットへ露出する。MeTubeに認証は無いので、最初はループバックに閉じ、必要になってから公開範囲を広げるほうが安全側に倒れる。
主な環境変数の既定値はソース(app/main.py)で確認できる。
| 環境変数 | 既定値 | 意味 |
|---|---|---|
DOWNLOAD_DIR |
. |
保存先ディレクトリ |
OUTPUT_TEMPLATE |
%(title)s.%(ext)s |
ファイル名テンプレート |
OUTPUT_TEMPLATE_PLAYLIST |
%(playlist_title)s/%(title)s.%(ext)s |
プレイリスト時の階層 |
OUTPUT_TEMPLATE_CHANNEL |
%(channel)s/%(title)s.%(ext)s |
チャンネル単位の階層 |
HOST |
0.0.0.0 |
待受アドレス |
PORT |
8081 |
待受ポート |
DEFAULT_THEME |
auto |
UIテーマ |
ALLOW_YTDL_OPTIONS_OVERRIDES |
false |
個別上書き欄の有効化 |
テンプレート記法はyt-dlpの-oとまったく同じものだ。プレイリスト用・チャンネル用・チャプター用がそれぞれ独立した変数になっているので、保存先の階層設計をUIに触れずに決められるのが実用上ありがたい。
yt-dlpオプションは3層で合成される
MeTubeがただのボタン付きラッパーに留まらないのは、この設計があるからだ。yt-dlpのオプションを広い順に3層で与え、衝突したら具体的な層が勝つ。
YTDL_OPTIONS / YTDL_OPTIONS_FILE"] --> D["最終的なオプション集合"] B["② プリセット
YTDL_OPTIONS_PRESETS / _FILE
(UIで複数選択可・後勝ち)"] --> D C["③ 個別上書き
UIの Custom yt-dlp Options
(既定では無効)"] --> D D --> E["yt-dlp の Python API を実行"] F["extract_flat / noplaylist 等は
MeTubeが強制(上書き不可)"] --> E
重要なのは書式がコマンドラインフラグではないことだ。MeTubeはyt-dlpのPython APIオプション名をJSONで受け取る。おおむね「フラグのハイフンをアンダースコアに寄せた名前」になる。
{
"writesubtitles": true,
"subtitleslangs": ["ja", "en"],
"updatetime": false,
"writethumbnail": true
}
--write-subsが"writesubtitles": trueになる、という対応だ。ただし1対1で対応しないフラグがある点は要注意で、--embed-thumbnailや--recode-videoは"postprocessors"の配列として表現しなければならない。yt-dlp側にdevscripts/cli_to_api.pyという変換スクリプトが用意されているので、手元のコマンドライン設定を移植するときはそれを通すのが確実だ。
プリセットは「よく使う組合せに名前を付けてUIに出す」機能で、たとえばSponsorBlockでのスポンサー区間除去、字幕の埋め込み、速度制限などを名前つきの束にできる。ファイルで与えた場合は変更が監視されて自動リロードされるため、コンテナ再起動なしで設定を回せる。
合成規則で押さえる3点
・同じキーが複数の層にあれば、個別上書き > プリセット > グローバルの順で勝つ
・プリセットを複数選んだ場合は後に適用されたものが勝つ
・値にnullを入れるとそのキーを打ち消せる(例: "download_archive": nullでグローバルのアーカイブ設定を無効化)
なおメタデータ取得フェーズでMeTubeが使うextract_flat・noplaylistなどのキーはMeTube側が強制し、プリセットからは上書きできない。「なぜかプレイリストの扱いが設定どおりにならない」ときは、この強制キーに当たっていないか疑うとよい。
信頼境界:どこまでを内側に置くか
MeTubeを運用するうえで、日本語圏でまったく共有されていないが最も重要なのがここだ。
ALLOW_YTDL_OPTIONS_OVERRIDES=trueにすると、UIに自由記述のJSON欄(Custom yt-dlp Options)が出る。ここに入力された内容は最優先で適用される。公式READMEはこの機能に対して、有効化すると「UIにアクセスできる誰もが任意のyt-dlp APIオプションを与えられるようになり、使うオプション次第ではコンテナ内での任意コード実行を可能にしうる」と明記し、信頼できる環境でのみ有効化するよう求めている。
実際の既定値をソースで確認したところ、app/main.pyの設定ブロックに'ALLOW_YTDL_OPTIONS_OVERRIDES': 'false'とあり、ブール値として扱われるキーの一覧にも含まれていた。既定は無効である。
ここから導かれる運用方針は明快だ。
・MeTubeに認証は無い。到達できる=操作できる、と考える
・したがって-p 8081:8081のまま外に出さない。リバースプロキシで認証を挟むか、VPN・Tailscale等の内側に置く
・ALLOW_YTDL_OPTIONS_OVERRIDESは、UIに触れる人間を全員信頼できる場合のみtrueにする
・家庭内で家族に開放する、社内の限定メンバーに配る、といった用途なら既定のままで十分機能する
MeTubeはHTTPS対応とリバースプロキシ配下での動作を公式にサポートしており、Cookieを使った制限付き動画のダウンロードにも対応している。Cookieを預けるということは、そのアカウントへのアクセス権をコンテナに渡すことに等しいので、認証境界の設計はいっそう重要になる。
どれを選ぶか:CLIのまま使うか、UIを被せるか
MeTubeは「yt-dlpの上位互換」ではなく、配布形態の選択肢だと捉えるのが正しい。
| やりたいこと | 選ぶもの | 理由 |
|---|---|---|
| 自分の手元で細かく制御したい | yt-dlp | オプションの表現力とCI組み込みやすさ |
| CLIを使わない人にも渡したい | MeTube | Docker1つでWeb UI化。認証は手前で足す |
| 静止画ギャラリーを集めたい | gallery-dl | 投稿者・タグ単位の集合を展開できる |
| 進行中のライブ配信を録りたい | Streamlink | 終端未定のストリームに追従できる |
MeTubeが担うのはあくまでyt-dlpの守備範囲であり、静止画ギャラリーやライブ配信の追従はカバーしない。UI化で解けるのは「誰が使えるか」であって「何が取れるか」ではない——この区別を持っておくと、ツール構成を考えるときに迷いが減る。
まとめ
・MeTubeはyt-dlpをDockerコンテナ1つでWeb UI化するセルフホストツール(★14,437 / AGPL-3.0)
・独自のダウンロード実装は持たず、提供するのはキュー・進捗・保存先・オプション管理の層
・yt-dlpオプションはグローバル → プリセット → 個別上書きの3層合成。書式はフラグではなくJSONのAPIオプション名
・ファイル指定の設定(YTDL_OPTIONS_FILE等)は変更監視つきで自動リロードされる
・認証機構は無く、既定は0.0.0.0:8081。ALLOW_YTDL_OPTIONS_OVERRIDESは既定falseで、公式が任意コード実行のリスクを明記している
参照ソース
- alexta69/metube — GitHub リポジトリ(★14,437 / AGPL-3.0 / 2026-08-19時点)
- MeTube README — Configuring yt-dlp options / Security note
- alexta69/metube — app/main.py(環境変数の既定値)
- MeTube リリース 2026.08.18