En direct : le flou d’arrière-plan échoue toujours dans Brave Browser (« Impossible de démarrer le flou d’arrière-plan ») – .play() sur une balise <video> détachée est interrompu

Résumé

FAO : @Falco :smiling_face_with_sunglasses:
Diversification IA : Ce bug a été investigué de manière autonome et la cause ainsi que le remède ont été suggérés par Opus 5.5.

Dans Brave Browser, l’activation du flou d’arrière-plan dans une salle Live affiche toujours une notification d’erreur : « Le flou d’arrière-plan n’a pas pu être démarré, il a donc été désactivé. » Le même utilisateur, le même forum et la même salle fonctionnent correctement dans Google Chrome sur la même machine.

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

La cause est la balise <video> cachée que BackgroundBlurManager#setup() crée mais n’insère jamais dans le document. Brave rejette play() dessus avec :

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

Insérer l’élément dans le document (de manière invisible) avant play() permet de le faire fonctionner dans Brave.

Environnement

  • Discourse 2026.10.0-latest.1 (568a006ad8), plugin Live inclus, discourse_voice_assets 0.2.0
  • Brave (Chromium 155) sous Linux, Wayland, GPU Intel ; WebGL2 et WebGPU accélérés par le matériel
  • Google Chrome sur la même machine : fonctionne

Étapes pour reproduire

  1. Ouvrir une salle Live dans Brave et allumer la caméra.
  2. Activer le flou d’arrière-plan.
  3. La notification apparaît et le flou est désactivé.

Diagnostic

J’ai exécuté le pipeline de flou du plugin étape par étape dans la console Brave (même chemin d’accès aux ressources, modèle, délégué et mode d’exécution que background-blur.js), avec la protection contre le fingerprinting de Brave activée puis désactivée :

Étape Brave, protection contre le fingerprinting activée Brave, protection contre le fingerprinting désactivée
Import de vision_bundle.js, chargement WASM ok ok
ImageSegmenter.createFromOptions, délégués GPU et CPU ok ok
getUserMedia({ video: true }), état de la piste ok, live ok, live
play() sur un <video> muet détaché avec le flux de la caméra (ce que fait le plugin) AbortError AbortError
play() sur un <video> de même type ajouté à document.body (1px, transparent) ok ok

Donc MediaPipe, WebGL et la caméra sont tous fonctionnels. Seul play() détaché échoue, et la protection contre le fingerprinting de Brave ne fait aucune différence. Chromium sans interface graphique joue un <video> détaché sans erreur, ce qui correspond au fonctionnement de Chrome.

Correction suggérée

Dans plugins/live/assets/javascripts/discourse/lib/live/background-blur.js, setup() : ajouter la vidéo cachée au document avant video.play(), et la retirer dans teardown(). Par exemple :

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() comme maintenant ...

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

Pour autant que je puisse voir, c’est le seul endroit dans le plugin qui lit un élément média détaché.

Deux observations connexes

  1. La vraie erreur est ignorée. #createBackgroundBlur() dans local-video-manager.js utilise un simple catch {} et appelle liveLog.warn("[live] failed to start background blur") sans l’erreur. Même avec live_verbose_logging activé, la console ne dit jamais pourquoi le flou a échoué. Transmettre l’erreur capturée à liveLog.warn (qui la sanitize déjà) aurait permis de mettre en surface l’erreur plus rapidement.

  2. Le flou est proposé là où il ne peut jamais fonctionner. BackgroundBlurManager.isSupported() vérifie uniquement canvas.captureStream et WebAssembly. Dans un navigateur sans WebGL, le segmenteur de MediaPipe échoue avec les deux délégués GPU et CPU (Service "kGpuService" ... cannot be created: emscripten_webgl_create_context() returned error 0), car le post-processeur de segmentation a besoin d’un contexte GL dans tous les cas. Ajouter une vérification WebGL2 à isSupported() masquerait ou désactiverait le contrôle de flou au lieu d’échouer après que l’utilisateur l’a activé. (Reproduit dans Chromium sans interface graphique en stubbant getContext("webgl*"), non observé en conditions réelles.)

Merci pour Live - à part cela, ça fonctionne bien pour nous.

1 « J'aime »

À première vue, cela semble bon. Souhaitiez-vous soumettre une PR avec le correctif ?