ライブ:Braveブラウザで背景ぼかしが常に失敗します(「背景ぼかしを開始できませんでした」)- 分離された <video>.play() が中断されます

サマリー

FAO: @Falco :smiling_face_with_sunglasses:
AI開示事項: このバグはエージェント的に調査され、原因と修正方法はOpus 5.5によって提案されました。

BraveブラウザでLiveルームの背景ぼかしを有効にすると、常にエラートーストが表示されます:「背景ぼかしを開始できなかったため、無効になりました。」 同じユーザー、フォーラム、ルームでも、同じマシン上のGoogle Chromeでは正常に動作します。

error: "Background blur couldn't be started, so it was turned off."

原因は、BackgroundBlurManager#setup() が作成するがドキュメントに挿入しない非表示の <video> です。Braveはこれに対する play() を以下のように拒否します:

AbortError: The play() request was interrupted because the media was removed from the document.

play() の前に要素を(見えない形で)ドキュメントに挿入すれば、Braveで動作するようになります。

環境

  • Discourse 2026.10.0-latest.1 (568a006ad8)、バンドルされたLiveプラグイン、discourse_voice_assets 0.2.0
  • Linux、Wayland、Intel GPUでのBrave (Chromium 155);WebGL2とWebGPUはハードウェアアクセラレーション済み
  • 同じマシン上のGoogle Chrome:動作確認済み

再現手順

  1. BraveでLiveルームを開き、カメラをオンにする。
  2. 背景ぼかしを有効にする。
  3. トーストが表示され、ぼかしが無効になる。

診断

Braveコンソールで、プラグイン独自のぼかしパイプラインを段階的に実行しました(background-blur.js と同じアセットパス、モデル、デリゲート、実行モードを使用)。Braveのフィンガープリント保護をオンにし、その後オフにしてテストしました:

ステップ Brave、フィンガープリント保護オン Brave、フィンガープリント保護オフ
vision_bundle.js のインポート、WASM読み込み ok ok
ImageSegmenter.createFromOptions、GPUおよびCPUデリゲート ok ok
getUserMedia({ video: true })、トラック状態 ok、live ok、live
カメラストリームを持つデタッチされたミュート <video> への play() (プラグインが実行している処理) AbortError AbortError
document.body に追加された同種の <video> (1px、透明) への play() ok ok

つまり、MediaPipe、WebGL、カメラはすべて正常です。失敗するのはデタッチされた play() のみであり、Braveのフィンガープリント保護には違いがありません。ヘッドレスChromiumではデタッチされた <video> をエラーなしで再生でき、これはChromeでの動作と一致します。

推奨される修正

plugins/live/assets/javascripts/discourse/lib/live/background-blur.js の setup() で、video.play() の前に非表示のビデオをドキュメントに追加し、teardown() で削除します。例:

video.setAttribute("aria-hidden", "true");
video.style.cssText =
  "position:fixed;width:1px;height:1px;opacity:0;pointer-events:none";
document.body.appendChild(video);
// ... await video.play() as now ...

// teardown():
this.#video?.remove();

私の知る限り、これはプラグイン内でデタッチされたメディア要素を再生する唯一の場所です。

関連する2つの観察事項

  1. 実際のエラーが飲み込まれている。 local-video-manager.js の #createBackgroundBlur() は素の catch {} を使用しており、エラーを伴わずに liveLog.warn("[live] failed to start background blur") を呼び出しています。live_verbose_logging を有効にしても、コンソールにはぼかしが失敗した理由が表示されません。キャッチされたエラーを liveLog.warn に渡す(すでにサニタイズされている)ことで、より迅速にエラーを表面化できたはずです。

  2. 決して動作しない場所でぼかしが提供されている。 BackgroundBlurManager.isSupported() は canvas.captureStream と WebAssembly のみをチェックしています。WebGLがないブラウザでは、MediaPipeのセグメンターはGPUおよびCPUデリゲートの両方で失敗します(Service "kGpuService" ... cannot be created: emscripten_webgl_create_context() returned error 0)。なぜなら、セグメンテーションの後処理はどちらの場合もGLコンテキストを必要とするからです。isSupported() にWebGL2チェックを追加することで、ユーザーが有効にした後に失敗するのではなく、ぼかしコントロールを非表示または無効にできます。(getContext("webgl*") をスタブすることにより、ヘッドレスChromiumで再現。実環境では確認されていません。)

Liveのおかげです - これを除けば、私たちの環境ではうまく動作しています。

「いいね!」 1

ざっと見たところ、良さそうです。修正をPRとして提出しますか?

「いいね!」 1

送信します!

「いいね!」 1