Audio web, política de reproducción automática y juegos

Tom Greenaway
Hongchan Choi

En septiembre de 2017, anunciamos un cambio que realizaría próximamente en cómo se manejaría el audio con la política de comportamiento de reproducción automática en Chrome. El cambio de política se lanzó con la versión estable de Chrome 66 en mayo de 2018.

Luego de los comentarios de la comunidad de desarrollo de Web Audio, retrasamos el lanzamiento de la sección Web Audio de la política de reproducción automática para darles a los desarrolladores más tiempo para actualizar sus sitios web. También realizamos algunos cambios en la implementación de la política de Web Audio que reducirán la cantidad de sitios web que deben ajustar su código, especialmente los juegos web, y, por lo tanto, brindarán una mejor experiencia para nuestros usuarios.

Este cambio de política está programado para lanzarse en Chrome 71 en diciembre de 2018.

¿Qué hace exactamente el cambio de política?

La reproducción automática es el nombre que se le da a un contenido que se reproduce inmediatamente cuando se carga una página web. En el caso de los sitios web que debían poder reproducir automáticamente su contenido, este cambio impedirá la reproducción de forma predeterminada. En la mayoría de los casos, la reproducción se reanudará, pero, en otros, será necesario hacer un pequeño ajuste en el código. Específicamente, los desarrolladores deben agregar un código que reanude su contenido si el usuario interactúa con la página web.

Sin embargo, si el usuario llega a una página con contenido de reproducción automática y navegó a esa página desde una página del mismo origen, ese contenido nunca se bloqueará. Lee nuestra entrada de blog anterior sobre la política de reproducción automática para obtener ejemplos más detallados.

Además, agregamos una heurística para aprender del comportamiento anterior de los usuarios con respecto a los sitios web que reproducen audio automáticamente. Detectamos si los usuarios dejan de reproducir el audio con frecuencia durante más de 7 segundos durante la mayoría de sus visitas a un sitio web. Habilitamos la reproducción automática para ese sitio web.

Lo hacemos con un índice que se almacena localmente por perfil de Chrome en un dispositivo. No se sincroniza entre dispositivos y solo se comparte como parte de las estadísticas anónimas de los usuarios. A este índice lo llamamos Índice de participación de medios (MEI) y puede verlo a través de chrome://media-engagement.

MEI lleva un registro de cuántas visitas a un sitio incluyen la reproducción de audio que dura más de 7 segundos. Según el MEI de un usuario, creemos que podemos comprender si un usuario espera audio de un sitio web en particular y anticipar la intención del usuario en el futuro.

Si el usuario suele permitir que el dominio de un sitio web reproduzca audio durante más de 7 segundos, supondremos que en el futuro espera que este sitio web tenga derecho a reproducir audio automáticamente. Por lo tanto, concedemos a ese sitio web el derecho a reproducir audio automáticamente sin que el usuario tenga que interactuar con una pestaña de ese dominio.

Sin embargo, este derecho no está garantizado de forma indefinida. Si el comportamiento del usuario cambia (p.ej., al detener la reproducción de audio o cerrar la pestaña dentro del umbral de 7 segundos después de varias visitas), eliminamos el derecho del sitio web a la reproducción automática.

Tanto el uso de elementos HTML de medios (video y audio) como el audio web (objetos AudioContext con instancias de JavaScript) contribuirán al MEI. Como preparación para el lanzamiento de esta política, el comportamiento de los usuarios en relación con Web Audio comenzará a contribuir al MEI a partir de Chrome 70. Esto garantizará que ya podamos anticipar la intención deseada del usuario con respecto a la reproducción automática y los sitios web que visita con frecuencia.

Ten en cuenta que los iframes solo pueden reproducir automáticamente sin interacción del usuario si la página web superior que incorpora el iframe extiende ese derecho al iframe determinado.

Retrasando el cambio para apoyar a la comunidad

La comunidad de desarrolladores de Web Audio, en particular los desarrolladores de juegos web y los desarrolladores de WebRTC de esta comunidad, se dieron cuenta de cuando este cambio apareció en el canal estable de Chrome.

Los comentarios de la comunidad indican que muchos juegos web y experiencias de audio web se verían afectados negativamente por este cambio. Específicamente, muchos sitios que no se actualizaron ya no reproducirían audio a los usuarios. Como resultado, nuestro equipo decidió que valía la pena retrasar este cambio para darles a los desarrolladores de audio web más tiempo para actualizar sus sitios web.

Además, dedicamos este tiempo a lo siguiente:

  • Evalúa seriamente si este cambio en la política fue la mejor forma de proceder o no.
  • Descubre cómo podemos ayudar a reducir la cantidad de sitios web con audio que se verían afectados.

En el primero, decidimos que el cambio en la política era realmente necesario para mejorar la experiencia de la mayoría de nuestros usuarios. En la siguiente sección de este artículo, puede leer más detalles sobre el problema que resuelve el cambio de política.

Para la segunda, realizamos un ajuste en nuestra implementación de Web Audio que reducirá la cantidad de sitios web afectados originalmente. De los sitios que sabíamos que estaban rotos por el cambio (muchos de los cuales la comunidad de desarrollo de juegos web proporcionó como ejemplo), este ajuste significó que más del 80% de ellos funcionarían automáticamente. Nuestro análisis y pruebas de estos sitios de ejemplo se pueden consultar aquí. Este nuevo ajuste se describe con más detalle a continuación.

También realizamos un cambio para admitir aplicaciones WebRTC: mientras haya una sesión de captura activa, se permitirá la reproducción automática.

¿Qué problema pretende resolver este cambio de comportamiento?

Históricamente, los navegadores no han ayudado al usuario a administrar el sonido. Cuando los usuarios abren una página web y reciben un sonido que no esperaban o no querían, la experiencia del usuario será poco satisfactoria. Esta mala experiencia del usuario es el problema que estamos tratando de resolver. El ruido no deseado es el motivo principal por el que los usuarios no desean que su navegador reproduzca contenido automáticamente.

Sin embargo, a veces los usuarios quieren que el contenido se reproduzca automáticamente y, posteriormente, una cantidad significativa de este tipo de reproducciones en Chrome.

Por lo tanto, creemos que, al aprender de los usuarios, y anticipar su intención según el sitio web, podemos crear la mejor experiencia del usuario. Si los usuarios tienden a dejar que el contenido se reproduzca desde un sitio web, lo reproduciremos automáticamente desde ese sitio en el futuro. Por el contrario, si los usuarios tienden a detener el contenido de reproducción automática de un sitio web determinado, de forma predeterminada impediremos la reproducción automática para ese contenido.

Una de las propuestas que presentó la comunidad fue silenciar el audio de una pestaña en lugar de pausar la reproducción automática. Sin embargo, creemos que es mejor detener la experiencia de reproducción automática para que el sitio web detecte que esta se bloqueó y permita que el desarrollador del sitio web reaccione ante esto. Por ejemplo, si bien es posible que algunos desarrolladores simplemente quieran silenciar el audio, otros podrían preferir que su contenido de audio se detenga hasta que el usuario interactúe activamente con él; de lo contrario, podría perder parte de la experiencia de audio.

Nuevos ajustes para ayudar a los desarrolladores de juegos web

La forma más común en que los desarrolladores usan la API de Web Audio es creando dos tipos de objetos para reproducir audio:

Los desarrolladores de audio web crearán un objeto AudioContext para reproducir audio. Para reanudar el audio después de que la política de reproducción automática haya suspendido automáticamente su AudioContext, deben llamar a la función reanuda() en este objeto después de que el usuario interactúe con la pestaña:

    const context = new AudioContext();

    // Setup an audio graph with AudioNodes and schedule playback.
    ...

    // Resume AudioContext playback when user clicks a button on the page.
    document.querySelector('button').addEventListener('click', function() {
      context.resume().then(() => {
        console.log('AudioContext playback resumed successfully');
      });
    });

Hay muchas interfaces que heredan contenido de AudioNode, una de las cuales es la interfaz AudioScheduledSourceNode. Los AudioNodes que implementan la interfaz AudioScheduledSourceNode se suelen conocer como nodos de origen (por ejemplo, AudioBufferSourceNode, ConstantSourceNode y OscillatorNode). Los nodos de origen implementan un método start().

Por lo general, los nodos fuente representan fragmentos de audio individuales que se reproducen en los juegos, por ejemplo, el sonido que se reproduce cuando un jugador recolecta una moneda o la música de fondo que se reproduce en el escenario actual. Es muy probable que los desarrolladores de juegos llamen a la función start() en los nodos de origen cada vez que alguno de estos sonidos sea necesario para el juego.

Una vez que reconocimos este patrón común en los juegos web, decidimos ajustar nuestra implementación de la siguiente manera:

Un AudioContext se reanudará automáticamente cuando se cumplan dos condiciones:

  • El usuario interactuó con una página.
  • Se llama al método start() de un nodo de origen.

Debido a este cambio, la mayoría de los juegos web ahora reanudarán su audio cuando el usuario comience a jugar.

Llevamos la Web hacia adelante

Para avanzar con la plataforma web, a veces es necesario realizar cambios que pueden dañar la compatibilidad. Lamentablemente, la reproducción automática de audio es compleja y entra en esta categoría de cambio. Sin embargo, hacer este cambio es fundamental para garantizar que la Web no se estanca ni pierda su innovación.

No obstante, reconocemos que aplicar correcciones a sitios web no siempre es factible a corto plazo por varios motivos:

  • Es posible que los desarrolladores web se enfoquen en un nuevo proyecto y que el mantenimiento de un sitio web antiguo no sea posible de inmediato.
  • Es posible que los portales de juegos web no tengan control sobre la implementación de los juegos en su catálogo, por lo que actualizar cientos (o miles) de juegos puede consumir mucho tiempo y dinero para los publicadores.
  • Es posible que algunos sitios web simplemente sean muy antiguos y, por alguna razón, ya no reciban mantenimiento, pero todavía se alojen con fines históricos.

A continuación, se muestra un breve fragmento de código JavaScript que intercepta la creación de nuevos objetos AudioContext y activa automáticamente la función de reanudación de esos objetos cuando el usuario realiza varias interacciones. Este código debe ejecutarse antes de la creación de cualquier objeto AudioContext en tu página web; por ejemplo, puedes agregar este código a la etiqueta de tu página web:

(function () {
  // An array of all contexts to resume on the page
  const audioContextList = [];

  // An array of various user interaction events we should listen for
  const userInputEventNames = [
    'click',
    'contextmenu',
    'auxclick',
    'dblclick',
    'mousedown',
    'mouseup',
    'pointerup',
    'touchend',
    'keydown',
    'keyup',
  ];

  // A proxy object to intercept AudioContexts and
  // add them to the array for tracking and resuming later
  self.AudioContext = new Proxy(self.AudioContext, {
    construct(target, args) {
      const result = new target(...args);
      audioContextList.push(result);
      return result;
    },
  });

  // To resume all AudioContexts being tracked
  function resumeAllContexts(event) {
    let count = 0;

    audioContextList.forEach(context => {
      if (context.state !== 'running') {
        context.resume();
      } else {
        count++;
      }
    });

    // If all the AudioContexts have now resumed then we
    // unbind all the event listeners from the page to prevent
    // unnecessary resume attempts
    if (count == audioContextList.length) {
      userInputEventNames.forEach(eventName => {
        document.removeEventListener(eventName, resumeAllContexts);
      });
    }
  }

  // We bind the resume function for each user interaction
  // event on the page
  userInputEventNames.forEach(eventName => {
    document.addEventListener(eventName, resumeAllContexts);
  });
})();

Ten en cuenta que este fragmento de código no ayudará a reanudar AudioContexts de los que se haya creado una instancia dentro de un iframe, a menos que este fragmento de código esté incluido dentro del alcance del contenido del iframe.

Servicio mejor a nuestros usuarios

Para acompañar el cambio de política, también presentamos un mecanismo para que los usuarios inhabiliten la política de reproducción automática a fin de abarcar los casos en los que el aprendizaje automático no funciona como se espera o para los sitios web que el cambio deja inutilizables. Este cambio se lanzará con la nueva política en Chrome 71 y se puede encontrar en la configuración de sonido. Los sitios en los que el usuario desea permitir la reproducción automática se pueden agregar a la lista de entidades permitidas.

¿Cómo se crea el MEI para los usuarios nuevos?

Como se mencionó anteriormente, creamos el MEI automáticamente con el tiempo en función del comportamiento del usuario para anticipar su intención deseada en relación con un sitio web determinado con contenido de reproducción automática. En este índice, cada sitio web tiene una puntuación entre cero y uno. Las puntuaciones más altas indican que el usuario espera que se reproduzca contenido desde ese sitio web.

Sin embargo, en el caso de los perfiles de usuario nuevos o si un usuario borra sus datos de navegación, en lugar de bloquear la reproducción automática en todas partes, se usa una lista de origen basada en puntuaciones de MEI agregadas por usuarios anonimizadas para determinar qué sitios web pueden reproducir automáticamente. Estos datos solo determinan el estado inicial del MEI cuando se crea el perfil de usuario. A medida que el usuario explora la Web e interactúa con sitios web con contenido de reproducción automática, su MEI personal anula la configuración predeterminada.

La lista de sitios presemilla se genera mediante algoritmos, en lugar de seleccionarse manualmente, y se puede incluir cualquier sitio web. Los sitios se agregan a la lista si una cantidad suficiente de usuarios que lo visitan permiten la reproducción automática en ellos. Este umbral se basa en porcentajes, de modo que no favorece los sitios más grandes.

Buscando el equilibrio

Publicamos nueva documentación para brindar más información sobre nuestro proceso de toma de decisiones y la lógica del diseño que respalda esta política. Además de documentación nueva sobre cómo funciona la lista de sitios preseleccionados.

Siempre priorizamos a nuestros usuarios, pero tampoco queremos decepcionar a la comunidad de desarrollo web. A veces, ser el navegador implica que estos dos objetivos deben equilibrarse cuidadosamente. Creemos que, con nuestros ajustes a la implementación de la política y el tiempo adicional que asignamos a los desarrolladores de audio web para actualizar su código, lograremos ese equilibrio con Chrome 71.

Comentarios