6 ポイント 投稿者 GN⁺ 2023-08-15 | 1件のコメント | WhatsAppで共有
  • YouTubeのファイルURLは /youtubei/v1/player API から取得できるが、そのままダウンロードすると 非公式ダウンロード制限 のため速度が極端に遅くなる
  • 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ブラウザのリクエストを観察して許容値を見つける
  • 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.js URL を探す
    • 正規表現でチャレンジ関数名と関数本体を抽出する
    • Node.js の vm.runInNewContext で変換関数を実行する
    • 変換された値でURLの n パラメータを置き換える

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 の制限を回避するために似た手法を使っている

1件のコメント

 
GN⁺ 2023-08-15
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
    • そうしたアンチデバッグ手法を回避するなら Anti-Anti-Debug [0] を試す価値がある
      似たような理由で以前、数時間で作った簡単な拡張機能だ
      0: https://chrome.google.com/webstore/detail/anti-anti-debug/mn...
    • 開発者ツールが開かれているかどうかを検知できること自体、ブラウザー側の大きな欠陥のように感じる
      開発者ツールが開かれているかどうかは Web ページが絶対に知ることができないようにすべきで、きちんと実装できるはずだ
    • Firefox でたまに効く方法は、動画上で shift+右クリックThis FrameOpen Frame in New Tab を押すことだ
      新しいタブでは開発者ツールが動作する
    • ブラウザーの開発者ツールを検知しようとするページなら、トラフィック解析にはまず Wireshark を使ってみることを思いつく
  • 最終段階では、画面を見続けるには 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を推奨している
      色の変化は動画の色空間やモニタープロファイル処理の失敗に由来することがあり、この場合スクリーンショットが実際のアプリ画面と違って見えることもある
      細かな揺れはフレームドロップかもしれず、色のある物体のエッジにピクセル化が見えるなら、最近傍の色差アップスケーリングの可能性がある
    • 1つのYouTube動画には複数の映像・音声・統合ストリームがある
      ブラウザが選ぶストリームと、youtube-dlまたはそのフォークがデフォルトで選ぶストリームは異なる場合がある
      以前はしばらく最高の統合ストリームをデフォルトで選んでいたが、分離された最高品質の音声ストリームと映像ストリームのほうが品質は高い
    • VLCのようなプレイヤーはもっと上手くやれるし、GLSLで望みの補正を自作することもできる
      特にanime4kシェーダーパックが気に入っていて、機械学習ベースだがmpvではリアルタイムに動き、VLCでもできそう
      名前の通りアニメ向けに調整されているが、ノイズ除去とぼけ除去がなかなか良く、YouTubeコンテンツを見やすくすることが多く、復元ステップは圧縮アーティファクトをかなりうまく処理する
      ただしアニメに寄せすぎているので常にうまく動くわけではなく、かえって悪くなることもある
      https://github.com/bloc97/Anime4K/releases
    • ブラウザの映像パイプラインはVLCが使うものと異なる可能性がある
      ローカルファイルを指すvideo要素を入れた簡単なHTML文書を作って比較できる
  • YTがダウンローダー相手にまた中途半端な対策を配布するたびに驚く
    GOOGはWidevineも持っているのに、なぜ使わないのか気になる

    • Widevineのソフトウェア版はごく短時間で完全に破られ、ワンクリックのダウンロード用アドオンでも回避されるはず
      ユーザーにとって変わることはなく、YouTubeはWidevine運用の負担だけを負うことになる
      ハードウェアベース版を使うと、サポートされていないデバイスで多くの問題が起きる可能性がある
    • YouTubeはコンテンツを違法コピーしたりサードパーティクライアントを使ったりすること自体は、それほど気にしていないように思える
      気にしているのは帯域幅の浪費
      広告ベースの動画ストリーミングサイトでは通常、帯域幅コストが収益より高いが、GoogleはISPに無料ピアリングを迫れるほど安い帯域を確保しているため、かろうじて成り立っている
      こうした速度制限は、すべてのコンテンツをクロールして持っていく人ではなく、実際のユーザーに帯域の大半を残すための措置
    • Widevineを使わない理由は、復号ステップが追加されて遅くなり、ソフトウェア動画デコードを強制して遅くなり、Webブラウザは効果の弱い最弱形態のWidevineしかサポートしないため
      目標達成にもあまり効果的ではない一方で、かなりの数のユーザーをプラットフォームの外へ押し出す可能性が高い
    • 主な理由は、CDNキャッシュ効率を少し落としてコストがかかり、追加の鍵管理システムを運用しなければならないから
      YouTube規模では、こうしたシステムをできるだけ減らしたがっている
      さらにWidevine Level 3を非常に大きな攻撃対象にしてしまう
      結局は財務上の方程式で、広告ブロックで失う金額はまだWidevineのスイッチを入れるほどではないが、より弱い対策を取る程度にはなっており、レコード会社からの圧力もあるだろうから、数年以内により広く展開される可能性はある
      予測するなら、最初はContent IDに引っかかったレーベル音楽やスタジオクリップが入った動画から始まり、他のクリエイターには選択タグを提供するかもしれない
      そうした動画のほうが収益化に有用で、CDN上の利点を一度に失うこともない
    • Googleはサードパーティクライアントを抑制しつつ、人々がアーカイブすることは許容したい可能性が高い
      目立たない形でこうした中途半端な対策を取ることが、その目標を達成するための完璧で唯一の解法
  • YouTubeが動画をどう配信しているのか、ずっと気になっていた
    インターネットがひどい状態のときでもうまく動いたし、南米ではすべてのプラットフォームが快適に動くわけではないのに、YouTubeは最も滑らかな動画プラットフォーム
    最も近いのはNetflixだが、それでもかなり後れを取っている

    • 自宅近くのISPネットワーク内にキャッシュサーバーを配置している
      ISPにもメリットがあるので受け入れる
      ISPのボトルネックは自社ネットワークからより広いインターネットバックボーンへ出る接続であり、大手CDNのキャッシュサーバーはそのボトルネックから大きな負荷を取り除く
      Netflixの似た構成の文書: https://openconnect.netflix.com/
  • YouTube から動画を直接ダウンロードしたことはあるだろうか?
    youtube-dl、yt-dlp、そうしたウェブサイトに頼らずに手動でやってみると、思ったよりずっと複雑だ

    • かなり昔、そういうことをする Perl スクリプトを作ったことがある: https://www.perlmonks.org/?node_id=636777
      もちろん、この種のスクリプトの問題は、YouTube が動画のダウンロードを防ぐために変更する部分を追い続けなければならないことだ
    • ユーザースクリプトを直接注入して処理している
      WEI を見ると、長くは持たないかもしれない自分の USER AGENT を使う方式だ
      署名、n のデコード、速度制限関数を再実装しようと苦労するのではなく、player.jsmatch(/(?: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% 正常に見えるとも言える
    • 「Download」ボタンを押して Premium 料金を払う、という方法のこと?
  • 技術的にはどれも興味深いが、倫理的に「Google くたばれ」だけを考えるのでなければ、最初の最適化、つまり実ブラウザ検査を通過して通常のブラウザ速度を得るところで止めるのが合理的に感じる
    その程度なら、広告ブロックブラウザのユーザーより YouTube のリソースを無駄にしているわけではない
    何の費用も払わず Gb/s の全速を使うのは、広告ブロックユーザー全体の運を試している感じがする
    もちろん、結局は Google くたばれ、なのかもしれない

    • 技術的には、誰もがネットワーク接続のコストを払っている
      YouTube に最大速度で叩きつけることが非倫理的だとまでは言わないが、YouTube がブロックする措置を取っても非難はしない
      ソーシャルメディアの画像にマウスを乗せると元のサイズで表示するブラウザ拡張を使っているが、Instagram が異常なアクティビティの警告とアカウントロックの脅しを表示した
      拡張が裏でスクレイピングしているのか確認したが、特に問題はなさそうで、おそらく Meta は標準クライアントと異なるリクエスト順序を見てデータスクレイピングだと判断しているのだろう
      措置と対抗措置の繰り返しであり、YouTube も自分たちの対策を実装してスクレイパーに再び対抗させるだろうが、正当な消費が公式クライアントで再生速度の 2 倍より速くなることはないので、いずれはその程度にダウンロードを制限できるはずだ
      それでも、ダウンロード自体は制限されるべきではないと思う
      コンテンツはすでに法律で保護されており、多くの場合、保存、分析、レビュー動画の制作のような正当な理由で動画をダウンロードしている
      YouTube コンテンツは真空の中で作られるものではなく、公開された後は新しい動画が作られる環境を生むため、この創作の自由が重要だ
    • これがどれほどの濫用なのか、よく分からない
      結局、同じ量のデータをより短い時間で受け取るだけなので、帯域幅は多く使うが、より早く消える
      通常のブラウザのユースケースは、動画を最後まで見ないというよくある状況に合わせて調整されているようだ
      最初から全体を見て保存するつもりなら、Google の帯域をより食っているとは見なしにくく、ただ接続数のためにオーバーヘッドは大きくなる可能性がある
    • 企業にあるのは倫理ではなく、利害関係だけだ
      私も同じように振る舞うのが自然だ
    • YouTube のリソースや Gb/s と言うが、多くの場合、動画は同じ ISP ネットワーク内で配信される
      YouTube が世界中のほぼすべての ISP とインターネットエクスチェンジにキャッシュを置いているからで、これまで作られた最大の CDN かもしれない
      例えば、投稿者の YouTube URL はカナダの ISP Videotron を指している
      https://bgp.he.net/dns/rr1---sn-8qu-t0aee.googlevideo.com
    • 技術的には、動画はダウンロードできるべきで、ブロックされるべきではない
      誰かがヘイトスピーチを広めたり、自分や家族を侮辱したりした証拠を残すためにも必要だ
      画面をカムコーダーで撮ることもできるが、石器時代的な解決策に聞こえる
      例えば Mac のブラウザでは Netflix のスクリーンショットを撮れないので、フェアユースに当たるミーム制作さえ奪われている