YouTube動画のワンボックス埋め込みが機能しなくなりました

数日前(Discourse 2.5 ベータ 5 へのアップデート直後、そしてベータ 6 でも継続していますが、単なる偶然かもしれません)から、YouTube 動画の埋め込みが断続的に機能しています。
数時間機能しなかった後、再び正常に埋め込みが開始されました。
昨日からは、完全に機能しなくなりました。

フォーラムのログに特定の疑わしいエラーは見当たりません。
タイムアウトの問題でしょうか?これを特定して調査する方法はありますか?

ご協力ありがとうございます!

「いいね!」 2

YouTube のリンクを含む投稿の再構築をリクエストして生成されるトラフィックを確認したところ、奇妙な点が見つかりました。
リクエストは 404 エラーで失敗します。:thinking:

もう一つ、少し詳しい情報です。
Discourse 2.5.0.beta6 をコミット 2d880b42a3 に更新して実行しています(この投稿を送信する直前に再ビルドしました)。

YouTube のリンクを含む新しい投稿を作成すると、Google Chrome のコンソールで、onebox への GET リクエストの 404 エラーの直前に、Service Worker の登録エラーに関する追加のエラーが表示されます。

すべての onebox が機能していること、ただし YouTube だけが例外であることを指摘しておきます。:confused:

「いいね!」 1

ブラウザでは、ワンボックスが失敗した真の理由をお伝えすることができません。サーバーから同様のリクエストを試して確認する必要があります。

「いいね!」 2

ご提案いただいたことは理解しましたが、以下の点に問題があります:

  • /onebox?url=… に単純な GET リクエスト(ヘッダーなどを期待通りに渡して)を再実行すると、エラー HTML 404 が返ってきます。

  • サーバー側で、onebox が実行するリクエストを youtube_onebox.rb の Ruby コードからコピーして再実行すると、埋め込まれていない動画のうちの1つに対して curl 'curl 'https://www.youtube.com/oembed?format=json&url=https://www.youtube.com/watch?v=Xl-PTTeRsik' が正しく動作しているようです。
    実際にこの呼び出しは以下を返します:
    {"author_name":"AstronautiCAST","version":"1.0","height":270,"author_url":"https:\/\/www.youtube.com\/user\/AstronautiCAST","provider_name":"YouTube","provider_url":"https:\/\/www.youtube.com\/","thumbnail_height":360,"width":480,"html":"\u003ciframe width=\"480\" height=\"270\" src=\"https:\/\/www.youtube.com\/embed\/Xl-PTTeRsik?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen\u003e\u003c\/iframe\u003e","type":"video","thumbnail_width":480,"title":"Loading cargo into HTV-9 Konutori","thumbnail_url":"https:\/\/i.ytimg.com\/vi\/Xl-PTTeRsik\/hqdefault.jpg"}root@fait-2020:/var/discourse#
    これは埋め込みに必要なすべての情報を含んでいます。

なぜか分かりません :confused:

@Falco 大変お手数をおかけして申し訳ありませんが、YouTube の Onebox 機能の欠如が当フォーラムのユーザーエクスペリエンスを著しく損なっています。

昨日は、ソースコードを読んで(Onebox が 404 を返すタイミングや条件を理解するため)試行錯誤したり、本番環境のフォーラムを複製して別の Digital Ocean ドロップレットに移行して検証したりしました。

しかし、プラットフォームに関する深い知識が不足しているため、コードを読むだけでは十分な手がかりが得られませんでした。
ここで一つ疑問が残ります:Onebox の処理過程はどこかにログが残るのでしょうか?Onebox がエラーを認識して 404 を返す原因を理解するためには、非常に有用な情報になるはずです。

複製したドロップレットでは、本番サーバーの IP アドレスが YouTube によってブロックされているのか、あるいは使用しているドメイン名に関連する問題があるのかを確認しようとしたのですが、IP アドレスもドメイン名も異なるにもかかわらず、YouTube の Onebox は依然として機能しませんでした。

少なくとも Onebox が何を行っているのかを追跡できる方法を教えていただければと切に願っています。

「いいね!」 1

根本原因は判明しました:YouTube が当社の IP を禁止しましたが、なぜ禁止されたのかは不明です。なぜなら、この事象が発生した時点では、大規模なリベイクや同様の処理を行っていなかったからです。

@Falco さん、@codinghorror さんへの質問:2.5.0beta 5 または 6 のインストール時に、リクエスト制限を超えてしまうようなリベイクがトリガーされましたでしょうか?

「いいね!」 5

いいえ、最近のリベイクは追加していません。YouTube の変更のようです。他のユーザーも同様の不満を述べています。

「いいね!」 4

"Onebox Assistant", crawl for those previews reliably! を使用してプロキシクロールを試してみてください

「いいね!」 3

皆様、ご回答ありがとうございます。
ただ、Onebox エンジンが行うリクエストを模倣した場合(少なくともそうなるはずですが、@Falco さん、いかがでしょうか)、正しい回答を含む JSON 応答が返され、429 エラーにはならない理由がまだ不明です。

私のスクリーンショットにあるようなリクエストを実行する前に、Onebox によって 429 エラーを返す別のリクエストが行われているのでしょうか?
curl 'https://www.youtube.com/oembed?format=json&url=https://www.youtube.com/watch?v=Xl-PTTeRsik'

言うまでもありませんが、これらのリクエストは Discourse を実行しているサーバー自体(つまり、同じ発信元 IP)から行われました。

「いいね!」 1

curl コマンドを 1 回実行しただけでは、レート制限に引っかかることは少ないでしょう?

それを短時間に連続して実行してみるのはどうですか?反復的な bash スクリプトで実行するのは?(ただし、やりすぎるとBANされる可能性があります)

「いいね!」 1

ええと、YouTubeへのリンクが1つだけ含まれた投稿を再処理しようとするだけで、oneboxから404エラーが返されてしまいます…

トラブルシューティングの週末の後、興味深い発見がありました。
これは @Falco または @codinghorror が見てみる価値があるかもしれません。

現在、youtube_onebox.rb のソースコードを読むと、動画 ID を抽出できる 3 つの URL 形式がサポートされていることがわかります。

  1. http://youtu.be/<videoid>
  2. https://www.youtube.com/embed/<videoid>
  3. https://www.youtube.com/watch?v=<videoid>

1 と 3 の形式のリンクを持つ動画を onebox しようとする試みはすべて、onebox が 404 を返して失敗します(これはおそらく私たちの IP がブロックされていることに関連していると思います)。

2 の形式のリンクを埋め込もうとすると、うまくいきます!

これが この投稿 で説明されている事実とどのように関連しているのか、あるいは関連しているかどうか気になります。

onebox の内部動作(つまり、YouTube に対して実際にどのような呼び出しが行われるか)についての理解(およびログ出力)は非常に役立つでしょう…

「いいね!」 3

このスレッドを締めくくるために戻ってきました。
昨日、YouTube は私たちの禁止を解除し、再び業務を再開できました。

いずれにせよ、理解しておくことが興味深いと思う点がいくつかあります:

  • onebox が失敗した場合、詳細をログに記録することは可能でしょうか?onebox が失敗する理由を正確に把握するのに非常に役立ちます。
  • YouTube 動画の onebox に必要な唯一の要素は動画 ID であるため、404 を返す前に 3 種類の URL のそれぞれからデータを取得しようと試みるのは良いアイデアではないでしょうか(前述の通り、/embed/ URL は禁止されていたにもかかわらず、なぜか動作し続けていました)。

私のパニックに陥った質問に答えてくださった皆様、ありがとうございます!:clap:

「いいね!」 2

その通り!!!(以前も言及した非常に良いアイデアです)

ここでの課題の一部は、ターゲットが og タグを持たないページを返した場合、ワンボックス機能がそれがリダイレクトによるものだと認識できない点にあります。ただし、それをログに記録することは可能です(例:「ONEBOX: og タグが見つかりません」など)。空のワンボックスにつながるエラーはすべて確実にログに記録すべきです。

「いいね!」 2

tl;dr:私たちが直面しているのは、同じ問題のようです。最近の変更によりレート制限の問題が発生している場合、移行中や投稿の再ベイク中、あるいは単にフォーラムが非常に混雑している状況で、他のユーザーも同様の問題に直面し始める可能性があります。Onebox が「見かけ上」失敗してエラーを出力しないため、ユーザーが YouTube の onebox が表示されていないと報告するまで、これらの問題に気づくことができません。

背景

バージョン 2.6.0.beta 1 を使用しています。

ユーザーから「非安全なコンテンツ」に関するメッセージが届いていました。調査したところ、Chrome が HTTP サイトからリンクされた画像に対して警告を出しているようでした。そこで、Discourse を設定してすべての画像やメディアをダウンロードし、HTTPS で配信するように変更しました。

設定を変更した後、過去の投稿の再ベイクを行う必要がありました。その再ベイク以降、以前は onebox として表示されていた YouTube 動画の大部分が、再びリンク URL として表示されるようになりました。

10,000 件の投稿からなるスレッドがあり、そこには YouTube 動画への返信のみが含まれており、すべての投稿が onebox ではなく URL として表示されています。

再ベイク中は、キューに保留されたジョブが自然に処理されたため、削除されたジョブがキューに留まっているわけではありません。

@marcozambi が報告した同じエラーメッセージは確認していませんが、私たちもレート制限に抵触していると考えています。

試したこと

レート制限の仮説を裏付けるため、私が作成した小さなコードで投稿を再ベイクしたところ、スレッド内の最初の 80 件以上の YouTube 動画は正常に onebox 化されましたが、残りの動画は変換に失敗しました。

その時点では、投稿を編集してわずかな修正を加えて再保存しても、URL が onebox として「展開」されませんでした。同時に、すべてのキューは空か、期待通り即座に処理される最小限のジョブのみが含まれていました。

そのコードを 30 分間再実行しても、リンクの onebox 化を強制できませんでした。80 という数字に特別な意味があるわけではなく、利用可能なクォータの範囲内だったに過ぎないと考えられます。

@marcozambi は、他のリンクが失敗する中で /embed/ 形式の YouTube リンクが機能したと報告していました。そこで、コードを修正して YouTube リンクを /embed/ 形式に変換する正規表現による検索と置換を追加しました。

コードは機能しました。

しかし、再度コードを実行して投稿を再ベイクしただけでは、onebox として表示されませんでした。

今後の計画として、大規模なスレッド内のすべての YouTube リンクを /embed/ 形式に変換するタスクを実験的に実行する予定です。もしそれが失敗するか、より高いレート制限に抵触する場合は、@merefield の Onebox Assistant を検討します。

後ほど更新を投稿します。

「いいね!」 2

はい、確かに何かおかしいことが起きており、レート制限に関連しているようです。

私が大量のリベイクを行ったことで「悪者」扱いされているのか、それとも他のユーザーも直面する制限に引っかかっているのかはわかりません。

YouTube 動画のワンボックス化には制限があり、その制限に達するとワンボックス化は失敗しますが、エラー表示はされずに静かに失敗します。

これは、明らかな理由から変更する必要があると感じていますが、特に移行やリベイクを行うユーザーにとっては、展開されていない、または一度展開されたワンボックスが単なる通常の URL になっていることに気づかない可能性があります。

上記で @marcozambi 氏が言及していた通り、他の形式が失敗している場合(おそらくレート制限の問題による)、動画 ID の前に /embed/ が含まれる YouTube URL 形式は機能します。

この現象をよく示す動画はこちらです。

このスクリーンキャストを記録した時点では、キューに処理が詰まっておらず、フォーラム全体も正常に動作していました。

この動画の撮影前には、すでに YouTube リンクがワンボックスによって展開されなくなっていました。

ご覧いただくと、https://youtu.be/<video-id> 形式の YouTube リンクがワンボックスによって展開されない compose ウィンドウが表示されます。

その後、形式を https://youtube.com/embed/<video-id> に変更すると、ワンボックスが正常に展開されます。

再度元の形式で試すと、失敗します。

この動画の記録中は、ブラウザのコンソールとネットワークタブを追跡しました。問題は私のブラウザとサーバーの間ではなく、サーバーと YouTube の間にあることは確かだと認識していますが、参考になればと思い以下に含めます。

(画像がズームアウトしすぎていることにお詫び申し上げます。拡大すれば見えることを願っています)

そして、ワンボックスが機能したときのネットワークトレースです。

私は、/embed/形式のリンクがここでの万能薬だとは確信していません。

むしろ、https://youtu.be/<video-id> ルートがレート制限に達した際に、https://youtube.com/embed/<video-id> ルートという別のルートが、独立した制限を持つ別の経路として機能しているように思われます。

両方のルートに制限がかかっているという証拠は、99% が YouTube の動画返信で構成される、1 万スレッドもの巨大なスレッドにある YouTube 埋め込みの形式を変更するために私が作成したユーティリティから得られます。

この段階では、すでに https://youtu.be/<video-id> 形式のリンクを Onebox が展開できなくなっていました。

私のユーティリティは、YouTube の動画 URL を https://youtube.com/embed/<video-id> 形式に変更するもので、スレッド内の最初の 3000 投稿に対して実行されました。

最初の 1108 件では正常に動作しましたが、その後の約 1900 件では形式は変更されたものの、Onebox によって展開されませんでした。

この間、多くのジョブが生成されました(私のコードは post.revise を使用していました)が、エラーや再試行なしにすべて処理されました。

個人的な観察ですが、ある時点でジョブの処理が劇的に加速したように見えました。これは、Onebox のコードが YouTube から何らかのエラーを素早く受け取っていたためかもしれません。ただし、計測は行っていないため、他の要因による可能性もあります。

より詳細な証拠を提供する用意はありますが、Onebox gem に計装を施さなければ何ができるか確信が持てません。

私はハッカーであり Ruby の専門家ではありませんが、もし大まかな手順があれば喜んで従います。

「いいね!」 1

サーバーのコマンドラインから、同じユーザーエージェントを使用していくつかの短い反復的な curl スクリプトを実行することで、レート制限の問題を特定できる可能性があります。

この回避策が機能するのは、おそらく別個のカウントとして扱われているためだと考えられます。

「いいね!」 3

さらにいくつかの結果があります。ただし、以下の投稿には多くの仮定が含まれており、それらは実際の知識の欠如に基づいています。

次に、何が起きているか、そして何が起こるべきかについての私の見解を投稿します。

レスポンスありがとうございます、ロバート。

注意点として、/watch ルートを使用した動画のワンボックス化は、私が試した際に(今も!)失敗していました。そのため、ループを使って強制的に失敗させる必要はありませんでした。

そこで私が行った仮定の1つは、Onebox が使用する user-agentDiscourse Forum Onebox v2.6.0.beta1 であるということです。これは以下のコードに基づいています…

ランダムな動画を選択し、curl を使用してヘッダーを読み取る試みを行いました。

これはライブサイトの Docker コンテナ内で行ったもので、以下のレスポンスが得られました。

/watch? ルートを使用した最初の curl の結果

コマンド

curl --user-agent "Discourse Forum Onebox v2.6.0.beta1" -sD - -o /dev/null "https://m.youtube.com/watch?v=s0ONj4TG0UA"

レスポンス:

curl --user-agent "Discourse Forum Onebox v2.6.0.beta1" -sD - -o /dev/null "https://m.youtube.com/watch?v=s0ONj4TG0UA"
HTTP/2 303 
content-length: 0
p3p: CP="This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=en-GB for more info."
cache-control: no-cache
x-frame-options: SAMEORIGIN
content-type: text/html; charset=utf-8
location: https://www.youtube.com/watch?v=s0ONj4TG0UA&app=desktop
accept-ch-lifetime: 2592000
x-content-type-options: nosniff
accept-ch: DPR
expires: Tue, 27 Apr 1971 19:44:06 GMT
strict-transport-security: max-age=31536000
date: Fri, 07 Aug 2020 11:35:21 GMT
server: YouTube Frontend Proxy
x-xss-protection: 0
set-cookie: VISITOR_INFO1_LIVE=rcVTSJn81Ck; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:35:20 GMT; httponly; samesite=None
set-cookie: YSC=cFXIPerzT3Y; path=/; domain=.youtube.com; secure; httponly; samesite=None
set-cookie: GPS=1; path=/; domain=.youtube.com; expires=Fri, 07-Aug-2020 12:05:20 GMT
alt-svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"

したがって、location ヘッダーにある URL である https://www.youtube.com/watch?v=s0ONj4TG0UA&app=desktop へ 303 レスポンスでリダイレクトされました。

これにより、URL の末尾に &app=desktop が追加されるだけの効果がありました。

リダイレクトされた URL への 2 回目の curl の結果 - まだ /watch? ルート上

コマンド
curl --user-agent "Discourse Forum Onebox v2.6.0.beta1" -sD - -o /dev/null "https://www.youtube.com/watch?v=s0ONj4TG0UA&app=desktop"

レスポンス

HTTP/2 429 
x-content-type-options: nosniff
expires: Tue, 27 Apr 1971 19:44:06 GMT
x-frame-options: SAMEORIGIN
cache-control: no-cache
p3p: CP="This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=en-GB for more info."
accept-ch-lifetime: 2592000
content-type: text/html; charset=utf-8
accept-ch: DPR
strict-transport-security: max-age=31536000
content-length: 48982
date: Fri, 07 Aug 2020 11:46:00 GMT
server: YouTube Frontend Proxy
x-xss-protection: 0
set-cookie: VISITOR_INFO1_LIVE=VQwNuouhq-s; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:46:00 GMT; httponly; samesite=None
set-cookie: YSC=8IRfPRFRY6c; path=/; domain=.youtube.com; secure; httponly; samesite=None
set-cookie: GPS=1; path=/; domain=.youtube.com; expires=Fri, 07-Aug-2020 12:16:00 GMT
set-cookie: VISITOR_INFO1_LIVE=VQwNuouhq-s; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:46:00 GMT; httponly; samesite=None
set-cookie: YSC=8IRfPRFRY6c; path=/; domain=.youtube.com; secure; httponly; samesite=None
set-cookie: GPS=1; path=/; domain=.youtube.com; expires=Fri, 07-Aug-2020 12:16:00 GMT
alt-svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"

つまり、retry-after ヘッダーなしで 429(要求が多すぎます)レスポンスコードが返されており、交渉なしに即座に停止を命じられています。

いずれにせよ、これが Onebox が受け取っている応答であれば、それを無視しているか、少なくともログに記録されている場合でもどこを確認すればよいか分かりません。

単一の 429 に対してはこれが正当な行動かもしれません。しかし、非常に短い期間に多数の 429 レスポンスが返されることは無視できません。

3 回目の curl の結果 - 今回は /embed/ ルートを使用

完全を期すために、同じ動画を取得しようとしましたが、今回は /embed/ ルートを使用しました。

コマンド

curl --user-agent "Discourse Forum Onebox v2.6.0.beta1" -sD - -o /dev/null "https://www.youtube.com/embed/s0ONj4TG0UA"

レスポンス

HTTP/2 200 
accept-ch-lifetime: 2592000
content-type: text/html; charset=utf-8
expires: Tue, 27 Apr 1971 19:44:06 GMT
x-content-type-options: nosniff
cache-control: no-cache
p3p: CP="This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=en-GB for more info."
strict-transport-security: max-age=31536000
accept-ch: DPR
date: Fri, 07 Aug 2020 11:55:29 GMT
server: YouTube Frontend Proxy
x-xss-protection: 0
set-cookie: VISITOR_INFO1_LIVE=PNE6x6djF00; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:55:29 GMT; httponly; samesite=None
set-cookie: VISITOR_INFO1_LIVE=PNE6x6djF00; path=/; domain=.youtube.com; secure; expires=Wed, 03-Feb-2021 11:55:29 GMT; httponly; samesite=None
set-cookie: GPS=1; path=/; domain=.youtube.com; expires=Fri, 07-Aug-2020 12:25:29 GMT
set-cookie: YSC=pDW-hdbauK8; path=/; domain=.youtube.com; secure; httponly; samesite=None
alt-svc: h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
accept-ranges: none
vary: Accept-Encoding

200 - 成功。

lazy-yt プラグインが /watch 形式の URL を書き換えているようです

これが重要かどうかは分かりませんが、埋め込みプラグインの lazy-yt はデフォルトで有効になっていますか?開発環境のインストールでそれを見つけました。

これは YouTube Oneboxer の to_html メソッドをモキーパッチしているようです。

重要かどうかは分かりませんが、元の Onebox の to_html メソッドは /embed/ URL 形式を返します…

一方、lazy-yt プラグインは /watch?v= URL 形式を使用します。

問題が存在し、何らかの形で対応が必要であることを示すために他にできることはありますか?次の投稿では、私が根本原因だと考えていることについて説明します。

「いいね!」 4