He aquí un escenario. Comienzas una pista de Kendrick Lamar en una de las muchas pestañas abiertas del 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 pueda silenciar todo el audio del sistema. Pero, ¿no sería bueno tener realmente el control sobre la reproducción de audio sin necesidad de encontrar el camino de regreso a esa pestaña?
La API de Media Session lo hace posible. Le da acceso a la reproducción de medios al usuario fuera de la pestaña del navegador donde se está reproduciendo. Si se implementa, estará disponible en varios lugares del dispositivo, que incluyen:
- el área de notificaciones en muchos dispositivos móviles,
- en otros wearables, y
- el área del centro de medios de muchos dispositivos de escritorio.
Además, la API de sesión de medios nos permite controlar la reproducción de medios con teclas de medios y asistentes de voz como Siri, Google Assistant, Bixby o Alexa.
La API de sesión de medios
La API de Media Session consta principalmente de las dos siguientes interfaces:
MediaMetadata
MediaSession
El MediaMetadata
La interfaz 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). El MediaSession
La interfaz es la responsable de la funcionalidad de reproducción de medios.
Antes de profundizar en el tema, deberíamos tomar nota de la detección de características. Es una buena práctica comprobar si un navegador admite una función antes de implementarla. Para verificar si un navegador es compatible con la API de sesión de medios, 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 "Alright"
}
La interfaz MediaMetadata
El constructor MediaMetadata.MediaMetadata()
crea un nuevo MediaMetadata
objeto. Después de crearlo, podemos agregar las siguientes propiedades:
MediaMetadata.title
establece u obtiene el título de los medios que se están reproduciendo.MediaMetadata.artist
establece u obtiene el nombre del artista o grupo del medio que se reproduce.MediaMetadata.album
establece u obtiene el nombre del álbum que contiene el contenido multimedia que se está reproduciendo.MediaMetadata.artwork
establece u obtiene el conjunto de imágenes relacionadas con la reproducción multimedia.
El valor de la artwork
propiedad de la MediaMetadata
el objeto es una matriz de MediaImage
objetos. A MediaImage
El objeto contiene detalles que describen una imagen asociada con los medios. Los objetos tienen las tres propiedades siguientes:
src
: la URL de la imagensizes
: indica el tamaño de la imagen para que no sea necesario escalar una imagentype
: el tipo MIME de la imagen
Vamos a crear un MediaMetadata
Objeto 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 de 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 los medios de reproducción a través de esta interfaz:
play
: reproducir los mediospause
: pausa los mediosprevioustrack
: cambia a la pista anteriornexttrack
: cambia a la siguiente pistaseekbackward
: buscar hacia atrás desde la posición actual, unos segundosseekforward
: buscar hacia adelante desde la posición actual, unos segundosseekto
: busca un tiempo específico desde la posición actualstop
: detiene la reproducción multimediaskipad
: omite el anuncio que se está reproduciendo, si lo hubiera
El MediaSessionAction
El tipo enumerado hace que estas acciones estén disponibles como tipos de cadena. Para respaldar cualquiera de estas acciones, tenemos que utilizar el MediaSession
‘s setActionHandler()
método 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. Hagamos una inmersión no demasiado profunda para comprenderlo mejor.
Para establecer controladores para el play
y pause
acciones, 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 tocar cuando el usuario lo juega y pausa cuando el usuario lo pausa a través de la interfaz de medios.
Para el previoustrack
y nexttrack
acciones, incluimos las siguientes:
let u = new HTMLAudioElement();
let forSaleInterlude = new HTMLAudioElement();
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('previoustrack', () => {
u.play();
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
forSaleInterlude.play();
});
}
Es posible que esto no se explique por sí mismo si no eres un gran fanático de Kendrick Lamar, pero con suerte, entiendes la esencia. Cuando el usuario quiere reproducir la pista anterior, configuramos la pista anterior para que se reproduzca. Cuando es la siguiente pista, es la siguiente pista.
Para implementar el seekbackward
y seekforward
acciones, incluimos las siguientes:
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 considero que nada de esto se explique por sí mismo, me gustaría dar una explicación concisa sobre el seekbackward
y seekforward
comportamiento. Los manejadores de ambas acciones, seekbackward
y seekforward
, se disparan, como sus nombres implican, cuando el usuario desea buscar hacia atrás o hacia adelante unos pocos segundos. El MediaSessionActionDetails
El diccionario nos proporciona “pocos segundos” en una propiedad, seekOffset
. sin embargo, el seekOffset
La propiedad 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 por un “número de segundos” que tenga sentido para nosotros. Por lo tanto, usamos 10 segundos porque son bastantes. En pocas palabras, establecemos el camino para buscar por seekOffset
segundos si se proporciona. Si no se proporciona, buscamos por 10 segundos.
Para agregar el seekto
funcionalidad 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 MediaSessionActionDetails
diccionario proporciona el fastSeek
y seekTime
propiedades. fastSeek
Básicamente, la búsqueda se realiza rápidamente (como adelantar o rebobinar) mientras seekTime
es el tiempo que debe buscar la pista. Mientras fastSeek
es una propiedad opcional, el MediaSessionActionDetails
diccionario siempre proporciona el seekTime
propiedad para el seekto
manejador de acciones. Así que, fundamentalmente, fijamos la pista para fastSeek
al seekTime
cuando la propiedad está disponible y el usuario busca rápidamente, mientras que simplemente la configuramos en el seekTime
cuando el usuario solo busca un tiempo específico.
Aunque no sabría por qué uno querría detener una canción de Kendrick, no estaría de más describir la stop
manejador de acciones del MediaSession
interfaz:
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('stop', () => {
alright.pause();
alright.currentTime = 0;
});
}
El usuario invoca el skipad
(como en, “omitir anuncio” en lugar de “plataforma de esquí”) controlador de acción cuando se reproduce un anuncio y quieren omitirlo para poder seguir escuchando la pista “Alright” de Kendrick Lamar. Si soy honesto, los detalles completos del skipad
El controlador de acciones está fuera del alcance de mi comprensión de la “API de sesión de medios”. Por lo tanto, probablemente debería buscarlo por su cuenta después de leer este artículo, si realmente desea implementarlo.
Terminando
Deberíamos tomar nota de algo. Siempre que el usuario reproduce la pista, busca o cambia 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 mediaSession
objeto, como en el siguiente:
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 admitirían todas las acciones. Por lo tanto, se recomienda configurar los controladores de acción en un try...catch
bloque, como en el siguiente:
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 dude en probar el resto durante su tiempo libre.
Si ve el lápiz en su dispositivo móvil, observe cómo aparece en su área de notificación.
Si tu reloj inteligente está emparejado con tu dispositivo, échale un vistazo.
Si ve el lápiz en Chrome en el escritorio, navegue hasta el centro de medios y juegue con los botones de medios allí. La demostración incluso tiene varias pistas, por lo que puedes experimentar moviéndote hacia adelante o hacia atrás a través de las pistas.
Si llegó hasta aquí (o no), gracias por leer y, por favor, en la próxima aplicación que cree con funcionalidad multimedia, implemente esta API.