未分類
背景
ボットや自動ダウンロードツールを防ぐため、YouTubeは動画のストリーミングURLを保護するJavaScriptベースの「チャレンジ」を導入している。
仕組み
1. 通常のブラウザでのアクセス
- ユーザーがYouTube動画ページにアクセス
- YouTubeサーバーがJavaScriptコードを送信
- ブラウザがJavaScriptを実行し、「署名」を生成
- この署名付きのURLで動画をストリーミング
2. n challengeとは
- YouTubeの動画URLには
nというパラメータが含まれる - この
nパラメータは暗号化されたチャレンジ値 - 正しく「解読」しないと、動画URLが無効になる(403 Forbiddenエラー)
- 解読にはYouTubeが送ってくるJavaScriptコードを実行する必要がある
動画URL例:
https://rr1---sn-xxx.googlevideo.com/videoplayback?...&n=暗号化された値&...
↑
これを解読する必要がある
3. なぜyt-dlpで問題になるか
- yt-dlpはPythonで書かれている
- YouTubeのチャレンジはJavaScriptで書かれている
- PythonだけではJavaScriptを実行できない
- → JavaScriptランタイム(Node.js、Deno等)が必要
エラーメッセージの意味
WARNING: [youtube] kS8r7UcexJU: n challenge solving failed: Some formats may be missing.
意味: n challengeの解読に失敗したため、一部(または全部)の動画フォーマットが取得できない
なぜ「一部」なのか
- YouTubeには複数のフォーマット(画質・音質)がある
- 高画質の動画フォーマット → n challengeで保護されている
- 低品質の音声フォーマット → 保護が緩い場合がある
- → 音声だけダウンロードできて、動画がダウンロードできない現象が起きる
解決策
--remote-components ejs:github オプション
yt-dlp --remote-components ejs:github "URL"
このオプションは:
- GitHubから「チャレンジソルバースクリプト」をダウンロード
- Deno(JavaScriptランタイム)を使ってスクリプトを実行
- n challengeを解読
- 正しい動画URLを取得
ダウンロードされるもの
[youtube] [jsc:deno] Downloading challenge solver lib script from
https://github.com/yt-dlp/ejs/releases/download/0.3.2/yt.solver.lib.min.js
ejs= Embedded JavaScript solver- yt-dlpプロジェクトが管理しているチャレンジソルバー
YouTubeがこれをする理由
- 著作権保護 - 動画の不正ダウンロードを防ぐ
- 帯域制御 - ボットによる大量アクセスを防ぐ
- 広告収入保護 - ダウンロードされると広告が見られない
- いたちごっこ - YouTubeは定期的にチャレンジを更新する → yt-dlpも更新が必要
まとめ
| 用語 | 説明 |
|---|---|
| n challenge | YouTubeの動画URL保護機構 |
| チャレンジソルバー | n challengeを解読するスクリプト |
| ejs | yt-dlpが提供するチャレンジソルバー |
| Deno | JavaScriptを実行するランタイム |
--remote-components ejs:github | GitHubからソルバーをダウンロードして使うオプション |
2025年11月以降の重要な変更
外部JSランタイム必須化
yt-dlp 2025.11.12からYouTubeの完全サポートには外部JavaScriptランタイムが必須になった。
WARNING: [youtube] JavaScript runtime now required for full YouTube support
なぜこの変更が必要だったか
- 従来のアプローチ: yt-dlpは巨大な正規表現パターンでJSチャレンジを解読していた
- 問題点: YouTubeの難読化が複雑化し、正規表現では対応困難に
- 新アプローチ: AST(抽象構文木)ベースのパターンマッチングに移行
- 結果: player.jsの変更により迅速に対応可能に
サポートされているJSランタイム
| ランタイム | デフォルト | 備考 |
|---|---|---|
| Deno | ✅ 有効 | 推奨。完全にサンドボックス化、ネットワーク/ファイルアクセスなし |
| Node.js | ❌ 無効 | セキュリティ上の理由でデフォルト無効 |
| QuickJS | ❌ 無効 | パフォーマンス面で推奨される場合も |
| Bun | ❌ 無効 | セキュリティ上の理由でデフォルト無効 |
Denoが推奨される理由:
- 単一の実行ファイルでポータブル
- 完全にサンドボックス化されている
- ネットワークやファイルシステムへのアクセスが一切ない
JSランタイムなしの場合
- 現時点では「一応」動作する
- ただし利用可能なフォーマットが大幅に制限される
- ログイン状態では特に制限が厳しい
- 今後さらに悪化する見込み(バグではなく仕様)
今後の懸念: PO(Proof-of-Origin)トークン
YouTubeはすべてのプレイヤークライアントに対してPOトークンの要求を強化しています。これへの対応にも、ネイティブのjsinterpモジュールでは不可能なJavaScript機能が必要になる見込みです。