YouTubeにバグがあった – ChatGPTを使って調査した
YouTube had a bug – I used ChatGPT to investigate (blog.thezilber.com)
要約
筆者は、YouTubeで動画がランダムに巻き戻ったり、視聴途中の位置からずれてロードされたりするバグに遭遇し、その原因究明を試みました。ChatGPTの助けを借りながらブラウザの開発者ツールを駆使し、バグの再現方法や原因の特定を進め、最終的にウェブ版とAndroidアプリ版での挙動の違いから、バグの根本原因に迫りました。
全文翻訳
YouTubeにバグがあった – ChatGPTを使って調査した
バグ:
ここ数日、無視できないバグに気づいた。ソフトリロードの際にYouTubeがランダムに巻き戻ってしまうことがあり、視聴途中の動画をリロードすると、停止した時点よりもかなり前にロードされるのだ。これには非常に腹が立ったので、できる限り深くこの問題を探求し、Googleにチケットを送り、「この問題があります、問題はここにあり、修正はこれです、修正してくだらないものを押し付けるのをやめてください」と伝えることを目標にした。その結果、調査は当初の目標よりは劇的ではないものの、非常に洞察に富むものとなった。そこで、この経験を共有することにした。
当初は少し野心的すぎた。最近現れたInstagramでも同様のバグに気づき、ChatGPTにInstagramとYouTubeのスタックに何か共通点があるか尋ねた。可能性は低いし、あまり理にかなってはいなかったが、私の手元にある千人の博士号の力を使えば、トークンを消費して何が得られるか見てみる価値はあると思った。ChatGPTはしばらく考え、いくつかの興味深い推測を提示した…私はそれらをすべて無視し、スコープをYouTubeのバグのみに絞ることにした。
タブを切り替えたり、一時停止したり、解除したり、あらゆる種類のことを試して、巻き戻る挙動を再現しようと試行錯誤した。うまくいかなかった。これは主にソフトリロード、つまりYouTubeを視聴して一時停止し、しばらくしてからそのタブに戻った場合に発生することに気づいた。主な問題はソフトリロード自体ではなく、チェックポイントのタイムスタンプの復元にあると仮定することにした。そこで、動画を一時停止し、タブを閉じ、再度開いてみた – するとどうだろう! – 一時停止した時点より20秒ほど前に動画が復元された。
さらにいじってみた – 再度タブを閉じて開き直した – さらに20秒のずれ。
次にブラウザ全体を閉じて開き直した – さらに20秒の巻き戻し。
実際、新しいYouTubeのショートカットキーを発見した。Ctrl+Wでタブを閉じ、Ctrl+Shift+Tで開き直すと20秒巻き戻る。これを十分な回数繰り返せば、何かを見逃した場合でも、動画の任意のポイントまで簡単に巻き戻すことができる。
彼らはすべてのショートカットキーを文書化すべきだ:
- 左矢印キーで5秒巻き戻し
- Hキーで10秒巻き戻し
- そして今 – Ctrl+W、Ctrl+Shift+Tでなんと20秒巻き戻し! – 唯一の欠点は、毎回ページをリロードする必要があることだ :(
また、同じチェックポイントでも、ウェブブラウザでロードするとバグが発生するが、YouTubeのAndroidアプリを使用すると、毎回正しい時間でロードされることも発見した。
ブラウザでタブを閉じても、スマホでYouTubeの履歴を開けば、停止した時点に正確に戻るが、ブラウザで開き直すと、デジャヴュの強い感覚を経験させられる。
(しばらく寝た後、ウェブアプリとAndroidアプリの挙動の違いの原因が理解できたが、それは最後まで読んでもらわないと分からない。)
リバースエンジニアリング:
ウェブ開発の世界では、開発者が書いたコードがブラウザで直接実行されるという特権があり、ブラウザという獣は、開発者ツールというセットを提供してくれる。これらのツールを使えば、ウェブを閲覧している際に見かけるどんなひどいコードでもデバッグできる。通常、私がデバッグすることを選ぶ臭いコードは自分で書いたものだが、今日は、Googleという小さなインディーズ企業で働く誰かが書いたコードだった。
ⓘ DevToolsについて(ウェブ開発者以外向け)
Chromeを実行している場合、ウェブページを開いた状態でF12キーを押してください。そのページの仕組みを深く掘り下げることができます。HTMLのソースや異なる要素を検査したり、それらがページ上のどこにあるか、どのようなCSSスタイルが適用されているかなどを確認できます。それらの要素を追加したり削除したりできます。私たちのトピックにとって最も重要なのは、実行されているJavaScriptコードを見ることができることです。デバッグしたり、ブレークポイントを設定したり、コールスタックを確認したりできます。また、開発者ツール内でページ上のあらゆるものを直接変更することもできます。これにはJavaScriptのハッキングも含まれます。
これは非常に役立ちます。YouTubeはブラウザで実行されるため、バグがあれば、クライアント上で実行されている限り、それらを生み出すコードを見ることができます。(残念ながら、サーバー上で実行されるコードの一部にはアクセスできません。)主な注意点は、JSコードが難読化されているため、デバッグが面倒だということです。
一つの簡単な答えが知りたかった:チェックポイントのタイムスタンプはどのように推測または計算されるのか?サーバーからそのまま提供されるのか?それともクライアント側で何らかの変更を受けるのか?
知る必要があった。なぜなら?Googleの開発者は、最新バージョンのYouTubeに親切にもこのバグを「バイブコード」してくれたからだ。そして私は彼らがそれを解決してくれるとは信じられなかった。(バイブコーディングが適用されたという証拠なしに、allegedly vibecodedと言わざるを得ない。彼らはこの奇妙なバグを手動で作成した可能性も十分にある。)私は、彼らに解決策を明記することで、彼らでさえこのような複雑な問題を解決するためにLLMをガイドできるはずだと推測した。
この問題にどう取り組むべきか、ChatGPTに尋ねた。ページロード時に発生するものをどう調査するか?それは、動画のシークが発生するたびにハンドラをアタッチするTampermonkeyスクリプトを提供してくれた。つまり、動画が別のタイムスタンプにジャンプするたびに、コンソールに便利な「Seek [from -> to]」メッセージを表示してくれる。スクリプトがページリロード時でも機能し、YouTubeのチェックポイントジャンプによってトリガーされることを確認した後、次のステップの準備ができた – 動画シークがトリガーされるたびにスクリプトにdebugger;行を書き込み、コールスタックを備えたきれいなブレークポイントを得て、この問題を調査するために必要なすべてを確認できるようにする。
ⓘ Tampermonkeyについて
TampermonkeyはChromeの拡張機能です。これにより、JavaScriptをページに注入して、その動作をハッキングできます。
Tampermonkeyは、ページがどのように実行され、どのコードが実行されているかを理解したい場合にも役立ちます。例えば、ページ上のどこかで動画のシークがトリガーされた場合、シーク関数をフックして、呼び出されたタイムスタンプを印刷できます。また、スクリプト内にブレークポイントを設定することもできるため、そのシーク内でbreak;してコールスタックを検査し、実行パスを確認して、シークタイムスタンプの変数がどのように選択されたかをチェックできます。
難読化されたコードスタックを10分間上り下りして、次に何をすべきかを正確に理解した – デバッグをChatGPTに任せること。
シンギュラリティに近づいているのは幸いだ。なぜなら、私の慈悲深いLLMは、Chromeにはデバッグポートを開く機能が搭載されていることを教えてくれたからだ。さらに、OpenCode(ヒップスター向けのClaude Code)にアタッチできる気の利いたMCPサーバーがある。これにより、私の個人的な博士号はChromeに接続し、あらゆる方法でDevToolsを使用できるようになり、ブラウザを完全に侵害する能力を得られる。
つまり、Chromeでボタンを押し、LLMに指示を与えると、ブラウザにコマンドを送信して、デバッグYouTubeを含むあらゆることを実行させることができる。(セキュリティや侵害に関する懸念を抱く前に、OpenCodeがChromeに接続したいときはいつでも、Chromeが許可を求めるポップアップを表示することを知っておくべきだ。すべて合意の上で安全に行われる。)
ⓘ MCPとChromeデバッグについて
Chrome DevTools Protocol(CDP)は、デバッグモードでブラウザと通信して何が起こっているかを確認するために使用できるAPIです。これにより、Chromeと直接通信するソフトウェアを記述して、ネットワーク上で受信したものを検査したり、ロードされたJSファイルを確認したり、ページを表示したり、コードを変更したりできます。
Chromeで「chrome://inspect/#remote-debugging」を開くと、リモートデバッグを有効にするチェックボックスがあるページが表示されます。有効にすると、外部ソフトウェアがChromeに接続して制御できるようになります。これにはAIエージェントが使用するソフトウェアも含まれます。
MCP(またはModel Context Protocol)は、AIエージェントが外部ツールを使用できるようにする標準プロトコルです。Chrome DevTools MCPは、CDPによってバックアップされたブラウザデバッグツールのセットを公開するローカルサーバーです。OpenCodeをそれを使用するように構成すると、OpenCodeはそのサーバーを開始または接続します。エージェントはこれらのツールを呼び出すことができ、MCPサーバーはCDPを使用してChromeで実際の操作を実行します。
結論:
GPTにしばらく実行させてテストを行い、難読化されたYouTubeコードを読み、ネットワークを確認してタイムスタンプとして何を受信しているかを確認し、結論を導き出した。見つけたのは以下の通りだ:
- YouTubeのチェックポイントは、ローカルストレージなどからではなく、YouTubeサーバーから直接受信される。
- YouTubeサーバーから受信したチェックポイントのタイムスタンプは、すでに壊れている。タブを閉じると、サーバーに送信されるタイムスタンプはXだが、タブを再度開くと、サーバーはX - 20を返す – まさに驚くべきエンジニアリングだ。
ブラウザ版YouTubeとYouTube Androidアプリの挙動の違いを説明できるのは、次の2つのうちのどちらかだと推測している。
- AndroidアプリとブラウザアプリがGoogleサーバーから異なるタイムスタンプを受信する(可能性は低い)。
- Androidアプリは、サーバーから不適切なタイムスタンプを受信していることを「知って」おり、それをクライアント側で修正している。
最初のシナリオは、Android版YouTubeとウェブ版YouTubeが異なるサーバーと異なるメタデータを扱っているという奇妙なアーキテクチャ上の決定を意味することになる。
2番目のシナリオは、脳死したエンジニアが行うようなエンジニアリング上の決定、または将来私たち全員をペーパークリップに変えてしまう可能性のある何かに起因するバグを構成することになる。
何が起こったのかは、あなたが判断してください。
結論更新:
しばらく寝た後、見落としていたことに気づいた – 私はほとんどのテストをYouTubeリンクでページをロードして行っていた。しかし!YouTubeの履歴タブから動画をクリックした場合(YouTubeは視聴したすべての動画の履歴を保存する)、実際には「youtube.com/videoId_
&t=123s_
」というURLにリダイレクトされるのだ。このクソ野郎どもめ。
さて、なぜ私が怒っているのか説明しよう。最初の部分「youtube.com/videoId」は動画を識別する。これは直接的なURLだ。しかし、最後の部分「&t=123s」はページパラメータであり、ブラウザに「おい、この変数を取れ、アプリケーションがそれを使って何をするか知っているだろう」と伝える。したがって、アプリケーションはURLパラメータを通じてサーバーから異なるタイムスタンプを受信し、あなたが停止した時点に転送する。このアプローチの根本的な問題は二つある:
- これは単一責任の原則に違反している。なぜなら、ページはすでにURLパラメータとは無関係にサーバーからシークタイムスタンプを受信しているからだ。これはバグを生み出す可能性があり、またバグを隠す可能性もある(我々が見たように)。この場合の隠れたバグは、標準的なレジュームパスから来るチェックポイントタイムスタンプが20秒の巻き戻しを引き起こすことだ。
- ページがソフトリロードする場合、URLパラメータで提供されるタイムスタンプに移動し、サーバー上の保存されたチェックポイントを積極的に無視する。
そのため、私によく起こるのは次のことだ:
- 動画を20分ほど視聴する。
- 動画を閉じる。
- しばらくして動画を開く – URLタイムスタンプ20分、チェックポイントタイムスタンプ20分。
- さらに20分動画を視聴する。動画を一時停止する – URLタイムスタンプは20分のままで、サーバーに送信されるチェックポイント = 40分。
- ラップトップを閉じ、カフェで作業し、家に帰る。
- タブから再び動画を視聴し始める – タブが古いため、URLをリロードする。
- 40分(バグの20秒マイナス)でチェックポイントを受信するが、URLはまだ20分と読んでいるため、時間を巻き戻される。
- YouTubeにバグレポートを開く。
URLのタイムスタンプは一つのことに役立つ – 動画をタイムスタンプ付きで友達と共有することだ。履歴から動画をリロードする際は、すでに存在するチェックポイントメカニズムに依存すべきだ。YouTubeのURL内の時間パラメータをロードすべきではない。なぜなら、上記のようなことが起こるからだ。URLタイムスタンプは、標準的な動画レジュームパスとして設計されたことはなく、それを変更したことで、かつてMicrosoftだけが提供できた素晴らしいユーザーエクスペリエンスの種類が生まれたのだ。
追加の楽しいメモ:
- これを徹底的な調査と呼ぶのは難しい。この記事の初稿に書いたすべての言葉は私のものだったが、私の調査はYouTubeの最新アップデートのコードレビューと同じくらい徹底的に行われた。初めてDevToolsで「バイブデバッグ」した。今思えば、結論が正しいか確認するためにLLMにもういくつか質問できたはずだ。もし私が間違っていたら、私の過ちについて謝罪する。
- 正確さよりもスピードとユーモアを優先した。Googleとは何の確執もないし、一般的に彼らは合理的な仕事をしていると思う。私もAIに頼りすぎると不適切なバグを生み出すので、それを見かけたときは自分でそれを指摘することを許している。また、私がそもそも不適切な調査を行い、同様に不適切な結論に至った可能性もある。読者やこの記事に偶然たどり着くかもしれないGoogleの人々には、これを強いスタンスやGoogle、AI、あるいはその他のものに対する私の認識を示すものではなく、風刺として読んでほしいと期待している。
- YouTubeに開いたバグレポートでは、より丁寧な言葉遣いを使用した。