Dar control a los usuarios: la API de sesión multimedia

He aquí un escenario. Comienzas una canción de Kendrick Lamar en una de las muchas pestañas abiertas de tu navegador. Te encanta, pero alguien entra en tu espacio y necesitas pausarlo. ¿Qué pestaña es? Los navegadores intentan ayudar un poco con eso. Probablemente puedas silenciar todo el audio del sistema. ¿Pero no sería bueno tener control sobre la reproducción de audio sin necesariamente tener que encontrar el camino de regreso a esa pestaña?

La API Media Session lo hace posible. Proporciona acceso de reproducción multimedia al usuario fuera de la pestaña del navegador donde se está reproduciendo. Si se implementa, estará disponible en varios lugares del dispositivo, incluidos:

  • el área de notificaciones en muchos dispositivos móviles,
  • en otros dispositivos portátiles, y
  • el área del centro multimedia de muchos dispositivos de escritorio.

Además, la API Media Session nos permite controlar la reproducción multimedia con teclas multimedia y asistentes de voz como Siri, Google Assistant, Bixby o Alexa.

La API de sesión de medios

La API Media Session consta principalmente de las dos interfaces siguientes:

  • MediaMetadata
  • MediaSession

La MediaMetadatainterfaz es lo que proporciona datos sobre los medios de reproducción. Es responsable de informarnos el título, el álbum, la obra de arte y el artista del medio (que es Kendrick Lamar en este ejemplo). La MediaSessioninterfaz es la responsable de la funcionalidad de reproducción multimedia.

Antes de profundizar en el tema, deberíamos tomar nota de la detección de funciones. Es una buena práctica comprobar si un navegador admite una función antes de implementarla. Para comprobar si un navegador admite la API de sesión multimedia, tendríamos que incluir lo siguiente en nuestro archivo JavaScript:

if ('mediaSession' in navigator) {  // Our media session api that lets us seek to the beginning of Kendrick Lamar's quot;Alrightquot;}

La interfaz MediaMetadata

El constructor MediaMetadata.MediaMetadata()crea un nuevo MediaMetadataobjeto. Después de crearlo, podemos agregar las siguientes propiedades:

  • MediaMetadata.titleestablece u obtiene el título del medio que se reproduce.
  • MediaMetadata.artistestablece u obtiene el nombre del artista o grupo del medio que se reproduce.
  • MediaMetadata.albumestablece u obtiene el nombre del álbum que contiene el medio en reproducción.
  • MediaMetadata.artworkestablece u obtiene la variedad de imágenes relacionadas con el medio en reproducción.

El valor de la artworkpropiedad del MediaMetadataobjeto es una matriz de MediaImageobjetos. Un MediaImageobjeto contiene detalles que describen una imagen asociada con los medios. Los objetos tienen las tres propiedades siguientes:

  • src: la URL de la imagen
  • sizes: indica el tamaño de la imagen, por lo que no es necesario escalar una imagen
  • type: el tipo MIME de la imagen

Creemos un MediaMetadataobjeto para “Alright” de Kendrick Lamar de su álbum To Pimp a Butterfly.

if ('mediaSession' in navigator) {  navigator.mediaSession.metadata = new MediaMetadata({    title: 'Alright',    artist: 'Kendrick Lamar',    album: 'To Pimp A Butterfly',    artwork: [      { src: 'https://mytechnicalarticle/kendrick-lamar/to-pimp-a-butterfly/alright/96x96', sizes: '96x96', type: 'image/png' },      { src: 'https://mytechnicalarticle/kendrick-lamar/to-pimp-a-butterfly/alright/128x128', sizes: '128x128', type: 'image/png' },      // More sizes, like 192x192, 256x256, 384x384, and 512x512    ]  });}

La interfaz MediaSession

Como se indicó anteriormente, esto es lo que permite al usuario controlar la reproducción de los medios. Podemos realizar las siguientes acciones en el medio de reproducción a través de esta interfaz:

  • play: reproducir los medios
  • pause: pausar los medios
  • previoustrack: cambia a la pista anterior
  • nexttrack: cambia a la siguiente pista
  • seekbackward: busca hacia atrás desde la posición actual, unos segundos
  • seekforward: busca hacia adelante desde la posición actual, unos segundos
  • seekto: busca a un tiempo específico desde la posición actual
  • stop: detener la reproducción multimedia
  • skipad: pasa por alto el anuncio que se reproduce, si lo hay

El MediaSessionActiontipo enumerado hace que estas acciones estén disponibles como tipos de cadena. Para admitir cualquiera de estas acciones, tenemos que usar el MediaSessionmétodo setActionHandler()para definir un controlador para esa acción. El método realiza la acción y una devolución de llamada que se llama cuando el usuario invoca la acción. Profundicemos un poco más para comprenderlo mejor.

Para configurar controladores para las acciones playy pause, incluimos lo siguiente en nuestro archivo JavaScript:

let alright = new HTMLAudioElement();if ('mediaSession' in navigator) {  navigator.mediaSession.setActionHandler('play', () = {    alright.play();  });  navigator.mediaSession.setActionHandler('pause', () = {    alright.pause();  });}

Aquí configuramos la pista para que se reproduzca cuando el usuario la reproduzca y se detenga cuando el usuario la pausa a través de la interfaz multimedia.

Para las acciones previoustracky nexttrack, incluimos lo siguiente:

let u = new HTMLAudioElement();let forSaleInterlude = new HTMLAudioElement();if ('mediaSession' in navigator) {  navigator.mediaSession.setActionHandler('previoustrack', () = {    u.play();  });  navigator.mediaSession.setActionHandler('nexttrack', () = {    forSaleInterlude.play();  });}

Puede que esto no se explique por sí solo si no eres un gran fanático de Kendrick Lamar, pero con suerte entenderás lo esencial. Cuando el usuario quiera reproducir la pista anterior, configuramos la pista anterior para que se reproduzca. Cuando es la siguiente pista, es la siguiente pista.

Para implementar las acciones seekbackwardy seekforward, incluimos lo siguiente:

if ('mediaSession' in navigator) {  navigator.mediaSession.setActionHandler('seekbackward', (details) = {    alright.currentTime = alright.currentTime - (details.seekOffset || 10);  });  navigator.mediaSession.setActionHandler('seekforward', (details) = {    alright.currentTime = alright.currentTime + (details.seekOffset || 10);  });}

Dado que no consideramos que nada de esto se explique por sí solo, me gustaría dar una explicación concisa sobre las acciones seekbackwardy . seekforwardLos controladores para ambas acciones, seekbackwardy seekforward, se activan, como sus nombres lo indican, cuando el usuario quiere buscar hacia atrás o hacia adelante unos pocos segundos. El MediaSessionActionDetailsdiccionario nos proporciona los “pocos segundos” en una propiedad seekOffset. Sin embargo, la seekOffsetpropiedad no siempre está presente porque no todos los agentes de usuario actúan de la misma manera. Cuando no esté presente, debemos configurar la pista para que busque hacia atrás o hacia adelante “unos cuantos segundos” que tenga sentido para nosotros. Por eso usamos 10 segundos porque son bastantes. En pocas palabras, configuramos la pista para que se busque por seekOffsetsegundos si se proporciona. Si no se proporciona, buscamos por 10 segundos.

Para agregar la seektofuncionalidad a nuestra API de sesión de medios, incluimos el siguiente fragmento:

if ('mediaSession' in navigator) {  navigator.mediaSession.setActionHandler('seekto', (details) = {    if (details.fastSeek  'fastSeek' in alright) {      alright.fastSeek(details.seekTime);      return;    }    alright.currentTime = details.seekTime;  });}

Aquí, el MediaSessionActionDetailsdiccionario proporciona las propiedades fastSeeky seekTime. fastSeekBásicamente, la búsqueda se realiza rápidamente (como avance rápido o rebobinado), mientras que seekTimees el momento en que la pista debe buscar. Si bien fastSeekes una propiedad opcional, el MediaSessionActionDetailsdiccionario siempre proporciona la seekTimepropiedad para el seektocontrolador de acciones. Básicamente, configuramos el seguimiento fastSeekcuando seekTimela propiedad está disponible y el usuario busca rápidamente, mientras que simplemente lo configuramos seekTimecuando el usuario solo busca en un tiempo específico.

Aunque no sé por qué uno querría detener una canción de Kendrick, no estaría más describir el stopcontrolador de acciones de la MediaSessioninterfaz:

if ('mediaSession' in navigator) {  navigator.mediaSession.setActionHandler('stop', () = {    alright.pause();    alright.currentTime = 0;  });} 

El usuario invoca el skipadcontrolador de acción (como en “omitir anuncio” en lugar de “ski pad”) cuando se reproduce un anuncio y quiere omitirlo para poder continuar escuchando la pista “A lright” de Kendrick Lamar. Si soy honesto, los detalles completos del skipadcontrolador de están fuera del alcance de mi comprensión de “API de sesión de medios”. Por lo tanto, probablemente deberías buscarlo por tu cuenta después de leer este artículo, si realmente quieres implementarlo.

terminando

Deberíamos tomar nota de algo. Siempre que el usuario reproduzca la pista, busque o cambie la velocidad de reproducción, se supone que debemos actualizar el estado de posición en la interfaz proporcionada por la API de sesión de medios. Lo que usamos para implementar esto es el setPositionState()método del mediaSessionobjeto, como se muestra a continuación:

if ('mediaSession' in navigator) {  navigator.mediaSession.setPositionState({    duration: alright.duration,    playbackRate: alright.playbackRate,    position: alright.currentTime  });}

Además, me gustaría recordarles que no todos los navegadores de los usuarios soportan todas las acciones. Por lo tanto, se recomienda configurar los controladores de acciones en un try...catchbloque, como se muestra a continuación:

const actionsAndHandlers = [  ['play', () = { /*...*/ }],  ['pause', () = { /*...*/ }],  ['previoustrack', () = { /*...*/ }],  ['nexttrack', () = { /*...*/ }],  ['seekbackward', (details) = { /*...*/ }],  ['seekforward', (details) = { /*...*/ }],  ['seekto', (details) = { /*...*/ }],  ['stop', () = { /*...*/ }]] for (const [action, handler] of actionsAndHandlers) {  try {    navigator.mediaSession.setActionHandler(action, handler);  } catch (error) {    console.log(`The media session action, ${action}, is not supported`);  }}

Poniendo todo lo que hemos hecho, tendríamos lo siguiente:

let alright = new HTMLAudioElement();let u = new HTMLAudioElement();let forSaleInterlude = new HTMLAudioElement();const updatePositionState = () = {  navigator.mediaSession.setPositionState({    duration: alright.duration,    playbackRate: alright.playbackRate,    position: alright.currentTime  });} const actionsAndHandlers = [  ['play', () = {    alright.play();    updatePositionState();  }],  ['pause', () = { alright.pause(); }],  ['previoustrack', () = { u.play(); }],  ['nexttrack', () = { forSaleInterlude.play(); }],  ['seekbackward', (details) = {    alright.currentTime = alright.currentTime - (details.seekOffset || 10);    updatePositionState();  }],  ['seekforward', (details) = {    alright.currentTime = alright.currentTime + (details.seekOffset || 10);    updatePositionState();  }],  ['seekto', (details) = {    if (details.fastSeek  'fastSeek' in alright) {      alright.fastSeek(details.seekTime);      updatePositionState();      return;    }    alright.currentTime = details.seekTime;    updatePositionState();  }],  ['stop', () = {    alright.pause();    alright.currentTime = 0;  }],] if ( 'mediaSession' in navigator ) {  navigator.mediaSession.metadata = new MediaMetadata({    title: 'Alright',    artist: 'Kendrick Lamar',    album: 'To Pimp A Butterfly',    artwork: [      { src: 'https://mytechnicalarticle/kendrick-lamar/to-pimp-a-butterfly/alright/96x96', sizes: '96x96', type: 'image/png' },      { src: 'https://mytechnicalarticle/kendrick-lamar/to-pimp-a-butterfly/alright/128x128', sizes: '128x128', type: 'image/png' },      // More sizes, like 192x192, 256x256, 384x384, and 512x512    ]  });   for (const [action, handler] of actionsAndHandlers) {    try {      navigator.mediaSession.setActionHandler(action, handler);    } catch (error) {      console.log(`The media session action, ${action}, is not supported`);    }  }}

Aquí hay una demostración de la API:

Implementé seis de las acciones. No dudes en probar el resto durante tu tiempo libre.

Si ve el Pen en su dispositivo móvil, observe cómo aparece en su área de notificación.

Si su reloj inteligente está emparejado con su dispositivo, eche un vistazo.

Si tiene el P en Chrome en el escritorio, navegue hasta el centro de medios y juegue con los botones multimedia allí. La demostración incluso tiene varias pistas, por lo que puedes experimentar avanzando y retrocediendo entre las pistas.

Si llegué hasta aquí (o no), gracias por leer y, por favor, en la próxima aplicación que cree con funcionalidad multimedia, implemente esta API.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir