6 puntos por GN⁺ 2025-02-17 | 1 comentarios | Compartir por WhatsApp
  • Al rastrear el ruido blanco en una laptop Linux, se descubrió un problema en el que una pestaña de Firefox seguía despertando el sink de audio de PulseAudio incluso sin que hubiera sonido real
  • module-suspend-on-idle estaba configurado para detener el dispositivo de audio después de 10 segundos, pero si un sitio web crea un AudioContext, el sink no baja a IDLE/SUSPENDED
  • El mismo fenómeno apareció con notificaciones web de Outlook, clics en x.com, reproducción de voz en Google Translate y la app web de Discord, y el ruido empezaba incluso solo con new AudioContext()
  • En las mediciones, cuando no había ruido el uso de CPU de pulseaudio era 0.0%, pero con ruido era 4.7%, y el consumo del sistema aumentaba aproximadamente 1.5W
  • AudioContext.suspend() puede detener el acceso al hardware de audio para reducir el uso de CPU/batería, pero Firefox no detiene automáticamente ese desperdicio después de un tiempo como sí lo hace Chrome

El problema de que el sink de audio no entra en suspensión

  • En una laptop nueva, incluso cuando no se reproducía música ni audio, se escuchaba por los parlantes un ruido blanco tenue pero molesto
  • Para revisar el estado de PulseAudio en Linux se usó pactl list sinks short
    • El estado del sink de audio aparece como IDLE, SUSPENDED o RUNNING
    • Cuando el sink estaba en SUSPENDED, los parlantes permanecían en silencio
    • Cuando estaba en IDLE o RUNNING, podía haber ruido blanco aunque no se reprodujera sonido real
  • En /etc/pulse/default.pa y /etc/pulse/system.pa estaba cargado module-suspend-on-idle
    • Según la configuración, el sink de audio debería detenerse automáticamente tras 10 segundos de inactividad
    • Pero en algunas situaciones el sink no pasaba a IDLE, así que tampoco llegaba a SUSPENDED

Por qué el audio inactivo consume energía

  • module-suspend-on-idle desconecta en el backend los sinks y sources que no están conectados a ningún stream durante cierto tiempo
  • El efecto principal es el ahorro de energía
    • Si PulseAudio sigue enviando datos vacíos a la tarjeta de sonido incluso en reposo, ALSA usa más ciclos de CPU
    • Si no se planea mantener un stream siempre activo, conviene usar un temporizador corto para ahorrar energía

La causa se redujo a pestañas de Firefox y sitios web

  • Cada vez que se escuchaba ruido blanco, se revisaba con pactl list sink-inputs qué programa estaba usando el sink de audio
  • La causa siempre era Firefox
    • Entre las pestañas abiertas no había ninguna que debiera estar reproduciendo sonido real
    • Tampoco había videos silenciados
  • Se añadió un pequeño script a la barra de estado de i3 para que apareciera una marca roja cuando el sink de audio pasara a RUNNING
  • Al principio, parecía que la causa eran los sonidos de notificación de outlook.office.com, que estaba abierto como pestaña fijada
    • Al recibir un correo, empezaba el ruido blanco
    • No se detenía hasta recargar la pestaña o reiniciar Firefox
  • Después se confirmó el mismo fenómeno en otros sitios web
    • En x.com, el ruido empezaba apenas se hacía clic en cualquier parte
    • En translate.google.com, el ruido también aparecía al escuchar la voz de una traducción
    • La app web de Discord mostraba el mismo efecto con solo dejarla abierta

Resultados de medición de CPU y consumo eléctrico

  • Cuando no había ruido blanco, el uso de CPU de pulseaudio se mostraba como 0.0%
  • En el mismo entorno, la medición de consumo solía estar en el rango de 4.2~5.1W
  • Cuando había ruido blanco, el uso de CPU de pulseaudio subía a 4.7%
  • En ese momento, la medición de consumo solía estar en el rango de 5.8~6.7W
  • La diferencia no era “prácticamente nada”, sino un aumento aproximado de 1.5W

WebAudio API y AudioContext

  • En HTML/JavaScript, las formas de reproducir audio se dividen en dos: la etiqueta <audio> y la WebAudio API
  • En casos como Outlook, donde el sonido se reproduce de forma dinámica, se usa la WebAudio API, y para trabajar con audio primero hay que crear un AudioContext
  • El problema es que incluso con solo ejecutar const audioCtx = new AudioContext(); aparece ruido blanco en los parlantes
  • Se ofrece como página de prueba https://editor.43z.one/sqare/i
  • AudioContext.suspend() detiene el avance temporal del contexto de audio y pausa temporalmente el acceso al hardware de audio para reducir el uso de CPU/batería
  • AudioContext.resume() vuelve a iniciar el avance temporal de un contexto de audio detenido

Diferencias entre Firefox y Chrome

  • Muchos sitios web crean un AudioContext aunque no necesiten emitir sonido de inmediato, y luego no lo ponen en suspend
  • Chrome, pasado cierto tiempo, detiene automáticamente el desperdicio de CPU/batería
  • Firefox no se detiene automáticamente y mantiene el estado en el que sigue generando ruido blanco
  • Aunque la causa directa sea el sitio web, queda la queja de que Firefox no protege al usuario frente a este tipo de desperdicio de recursos
  • También existe la sospecha de que, si hay audífonos Bluetooth conectados, después de hacer clic en x.com puede empezar a transmitirse ruido blanco y desperdiciar la batería de los audífonos

Respuesta temporal: AudioContext Suspender

1 comentarios

 
GN⁺ 2025-02-17
Opiniones de Hacker News
  • Esto está planeado y es importante, y lo corregiremos pronto si es posible. Ya se ha postergado demasiado, y lamento que todavía no se haya resuelto. Siempre es una pelea de prioridades, así que es difícil satisfacer a todos a tiempo, pero en mi lista personal de prioridades está bastante arriba.
    Como podrán imaginar, es mucho más complejo que pausar el AudioContext después de cierto tiempo de silencio, pero de todos modos creo que se puede corregir. Otros navegadores ya lo hicieron, y también hay concesiones aceptables.
    Fuente: implementé muchas funciones de esta zona en Firefox y también soy editor del estándar Web Audio API.
    • Espero que no te tomes estas críticas como algo personal. Hace poco hubo un caso en el que un mantenedor de código abierto recibió este tipo de críticas como frustración y terminó explotando bastante.
      La mayoría entiende las circunstancias que se mencionan aquí. Hay mucho por hacer y el tiempo es limitado.
      He visto de primera mano que los desarrolladores de Firefox se esfuerzan más de lo esperado para que sitios muy usados funcionen correctamente para los usuarios. Sé hasta dónde llegan cuando un problema afecta a los usuarios, así que espero que sigan adelante.
    • Quiero ser un usuario que aproveche mejor Firefox, así que me gustaría depurar problemas que encuentre localmente. Necesito orientación sobre por dónde empezar.
  • Que un sitio web abra un contexto de audio sin reproducir nada de verdad probablemente se deba a detección de bots.
    Como cada motor de navegador y sistema operativo implementa el audio de forma distinta, si se reproduce un sonido completamente inaudible y luego se vuelve a grabar mediante la API, se genera una firma.
    Con esa firma se puede comprobar si el navegador está falsificando el user agent, si está en modo headless o si se trata de todo tipo de casos raros que no corresponden a un usuario real comprando un producto.
    https://github.com/fingerprintjs/fingerprintjs/blob/3201a7d6...
    • Parece que el lado de los navegadores/estándares web amplió las API demasiado a lo loco y no pensó lo suficiente en que el mundo las abusaría de esta manera.
    • De hecho, entre los plugins para bots que circulan ya hay algunos que simulan Audio Context para engañar la detección de bots. Es una locura.
    • Ya estoy esperando el día en que Cloudflare adopte esto para obstaculizar aún más la libertad de navegación y desperdiciar ciclos de CPU.
  • Este ruido blanco me estuvo volviendo loco durante mucho tiempo y no podía encontrar la causa en absoluto.
    En la pestaña no aparece el ícono de reproducción, y aunque silencie la pestaña el ruido no se detiene.
    Si silencio Firefox en el mezclador de volumen de Windows, el sonido tampoco se detiene.
    Edición: para usuarios de escritorio, esta extensión en realidad es bastante mala. Es mucho más molesto que el ruido blanco se esté encendiendo y apagando todo el tiempo.
    • Si al silenciar Firefox desde el mezclador de volumen de Windows no se detiene, me parece que esto es un bug en una capa más profunda que Firefox.
    • Uso esa extensión en el escritorio sin problemas. Parece depender de los sitios que visitas. En sitios que reproducen/detienen sonido con frecuencia, creo que conviene desactivar la extensión.
  • Cuando la salida queda inactiva, la señal digital SPDIF pierde sincronización. Al iniciar la reproducción, volver a sincronizar no es instantáneo, y se pierde alrededor del primer segundo de audio.
    Por eso hice un programa propio que mantiene la salida abierta sin enviar datos por la línea, para que la salida no entre en estado inactivo.
    Sin embargo, en el contexto de una laptop no tiene mucho sentido, así que ahí sí es razonable ahorrar energía.
    • Esto era interminablemente molesto cuando usaba un DAC FiiO K3 con una MacBook. Los sonidos del sistema, como las notificaciones, básicamente no se reproducían debido al retraso.
      En el driver de Windows hay una opción para configurar el stream como Always On. Ojalá existiera también en macOS.
    • Antes hice lo mismo con un DAC USB. Aunque simplemente hice que play -qn & se iniciara al iniciar sesión.
  • Creo que esto explica el problema que tenía a veces en Firefox para Android, donde el teléfono consumía 10 GB de datos al azar en un día. La factura del operador salía absurda.
    Parece que un sitio de noticias reproducía audio mientras recargaba anuncios nuevos en bucle, y por el audio la pestaña no entraba en modo de ahorro de energía. Terminé teniendo que cambiarme a Chrome porque seguían llegando cargos de datos inesperados.
  • En macOS también vi antes este mismo fenómeno, o uno muy parecido. No estoy seguro de si el sitio realmente mantenía abierto un contexto de audio o si era un problema interno de Firefox, porque también ocurría en sitios como Youtube, que no usan Web Audio API.
    Es decir, no había ruido blanco, pero sí consumo de energía por audio: https://bugzilla.mozilla.org/show_bug.cgi?id=1821102
    Incluso ahora, en mi Mac no se está reproduciendo nada y coreaudiod usa 20% de CPU. Está arruinando seriamente la duración de la batería, así que estoy pensando en cambiar a otro navegador hasta que se corrija, pero no quiero abandonar Firefox por algo que parece tan menor.
    Actualización: parece ser un bug relacionado, pero distinto.
  • El código que maneja esta pausa en Chromium está aquí:
    https://source.chromium.org/chromium/chromium/src/+/main:med...
    Básicamente, cuando detecta unos 30 segundos de silencio, cambia de un sink respaldado por el dispositivo de audio del sistema operativo a un sink nulo.
    Como referencia, este enfoque usa un reloj distinto al del dispositivo de audio, por lo que hubo algunos reportes de distorsión en ciertos tonos cuando el contexto se usa realmente más tarde. La solución alternativa es que el sitio use la API suspend/resume mencionada en el artículo.
  • No conozco en detalle cómo se implementa internamente audioContext, pero parece incluir muchos elementos bastante inteligentes y dinámicos. Reproducir un sonido de notificación se siente parecido a dibujar un SVG con D3 en vez de usar img href *.svg.
    Me pregunto si existirá algo como un hook de Service Worker que permita registrar cosas simples y repetibles, como un manejador de notificaciones, en una API eficiente de una capa más baja.
  • ¿Se supone que debería oírse algo realmente?
    En Firefox 134.0.1 en MacOS no escucho nada.
    • Yo tampoco escucho sonido, pero si presiono el botón de reproducción de sonido en la página de demo del autor, el consumo de energía aumenta aproximadamente 1 W.
    • En Firefox para Android se escucha un pequeño ruido blanco.
  • Con esto se corrigió el problema de la página principal de https://www.dr.dk/.