YouTube動画ダウンロード制限の回避
(blog.0x7d0.dev)- YouTubeのファイルURLは
/youtubei/v1/playerAPI から取得できるが、そのままダウンロードすると 非公式ダウンロード制限 のため速度が極端に遅くなる - 2021年半ば以降、URLに付く
nクエリパラメータ はbase.jsの JavaScript アルゴリズムで変換する必要があり、失敗すると YouTube が静かに速度制限をかける nを正しく処理しても、ダウンロード時間は動画の長さとサイズに合わせて調整され、例では 1.5GB の動画が約 4.0MB/s でダウンロードされる- HTTP
Rangeヘッダー でファイルを 10MB の断片に分けて新しい接続で受け取ると、制限がかかる前に各断片を高速に取得できる - 最終ファイルは別々に提供される 映像・音声ストリーム を
ffmpegで結合する必要があり、yt-dlp、VLC media player、NewPipe、node-ytdl-core も同様の手法を使っている
YouTubeファイルURLを取得する流れ
- 実際のメディアファイルURLは
/youtubei/v1/playerエンドポイントの呼び出しで取得できる - このAPIは動画タイトル、説明、サムネイル、フォーマット情報を返し、フォーマット一覧から希望する品質のファイルURLを選べる
- 例の動画IDは
aqz-KE-bpKQ - リクエスト本文には
videoId,context.client.clientName,context.client.clientVersionのような値が入る contextオブジェクトのほかの値はAPIが検証する前提条件で、Webブラウザのリクエストを観察して許容値を見つける
- 例の動画IDは
- APIで受け取った
adaptiveFormats[0].urlをそのまま使うと、ダウンロードは事実上妨げられたも同然の遅さになる- 例では 1.5GB ファイルが 66.7kB/s 程度で表示される
- 速度はおおむね 40〜70kB/s に制限される
- 10分の動画をすべて取得するのに約 6時間30分 かかることがある
n パラメータが作る最初の制限
- 2021年半ば以降、YouTube はほとんどのファイルURLに
nクエリパラメータ を含めている - この値は、Webページと一緒に配布される
base.js内の JavaScript アルゴリズムで変換しなければならない - YouTube は
nの値を、公式クライアントかどうかを見分ける チャレンジ のように使っているnがない、または正しく変換されていないと、ダウンロード速度制限が静かに適用される
- 変換アルゴリズムは難読化されており頻繁に変わるため、毎回その内容をリバースエンジニアリングする方法は実用的ではない
- 例の実装では、現在のプレーヤーバージョンの
base.jsをダウンロードしてn変換コードを抽出し、元のn値を渡して実行する- YouTube の embed ページで
base.jsURL を探す - 正規表現でチャレンジ関数名と関数本体を抽出する
- Node.js の
vm.runInNewContextで変換関数を実行する - 変換された値でURLの
nパラメータを置き換える
- YouTube の embed ページで
n 変換後にも残る速度制限
nパラメータを正しく変換すると、最初の極端な制限は消えるが、YouTube はなお 可変ダウンロード制限 を適用する- 制限の程度は動画サイズと長さによって異なり、ダウンロード時間が動画の長さの約半分になるよう調整される
- メディアファイルを常に可能な限り高速で提供すると、ストリーミングサービスにとって大きな帯域の無駄になりうる
- 例のダウンロードでは、1.5GB のファイルが約 4.0MB/s で取得される
HTTP Rangeで小さな断片を高速に受け取る
- 回避方法の核心は、HTTP
Rangeヘッダー でファイルを複数の小さな区間に分けてダウンロードすることにある Rangeヘッダーは各リクエストで受け取るファイル区間を指定する- 例:
Range: bytes=2000-3000
- 例:
- 例のコードはメディアファイルを 10MB セグメント に分けて処理する
- 既存の出力ファイルを削除する
- これまでに受け取ったバイト数を基準に次の 10MB 区間を計算する
- 各リクエストに
Rangeヘッダーを入れ、responseType: 'stream'で受け取る - 受け取ったデータをファイルの末尾に追記する
- 進捗、全体サイズ、セグメントごとの速度を出力する
- この方法が機能するのは、制限ルールが適用されるまで時間がかかり、小さなセグメントは新しい接続で非常に速く受け取れるためである
- テスト出力では 1464.99MB のファイルで次の速度が示された
- 0.68% 時点: 46.73MB/s
- 1.37% 時点: 60.98MB/s
- 2.05% 時点: 71.94MB/s
- 6.14% 時点: 104.17MB/s
- 一部のダウンロードでは 1Gb/s 接続 をほぼ使い切るほどで、平均速度は通常 50〜70MB/s、つまり 400〜560Mb/s の範囲だった
映像・音声の結合と既存実装
- YouTube は 映像と音声のチャンネル を別ファイルとして配信している
- この構造では、HD や UHD の動画が同じ音声ファイルを再利用できるため、保存容量を節約できる
- 一部の動画では、言語ごとに異なる音声チャンネルも提供される
- 最終段階では
ffmpegで映像ファイルと音声ファイルを1つに結合する-c copyで再エンコードせずにストリームをコピーする-map 0:v:0で1つ目の入力の映像ストリームを選択する-map 1:a:0で2つ目の入力の音声ストリームを選択する- 結合後に一時的な映像・音声ファイルを削除する
- 全体のサンプルコードは youtube-download.js として提供されている
- 複数のプロジェクトが YouTube の制限を回避するために似た手法を使っている
- yt-dlp: youtube-dl の Python フォークで、
nパラメータ変換のために独自の JavaScript インタプリタを含む - VLC media player
- NewPipe
- node-ytdl-core
- yt-dlp: youtube-dl の Python フォークで、
1件のコメント
Hacker News の意見
yt-dlp リポジトリでの議論で見た限り、この制限は HTTP Range ヘッダーではなく、
range=xxxというクエリパラメーターを付けるだけでも回避できた範囲をファイル全体にしても再び最高速度が出ていて、記憶が正しければ YouTube はすでにこの制限を解除していた
参考: https://github.com/yt-dlp/yt-dlp/issues/6400
YouTube では試していないが、もっと怪しげなストリーミングサイトの動画はWeb 開発者ツールで取得したことがある
たいていは開発者ツールを開くと、スキップできない
debugger文を作り、CPU を大量に使うコード、おそらく無限ループや暗号資産マイナーのようなものを実行して動画を止める、という保護を使っているさらに重要なのは、このコードがネットワークリクエスト情報も消して、これまで送られたトラフィックの解析を難しくする点で、Firefox の「ログを保持」は本当にログを保持すべきだ
完璧な防御ではないので結局取得できなかった動画はなかったが、この仕組みをもっと深く説明した資料を見てみたい
debuggerキーワード名を変えてしまう笑ってしまうほどだった
https://news.ycombinator.com/item?id=36961445
似たような理由で以前、数時間で作った簡単な拡張機能だ
0: https://chrome.google.com/webstore/detail/anti-anti-debug/mn...
開発者ツールが開かれているかどうかは Web ページが絶対に知ることができないようにすべきで、きちんと実装できるはずだ
shift+右クリック→This Frame→Open Frame in New Tabを押すことだ新しいタブでは開発者ツールが動作する
最終段階では、画面を見続けるには WorldCoin で支払わなければならず、その取引できない WorldCoin は広告を見ることでしか稼げないようになる気がする
画面に内蔵された小さな Orb がそれを監視するし、これが本当にベーシックインカムのためだと信じていたわけではないだろう
ベーシックインカムの問題は銀行口座と本人確認(KYC)でずっと前に解決されていた
最近 yt-dlp の速度制限問題に遭遇している人がいるのか気になる
いつも
mpvで YouTube を見ていて、内部的に yt-dlp を使っているのだが、先週から状態がかなり悪くなった最初は 500kB/s に制限している分だけ速く始まるが、少し経つと 3 秒のダウンロードで 1 秒分の再生しか取得できず、再生前にかなり長くキューに入れておく必要がある
git 版の yt-dlp を使っているが、関連する issue は見当たらなかった
mpvは yt-dlp で動画 URLだけを取得し、その URL をffmpegに渡すffmpegは Range ヘッダー関連の回避策を実装していないため、速度制限に引っかかるyt-dlp に直接ダウンロードさせて、それを
mpvにパイプで渡し標準入力から再生させることはできるが、まだダウンロードされていない区間へのシークが壊れるmpv の issue トラッカーにはこの問題に関する issue が多い
YouTube はこの過程で細かい部分を継続的に変えている
以前 YouTube 動画用の内部編集ツールを作ったことがあるが、MP4 ファイルが必要で、1か月ごとくらいに YouTube の変更のせいでエディターが壊れ、デバッガーで何が変わったのか確認して合わせる必要があった
脇道だけど、YouTubeで見ると動画がごくわずかに良く見えるのは気のせいなのか気になる
よく見る動画をダウンロードしてVLCやApple TVのInfuseで見ているが、YouTubeアプリの「nerd stats」で同じ映像/音声ストリームを見ていることは確認できる
それなのにYouTubeは、ブロック状の圧縮アーティファクトをより滑らかに見せる、非常に微妙なフィルターをかけているように思える
エッジを強調しているわけではなく、エッジのない色変化の領域を見つけて、ブロック状のアーティファクトを目立ちにくくしている感じ
気のせいかもしれないが、YouTubeでは画面がより鮮やかで締まって見え、ダウンロードした動画では背景や影にごく微妙だが目につくアーティファクトや細かな揺れが見えて、1440p動画でも最終的な画質が劣って見える
音声も違いがはっきりしていて、YouTubeは全体的に音量が均一なのに、ダウンロードした動画は音量を上げる必要があって不便
VLCやInfuseもYouTubeのように映像を見やすくする処理をしてくれるとよいのだが、色やシャープネスのフィルターというより、チャンネル間の体験を一貫させるオーディオレベリングのような処理をしているように思う
YouTubeやSpotifyのような多くのストリーミングサイトはReplayGainというものを使っている
動画や曲の平均音量を計算したタグで、アップロード時に計算される
公式YouTubeクライアントは再生時にそのタグを使って音量を調整するが、ダウンロード時にタグが抜けたり、MKVがReplayGainタグを標準サポートしていなかったりする可能性がある
元解像度のストリームをフルスクリーンで再生すれば、白黒のエッジでは差は消えるはず
OSによっては2つのフルスクリーンアプリを素早く切り替えて差をテストでき、ISO 29170-2は5Hzを推奨している
色の変化は動画の色空間やモニタープロファイル処理の失敗に由来することがあり、この場合スクリーンショットが実際のアプリ画面と違って見えることもある
細かな揺れはフレームドロップかもしれず、色のある物体のエッジにピクセル化が見えるなら、最近傍の色差アップスケーリングの可能性がある
ブラウザが選ぶストリームと、youtube-dlまたはそのフォークがデフォルトで選ぶストリームは異なる場合がある
以前はしばらく最高の統合ストリームをデフォルトで選んでいたが、分離された最高品質の音声ストリームと映像ストリームのほうが品質は高い
特に
anime4kシェーダーパックが気に入っていて、機械学習ベースだがmpvではリアルタイムに動き、VLCでもできそう名前の通りアニメ向けに調整されているが、ノイズ除去とぼけ除去がなかなか良く、YouTubeコンテンツを見やすくすることが多く、復元ステップは圧縮アーティファクトをかなりうまく処理する
ただしアニメに寄せすぎているので常にうまく動くわけではなく、かえって悪くなることもある
https://github.com/bloc97/Anime4K/releases
ローカルファイルを指す
video要素を入れた簡単なHTML文書を作って比較できるYTがダウンローダー相手にまた中途半端な対策を配布するたびに驚く
GOOGはWidevineも持っているのに、なぜ使わないのか気になる
ユーザーにとって変わることはなく、YouTubeはWidevine運用の負担だけを負うことになる
ハードウェアベース版を使うと、サポートされていないデバイスで多くの問題が起きる可能性がある
気にしているのは帯域幅の浪費
広告ベースの動画ストリーミングサイトでは通常、帯域幅コストが収益より高いが、GoogleはISPに無料ピアリングを迫れるほど安い帯域を確保しているため、かろうじて成り立っている
こうした速度制限は、すべてのコンテンツをクロールして持っていく人ではなく、実際のユーザーに帯域の大半を残すための措置
目標達成にもあまり効果的ではない一方で、かなりの数のユーザーをプラットフォームの外へ押し出す可能性が高い
YouTube規模では、こうしたシステムをできるだけ減らしたがっている
さらにWidevine Level 3を非常に大きな攻撃対象にしてしまう
結局は財務上の方程式で、広告ブロックで失う金額はまだWidevineのスイッチを入れるほどではないが、より弱い対策を取る程度にはなっており、レコード会社からの圧力もあるだろうから、数年以内により広く展開される可能性はある
予測するなら、最初はContent IDに引っかかったレーベル音楽やスタジオクリップが入った動画から始まり、他のクリエイターには選択タグを提供するかもしれない
そうした動画のほうが収益化に有用で、CDN上の利点を一度に失うこともない
目立たない形でこうした中途半端な対策を取ることが、その目標を達成するための完璧で唯一の解法
YouTubeが動画をどう配信しているのか、ずっと気になっていた
インターネットがひどい状態のときでもうまく動いたし、南米ではすべてのプラットフォームが快適に動くわけではないのに、YouTubeは最も滑らかな動画プラットフォーム
最も近いのはNetflixだが、それでもかなり後れを取っている
ISPにもメリットがあるので受け入れる
ISPのボトルネックは自社ネットワークからより広いインターネットバックボーンへ出る接続であり、大手CDNのキャッシュサーバーはそのボトルネックから大きな負荷を取り除く
Netflixの似た構成の文書: https://openconnect.netflix.com/
YouTube から動画を直接ダウンロードしたことはあるだろうか?
youtube-dl、yt-dlp、そうしたウェブサイトに頼らずに手動でやってみると、思ったよりずっと複雑だ
もちろん、この種のスクリプトの問題は、YouTube が動画のダウンロードを防ぐために変更する部分を追い続けなければならないことだ
WEI を見ると、長くは持たないかもしれない自分の USER AGENT を使う方式だ
署名、
nのデコード、速度制限関数を再実装しようと苦労するのではなく、player.jsをmatch(/(?:player\/([a-zA-Z0-9_-]+)\/)?(?:html5player|(?:www|player(?:_ias)?))[-\.]([^/]+?)(?:(?:\/html5player(?:-new)?)?|(?:\/[a-z]{2,3}_[A-Z]{2})?\/base)\.js/)で見つけ、その中から関連する関数を grep して直接呼び出しているYouTube 側から見れば、自前の DRM 関数が私のために
.mp4リンクを開いているのだから、100% 正常に見えるとも言える技術的にはどれも興味深いが、倫理的に「Google くたばれ」だけを考えるのでなければ、最初の最適化、つまり実ブラウザ検査を通過して通常のブラウザ速度を得るところで止めるのが合理的に感じる
その程度なら、広告ブロックブラウザのユーザーより YouTube のリソースを無駄にしているわけではない
何の費用も払わず Gb/s の全速を使うのは、広告ブロックユーザー全体の運を試している感じがする
もちろん、結局は Google くたばれ、なのかもしれない
YouTube に最大速度で叩きつけることが非倫理的だとまでは言わないが、YouTube がブロックする措置を取っても非難はしない
ソーシャルメディアの画像にマウスを乗せると元のサイズで表示するブラウザ拡張を使っているが、Instagram が異常なアクティビティの警告とアカウントロックの脅しを表示した
拡張が裏でスクレイピングしているのか確認したが、特に問題はなさそうで、おそらく Meta は標準クライアントと異なるリクエスト順序を見てデータスクレイピングだと判断しているのだろう
措置と対抗措置の繰り返しであり、YouTube も自分たちの対策を実装してスクレイパーに再び対抗させるだろうが、正当な消費が公式クライアントで再生速度の 2 倍より速くなることはないので、いずれはその程度にダウンロードを制限できるはずだ
それでも、ダウンロード自体は制限されるべきではないと思う
コンテンツはすでに法律で保護されており、多くの場合、保存、分析、レビュー動画の制作のような正当な理由で動画をダウンロードしている
YouTube コンテンツは真空の中で作られるものではなく、公開された後は新しい動画が作られる環境を生むため、この創作の自由が重要だ
結局、同じ量のデータをより短い時間で受け取るだけなので、帯域幅は多く使うが、より早く消える
通常のブラウザのユースケースは、動画を最後まで見ないというよくある状況に合わせて調整されているようだ
最初から全体を見て保存するつもりなら、Google の帯域をより食っているとは見なしにくく、ただ接続数のためにオーバーヘッドは大きくなる可能性がある
私も同じように振る舞うのが自然だ
YouTube が世界中のほぼすべての ISP とインターネットエクスチェンジにキャッシュを置いているからで、これまで作られた最大の CDN かもしれない
例えば、投稿者の YouTube URL はカナダの ISP Videotron を指している
https://bgp.he.net/dns/rr1---sn-8qu-t0aee.googlevideo.com
誰かがヘイトスピーチを広めたり、自分や家族を侮辱したりした証拠を残すためにも必要だ
画面をカムコーダーで撮ることもできるが、石器時代的な解決策に聞こえる
例えば Mac のブラウザでは Netflix のスクリーンショットを撮れないので、フェアユースに当たるミーム制作さえ奪われている