Cómo realizar la integración con las teclas multimedia de hardware, personalizar las notificaciones multimedia y mucho más
Para permitir que los usuarios sepan qué se está reproduciendo en su navegador y controlarlo sin volver a la página que lo inició, se introdujo la API de Media Session. Permite que los desarrolladores web personalicen esta experiencia a través de metadatos en notificaciones multimedia personalizadas, eventos multimedia, como reproducir, pausar, saltar, cambiar de pista, y eventos de videoconferencia, como silenciar o activar el micrófono, encender o apagar la cámara y colgar. Estas personalizaciones están disponibles en varios contextos, como centros multimedia para computadoras de escritorio, notificaciones multimedia en dispositivos móviles y hasta en wearables. Describiré estas personalizaciones en este artículo.
Información acerca de la API de Media Session
La API de Media session proporciona varios beneficios y capacidades:
- Se admiten las teclas multimedia de hardware.
- Las notificaciones multimedia se personalizan en dispositivos móviles, computadoras y dispositivos wearable vinculados.
- El centro de contenido multimedia está disponible en computadoras.
- Los controles multimedia de la pantalla de bloqueo están disponibles en ChromeOS y dispositivos móviles.
- Los controles de ventana de pantalla en pantalla están disponibles para reproducir audio, videoconferencias y presentar diapositivas.
- La integración de Asistente en dispositivos móviles está disponible.
A continuación, se incluyen algunos ejemplos para ilustrar estos puntos.
Ejemplo 1: Si los usuarios presionan la tecla multimedia "pista siguiente" del teclado, los desarrolladores web pueden controlar esta acción del usuario, ya sea que el navegador esté en primer o segundo plano.
Ejemplo 2: Si los usuarios escuchan un podcast en la Web mientras la pantalla del dispositivo está bloqueada, pueden presionar el ícono de "buscar hacia atrás" en los controles multimedia de la pantalla de bloqueo para que los desarrolladores web retrocedan el tiempo de reproducción unos segundos.
Ejemplo 3: Si los usuarios tienen pestañas que reproducen audio, pueden detener fácilmente la reproducción desde el centro multimedia en computadoras de escritorio para que los desarrolladores web tengan la oportunidad de borrar su estado.
Ejemplo 4: Si los usuarios están en una videollamada, pueden presionar el control "Activar/desactivar micrófono" en la ventana de pantalla en pantalla para evitar que el sitio web reciba datos del micrófono.
Todo esto se hace a través de dos interfaces diferentes: MediaSession
y MediaMetadata
. El primero permite que los usuarios controlen lo que se está reproduciendo. La segunda es cómo le indicas a MediaSession
qué se debe controlar.
A modo de ejemplo, en la siguiente imagen, se muestra cómo estas interfaces se relacionan con controles multimedia específicos, en este caso, una notificación multimedia en dispositivos móviles.
Informa a los usuarios qué se está reproduciendo
Cuando un sitio web reproduce audio o video, los usuarios reciben notificaciones multimedia automáticamente, ya sea en la bandeja de notificaciones en dispositivos móviles o en el centro multimedia en computadoras de escritorio. El navegador hace todo lo posible para mostrar la información adecuada mediante el título del documento y la imagen de ícono más grande que encuentre. Con la API de Media Session, es posible personalizar la notificación multimedia con metadatos multimedia más enriquecidos, como el título, el nombre del artista, el nombre del álbum y el material gráfico, como se muestra a continuación.
Chrome solicita el enfoque de audio "completo" para mostrar notificaciones multimedia solo cuando la duración del contenido multimedia es de al menos 5 segundos. Esto garantiza que los sonidos imprevistos, como los timbres, no muestren notificaciones.
// After media (video or audio) starts playing
await document.querySelector("video").play();
if ("mediaSession" in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
artist: 'Rick Astley',
album: 'Whenever You Need Somebody',
artwork: [
{ src: 'https://via.placeholder.com/96', sizes: '96x96', type: 'image/png' },
{ src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
{ src: 'https://via.placeholder.com/192', sizes: '192x192', type: 'image/png' },
{ src: 'https://via.placeholder.com/256', sizes: '256x256', type: 'image/png' },
{ src: 'https://via.placeholder.com/384', sizes: '384x384', type: 'image/png' },
{ src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
]
});
// TODO: Update playback state.
}
Cuando finaliza la reproducción, no es necesario “liberar” la sesión multimedia, ya que la notificación desaparecerá automáticamente. Sin embargo, ten en cuenta que se usará navigator.mediaSession.metadata
cuando comience la próxima reproducción. Por este motivo, es importante actualizarlo cuando cambia la fuente de reproducción multimedia para garantizar que se muestre la información relevante en la notificación multimedia.
Hay algunos aspectos que debes tener en cuenta sobre los metadatos de contenido multimedia.
- El array de material gráfico de notificaciones admite URLs de datos y URLs de BLOB.
- Si no se define ningún material gráfico y hay una imagen de ícono (especificada con
<link rel=icon>
) de un tamaño adecuado, las notificaciones multimedia la usarán. - El tamaño objetivo del material gráfico de las notificaciones en Chrome para Android es
512x512
. Para dispositivos de baja gama, es256x256
. - El atributo
title
del elemento HTML multimedia se usa en el widget de macOS "Reproduciendo ahora". - Si el recurso multimedia está incorporado (por ejemplo, en un iframe), la información de la API de Media Session se debe configurar desde el contexto incorporado. Consulta el siguiente fragmento.
<iframe id="iframe">
<video>...</video>
</iframe>
<script>
iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
...
});
</script>
También puedes agregar información de capítulos individuales, como el título de la sección, su marca de tiempo y una imagen de captura de pantalla a los metadatos de contenido multimedia. Esto permite a los usuarios navegar por el contenido multimedia.
navigator.mediaSession.metadata = new MediaMetadata({
// title, artist, album, artwork, ...
chapterInfo: [{
title: 'Chapter 1',
startTime: 0,
artwork: [
{ src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
{ src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
]
}, {
title: 'Chapter 2',
startTime: 42,
artwork: [
{ src: 'https://via.placeholder.com/128', sizes: '128x128', type: 'image/png' },
{ src: 'https://via.placeholder.com/512', sizes: '512x512', type: 'image/png' },
]
}]
});
Permite que los usuarios controlen lo que se reproduce
Una acción de sesión multimedia es una acción (por ejemplo, "reproducir" o "pausar") que un sitio web puede controlar para los usuarios cuando interactúan con la reproducción multimedia actual. Las acciones son análogas a los eventos y funcionan de manera similar. Al igual que los eventos, las acciones se implementan configurando controladores en un objeto apropiado, una instancia de MediaSession
, en este caso. Algunas acciones se activan cuando los usuarios presionan botones de auriculares, otro dispositivo remoto, un teclado o interactúan con una notificación multimedia.
Debido a que es posible que no se admitan algunas acciones de sesión multimedia, se recomienda usar un bloque try…catch
cuando las configures.
const actionHandlers = [
['play', () => { /* ... */ }],
['pause', () => { /* ... */ }],
['previoustrack', () => { /* ... */ }],
['nexttrack', () => { /* ... */ }],
['stop', () => { /* ... */ }],
['seekbackward', (details) => { /* ... */ }],
['seekforward', (details) => { /* ... */ }],
['seekto', (details) => { /* ... */ }],
/* Video conferencing actions */
['togglemicrophone', () => { /* ... */ }],
['togglecamera', () => { /* ... */ }],
['hangup', () => { /* ... */ }],
/* Presenting slides actions */
['previousslide', () => { /* ... */ }],
['nextslide', () => { /* ... */ }],
];
for (const [action, handler] of actionHandlers) {
try {
navigator.mediaSession.setActionHandler(action, handler);
} catch (error) {
console.log(`The media session action "${action}" is not supported yet.`);
}
}
Desactivar un controlador de acción de sesión multimedia es tan fácil como configurarlo en null
.
try {
// Unset the "nexttrack" action handler at the end of a playlist.
navigator.mediaSession.setActionHandler('nexttrack', null);
} catch (error) {
console.log(`The media session action "nexttrack" is not supported yet.`);
}
Una vez configurados, los controladores de acciones de la sesión multimedia persistirán durante las reproducciones multimedia. Esto es similar al patrón de objeto de escucha de eventos, excepto que controlar un evento significa que el navegador deja de realizar cualquier comportamiento predeterminado y lo usa como una señal de que el sitio web admite la acción multimedia. Por lo tanto, no se mostrarán los controles de acción multimedia, a menos que se configure el controlador de acciones adecuado.
Reproducir/pausar
La acción "play"
indica que el usuario desea reanudar la reproducción multimedia, mientras que "pause"
indica que desea detenerla temporalmente.
El ícono de "reproducir/pausar" siempre se muestra en una notificación multimedia, y el navegador controla automáticamente los eventos multimedia relacionados. Para anular su comportamiento predeterminado, controla las acciones de reproducción y pausa de contenido multimedia como se muestra a continuación.
El navegador puede considerar que un sitio web no reproduce contenido multimedia cuando busca o carga contenido. En este caso, anula este comportamiento configurando navigator.mediaSession.playbackState
en "playing"
o "paused"
para asegurarte de que la IU del sitio web permanezca sincronizada con los controles de notificaciones multimedia.
const video = document.querySelector('video');
navigator.mediaSession.setActionHandler('play', async () => {
// Resume playback
await video.play();
});
navigator.mediaSession.setActionHandler('pause', () => {
// Pause active playback
video.pause();
});
video.addEventListener('play', () => {
navigator.mediaSession.playbackState = 'playing';
});
video.addEventListener('pause', () => {
navigator.mediaSession.playbackState = 'paused';
});
Pista anterior
La acción "previoustrack"
indica que el usuario desea iniciar la reproducción de contenido multimedia actual desde el principio si la reproducción de contenido multimedia tiene noción de principio, o bien pasar al elemento anterior de la lista de reproducción si la reproducción de contenido multimedia tiene la noción de lista de reproducción.
navigator.mediaSession.setActionHandler('previoustrack', () => {
// Play previous track.
});
Pista siguiente
La acción "nexttrack"
indica que el usuario quiere mover la reproducción multimedia al siguiente elemento de la playlist si la reproducción multimedia tiene una noción de playlist.
navigator.mediaSession.setActionHandler('nexttrack', () => {
// Play next track.
});
Detener
La acción "stop"
indica que el usuario quiere detener la reproducción de contenido multimedia y borrar el estado si corresponde.
navigator.mediaSession.setActionHandler('stop', () => {
// Stop playback and clear state if appropriate.
});
Adelantar / retroceder
La acción "seekbackward"
indica que el usuario quiere retroceder el tiempo de reproducción de contenido multimedia por un período breve, mientras que "seekforward"
indica que desea avanzar el tiempo de reproducción de contenido multimedia por un período breve. En ambos casos, un período breve significa unos segundos.
El valor seekOffset
que se proporciona en el controlador de acciones es el tiempo en segundos que se debe mover el tiempo de reproducción de contenido multimedia. Si no se proporciona (por ejemplo, undefined
), debes usar un tiempo razonable (por ejemplo, de 10 a 30 segundos).
const video = document.querySelector('video');
const defaultSkipTime = 10; /* Time to skip in seconds by default */
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
const skipTime = details.seekOffset || defaultSkipTime;
video.currentTime = Math.max(video.currentTime - skipTime, 0);
// TODO: Update playback state.
});
navigator.mediaSession.setActionHandler('seekforward', (details) => {
const skipTime = details.seekOffset || defaultSkipTime;
video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
// TODO: Update playback state.
});
Cómo buscar una hora específica
La acción "seekto"
indica que el usuario desea mover el tiempo de reproducción de contenido multimedia a una hora específica.
El valor seekTime
que se proporciona en el controlador de acciones es el tiempo en segundos al que se debe mover el tiempo de reproducción multimedia.
El valor booleano fastSeek
proporcionado en el controlador de acciones es verdadero si se llama a la acción varias veces como parte de una secuencia y esta no es la última llamada en esa secuencia.
const video = document.querySelector('video');
navigator.mediaSession.setActionHandler('seekto', (details) => {
if (details.fastSeek && 'fastSeek' in video) {
// Only use fast seek if supported.
video.fastSeek(details.seekTime);
return;
}
video.currentTime = details.seekTime;
// TODO: Update playback state.
});
Cómo establecer la posición de reproducción
Mostrar con precisión la posición de reproducción de contenido multimedia en una notificación es tan simple como configurar el estado de posición en un momento apropiado, como se muestra a continuación. El estado de la posición es una combinación de la velocidad de reproducción multimedia, la duración y la hora actual.
La duración debe proporcionarse y ser positiva. La posición debe ser positiva y ser inferior a la duración. La velocidad de reproducción debe ser mayor que 0.
const video = document.querySelector('video');
function updatePositionState() {
if ('setPositionState' in navigator.mediaSession) {
navigator.mediaSession.setPositionState({
duration: video.duration,
playbackRate: video.playbackRate,
position: video.currentTime,
});
}
}
// When video starts playing, update duration.
await video.play();
updatePositionState();
// When user wants to seek backward, update position.
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
/* ... */
updatePositionState();
});
// When user wants to seek forward, update position.
navigator.mediaSession.setActionHandler('seekforward', (details) => {
/* ... */
updatePositionState();
});
// When user wants to seek to a specific time, update position.
navigator.mediaSession.setActionHandler('seekto', (details) => {
/* ... */
updatePositionState();
});
// When video playback rate changes, update position state.
video.addEventListener('ratechange', (event) => {
updatePositionState();
});
Restablecer el estado de la posición es tan fácil como configurarlo en null
.
// Reset position state when media is reset.
navigator.mediaSession.setPositionState(null);
Acciones de videoconferencia
Cuando el usuario coloca la videollamada en una ventana de pantalla en pantalla, es posible que el navegador muestre controles para el micrófono y la cámara, y para colgar. Cuando el usuario hace clic en ellos, el sitio web los controla a través de las acciones de videoconferencia que se indican a continuación. Para ver un ejemplo, consulta el ejemplo de videoconferencias.
Activar o desactivar micrófono
La acción "togglemicrophone"
indica que el usuario desea silenciar o activar el sonido del micrófono. El método setMicrophoneActive(isActive)
le indica al navegador si el sitio web considera que el micrófono está activo.
let isMicrophoneActive = false;
navigator.mediaSession.setActionHandler('togglemicrophone', () => {
if (isMicrophoneActive) {
// Mute the microphone.
} else {
// Unmute the microphone.
}
isMicrophoneActive = !isMicrophoneActive;
navigator.mediaSession.setMicrophoneActive(isMicrophoneActive);
});
Activar o desactivar la cámara
La acción "togglecamera"
indica que el usuario quiere activar o desactivar la cámara activa. El método setCameraActive(isActive)
indica si el navegador considera que el sitio web está activo.
let isCameraActive = false;
navigator.mediaSession.setActionHandler('togglecamera', () => {
if (isCameraActive) {
// Disable the camera.
} else {
// Enable the camera.
}
isCameraActive = !isCameraActive;
navigator.mediaSession.setCameraActive(isCameraActive);
});
Cuelga.
La acción "hangup"
indica que el usuario quiere finalizar una llamada.
navigator.mediaSession.setActionHandler('hangup', () => {
// End the call.
});
Acciones para presentar diapositivas
Cuando el usuario coloca su presentación de diapositivas en una ventana de pantalla en pantalla, el navegador puede mostrar controles para navegar por las diapositivas. Cuando el usuario hace clic en ellos, el sitio web los controla a través de la API de Media Session. Para ver un ejemplo, consulta el ejemplo de presentación de diapositivas.
Diapositiva anterior
La acción "previousslide"
indica que el usuario quiere volver a la diapositiva anterior cuando presenta diapositivas.
navigator.mediaSession.setActionHandler('previousslide', () => {
// Show previous slide.
});
Navegadores compatibles
Siguiente diapositiva
La acción "nextslide"
indica que el usuario quiere ir a la siguiente diapositiva cuando presenta diapositivas.
navigator.mediaSession.setActionHandler('nextslide', () => {
// Show next slide.
});
Navegadores compatibles
Ejemplos
Consulta algunos ejemplos de Media Session con Blender Foundation y el trabajo de Jan Morgenstern.
Recursos
- Especificación de Media Session: wicg.github.io/mediasession
- Problemas con las especificaciones: github.com/WICG/mediasession/issues
- Errores de Chrome: crbug.com