Resumo
FAO: @Falco ![]()
Divulgação de IA: Este bug foi investigado de forma autônoma e a causa e a solução foram sugeridas pelo Opus 5.5.
No navegador Brave, ao ativar o desfoque de fundo em uma sala Live, sempre aparece um toast de erro: “Não foi possível iniciar o desfoque de fundo, então ele foi desativado.” O mesmo usuário, fórum e sala funcionam normalmente no Google Chrome na mesma máquina.

A causa é o elemento <video> oculto que BackgroundBlurManager#setup() cria, mas nunca insere no documento. O Brave rejeita o play() nele com:
AbortError: The play() request was interrupted because the media was removed from the document.
Inserir o elemento no documento (de forma invisível) antes do play() faz com que funcione no Brave.
Ambiente
- Discourse
2026.10.0-latest.1(568a006ad8), plugin Live incluído,discourse_voice_assets0.2.0 - Brave (Chromium 155) no Linux, Wayland, GPU Intel; WebGL2 e WebGPU acelerados por hardware
- Google Chrome na mesma máquina: funciona
Passos para reproduzir
- Abra uma sala Live no Brave e ligue a câmera.
- Ative o desfoque de fundo.
- O toast aparece e o desfoque é desligado.
Diagnóstico
Executei o pipeline de desfoque do próprio plugin passo a passo no console do Brave (mesmo caminho de asset, modelo, delegado e modo de execução que background-blur.js), com a proteção contra fingerprinting do Brave ativada e depois desativada:
| Etapa | Brave, proteção contra fingerprinting ativada | Brave, proteção contra fingerprinting desativada |
|---|---|---|
Importação de vision_bundle.js, carregamento WASM |
ok | ok |
ImageSegmenter.createFromOptions, delegados GPU e CPU |
ok | ok |
getUserMedia({ video: true }), estado da track |
ok, live |
ok, live |
play() em um <video> mudo desconectado com o stream da câmera (o que o plugin faz) |
AbortError | AbortError |
play() no mesmo tipo de <video> anexado a document.body (1px, transparente) |
ok | ok |
Ou seja, MediaPipe, WebGL e a câmera estão todos funcionando corretamente. Apenas o play() desconectado falha, e a proteção contra fingerprinting do Brave não faz diferença. O Chromium headless reproduz um <video> desconectado sem erro, o que está de acordo com o fato de funcionar no Chrome.
Correção sugerida
Em plugins/live/assets/javascripts/discourse/lib/live/background-blur.js, em setup(): anexe o vídeo oculto ao documento antes de video.play() e remova-o em teardown(). Por exemplo:
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() como agora ...
// teardown():
this.#video?.remove();
Até onde consigo ver, este é o único lugar no plugin que reproduz um elemento de mídia desconectado.
Duas observações relacionadas
-
O erro real é ignorado.
#createBackgroundBlur()emlocal-video-manager.jsusa umcatch {}simples e chamaliveLog.warn("[live] failed to start background blur")sem o erro. Mesmo comlive_verbose_loggingativado, o console nunca diz por que o desfoque falhou. Passar o erro capturado paraliveLog.warn(que já o sanitiza) teria exposto o erro mais rapidamente. -
O desfoque é oferecido onde nunca pode funcionar.
BackgroundBlurManager.isSupported()verifica apenascanvas.captureStreameWebAssembly. Em um navegador sem WebGL, o segmentador do MediaPipe falha com ambos os delegados GPU e CPU (Service "kGpuService" ... cannot be created: emscripten_webgl_create_context() returned error 0), porque o pós-processador de segmentação precisa de um contexto GL de qualquer maneira. Adicionar uma verificação de WebGL2 emisSupported()ocultaria ou desabilitaria o controle de desfoque em vez de falhar após o usuário ativá-lo. (Reproduzido no Chromium headless fazendo stub degetContext("webgl*"), não visto no mundo real.)
Obrigado pelo Live - além disso, está funcionando muito bem para nós.