Comment intégrer les touches multimédias matérielles, personnaliser les notifications multimédias, et plus encore.
Pour indiquer aux utilisateurs ce qui est actuellement en cours de lecture dans leur navigateur et le contrôler sans revenir à la page qui l'a lancé, l'API Media Session a été introduite. Il permet aux développeurs Web de personnaliser cette expérience via des métadonnées dans des notifications multimédias personnalisées, des événements multimédias tels que la lecture, la mise en pause, la recherche, le changement de piste, et des événements de visioconférence tels que la mise en sourdine/désourdine du micro, l'activation/la désactivation de la caméra et le raccrochage. Ces personnalisations sont disponibles dans plusieurs contextes, y compris les hubs multimédias pour ordinateur, les notifications multimédias sur mobile et même sur les accessoires connectés. Je vais décrire ces personnalisations dans cet article.
À propos de l'API Media Session
L'API Media Session offre plusieurs avantages et fonctionnalités:
- Les touches multimédias matérielles sont compatibles.
- Les notifications multimédias sont personnalisées sur les appareils mobiles, les ordinateurs et les accessoires connectés associés.
- Le hub multimédia est disponible sur ordinateur.
- Les commandes multimédias de l'écran de verrouillage sont disponibles sur ChromeOS et sur mobile.
- Les commandes de la fenêtre Picture-in-Picture sont disponibles pour la lecture audio, la conférence vidéo et la présentation de diapositives.
- L'intégration de l'Assistant sur mobile est disponible.
Quelques exemples illustrent certains de ces points.
Exemple 1 : Si les utilisateurs appuient sur la touche multimédia "Piste suivante" de leur clavier, les développeurs Web peuvent gérer cette action de l'utilisateur, que le navigateur soit au premier plan ou en arrière-plan.
Exemple 2:Si les utilisateurs écoutent un podcast sur le Web alors que l'écran de leur appareil est verrouillé, ils peuvent toujours appuyer sur l'icône de recherche en arrière dans les commandes multimédias de l'écran de verrouillage, ce qui permet aux développeurs Web de reculer de quelques secondes le temps de lecture.
Exemple 3 : Si des utilisateurs écoutent de l'audio dans des onglets, ils peuvent facilement arrêter la lecture depuis le hub multimédia sur ordinateur afin que les développeurs Web puissent effacer leur état.
Exemple 4:Si les utilisateurs sont en cours d'appel vidéo, ils peuvent appuyer sur la commande d'activation du micro dans la fenêtre Picture-in-picture pour empêcher le site Web de recevoir les données du micro.
Tout cela se fait via deux interfaces différentes : l'interface MediaSession
et l'interface MediaMetadata
. Le premier permet aux utilisateurs de contrôler ce qui est en cours de lecture. La seconde consiste à indiquer à MediaSession
ce qui doit être contrôlé.
Pour illustrer, l'image ci-dessous montre comment ces interfaces se rapportent à des commandes multimédias spécifiques, en l'occurrence une notification multimédia sur mobile.
Indiquer aux utilisateurs ce qu'ils écoutent
Lorsqu'un site Web diffuse du contenu audio ou vidéo, les utilisateurs reçoivent automatiquement des notifications multimédias dans le bac de notifications sur mobile ou dans le hub multimédia sur ordinateur. Le navigateur fait de son mieux pour afficher les informations appropriées à l'aide du titre du document et de l'image d'icône la plus grande qu'il puisse trouver. Avec l'API Media Session, vous pouvez personnaliser la notification multimédia avec des métadonnées multimédias plus riches, telles que le titre, le nom de l'artiste, le nom de l'album et l'illustration, comme indiqué ci-dessous.
Chrome demande une attention audio "complète" pour afficher les notifications multimédias uniquement lorsque la durée du contenu multimédia est d'au moins cinq secondes. Cela garantit que les sons involontaires tels que les sonneries ne déclenchent pas de notifications.
// 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.
}
À la fin de la lecture, il n'est pas nécessaire de "libérer" la session multimédia, car la notification disparaît automatiquement. N'oubliez pas que navigator.mediaSession.metadata
sera utilisé au début de la lecture suivante. C'est pourquoi il est important de la mettre à jour lorsque la source de lecture multimédia change pour vous assurer que les informations pertinentes s'affichent dans la notification multimédia.
Voici quelques points à retenir concernant les métadonnées multimédias.
- Le tableau d'illustrations de notification est compatible avec les URL de blob et les URL de données.
- Si aucune illustration n'est définie et qu'une image d'icône (spécifiée à l'aide de
<link rel=icon>
) est disponible dans la taille souhaitée, les notifications multimédias l'utiliseront. - La taille cible de l'illustration de notification dans Chrome pour Android est
512x512
. Pour les appareils bas de gamme, il s'agit de256x256
. - L'attribut
title
de l'élément HTML multimédia est utilisé dans le widget macOS "En écoute". - Si la ressource multimédia est intégrée (par exemple, dans un iFrame), les informations de l'API Media Session doivent être définies à partir du contexte intégré. Voir l'extrait ci-dessous.
<iframe id="iframe">
<video>...</video>
</iframe>
<script>
iframe.contentWindow.navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
...
});
</script>
Vous pouvez également ajouter des informations sur chaque chapitre, comme le titre de la section, son code temporel et une capture d'écran, aux métadonnées multimédias. Cela permet aux utilisateurs de naviguer dans le contenu du média.
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' },
]
}]
});
Permettre aux utilisateurs de contrôler la lecture
Une action de session multimédia est une action (par exemple, "lecture" ou "pause") qu'un site Web peut gérer pour les utilisateurs lorsqu'ils interagissent avec la lecture du contenu multimédia en cours. Les actions sont analogues aux événements et fonctionnent de la même manière. Comme les événements, les actions sont implémentées en définissant des gestionnaires sur un objet approprié, une instance de MediaSession
, dans ce cas. Certaines actions sont déclenchées lorsque les utilisateurs appuient sur les boutons d'un casque, d'un autre appareil distant ou d'un clavier, ou interagissent avec une notification multimédia.
Étant donné que certaines actions de session multimédia peuvent ne pas être prises en charge, il est recommandé d'utiliser un bloc try…catch
lors de leur configuration.
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.`);
}
}
Pour désactiver un gestionnaire d'action de session multimédia, il vous suffit de le définir sur 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.`);
}
Une fois définis, les gestionnaires d'actions de session multimédia persistent pendant la lecture des contenus multimédias. Ce modèle est semblable au modèle d'écouteur d'événements, sauf que la gestion d'un événement signifie que le navigateur cesse d'exécuter tout comportement par défaut et l'utilise comme signal indiquant que le site Web est compatible avec l'action multimédia. Par conséquent, les commandes d'action multimédias ne s'affichent que si le gestionnaire d'action approprié est défini.
Lecture / Pause
L'action "play"
indique que l'utilisateur souhaite reprendre la lecture multimédia, tandis que "pause"
indique qu'il souhaite l'arrêter temporairement.
L'icône "Lire/Mettre en pause" s'affiche toujours dans une notification multimédia, et les événements multimédias associés sont gérés automatiquement par le navigateur. Pour remplacer leur comportement par défaut, gérez les actions multimédias "play" (Lire) et "pause" (Mettre en pause) comme indiqué ci-dessous.
Le navigateur peut considérer qu'un site Web ne diffuse pas de contenu multimédia lors d'une recherche ou d'un chargement, par exemple. Dans ce cas, remplacez ce comportement en définissant navigator.mediaSession.playbackState
sur "playing"
ou "paused"
pour vous assurer que l'interface utilisateur du site Web reste synchronisée avec les commandes de notification multimédia.
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';
});
Titre précédent
L'action "previoustrack"
indique que l'utilisateur souhaite démarrer la lecture du contenu multimédia en cours depuis le début si la lecture du contenu multimédia a une notion de début, ou passer à l'élément précédent de la playlist si la lecture du contenu multimédia a la notion de playlist.
navigator.mediaSession.setActionHandler('previoustrack', () => {
// Play previous track.
});
Titre suivant
L'action "nexttrack"
indique que l'utilisateur souhaite passer la lecture du contenu multimédia à l'élément suivant de la playlist si la lecture du contenu multimédia a la notion de playlist.
navigator.mediaSession.setActionHandler('nexttrack', () => {
// Play next track.
});
Arrêter
L'action "stop"
indique que l'utilisateur souhaite arrêter la lecture multimédia et effacer l'état, le cas échéant.
navigator.mediaSession.setActionHandler('stop', () => {
// Stop playback and clear state if appropriate.
});
Revenir en arrière/Avancer
L'action "seekbackward"
indique que l'utilisateur souhaite avancer le temps de lecture des contenus multimédias d'une courte période, tandis que "seekforward"
indique qu'il souhaite avancer d'une courte période la durée de lecture des contenus multimédias. Dans les deux cas, une période courte signifie quelques secondes.
La valeur seekOffset
fournie dans le gestionnaire d'actions correspond au temps de transfert du temps de lecture du contenu multimédia, exprimé en secondes. Si ce paramètre n'est pas fourni (par exemple, undefined
), vous devez utiliser une durée raisonnable (par exemple, 10 à 30 secondes).
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.
});
Accéder à un moment spécifique
L'action "seekto"
indique que l'utilisateur souhaite déplacer l'heure de lecture multimédia à une heure spécifique.
La valeur seekTime
fournie dans le gestionnaire d'actions correspond au temps (en secondes) auquel déplacer le temps de lecture multimédia.
La valeur booléenne fastSeek
fournie dans le gestionnaire d'actions est "true" si l'action est appelée plusieurs fois dans le cadre d'une séquence et qu'il ne s'agit pas du dernier appel de cette séquence.
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.
});
Définir la position de lecture
Pour afficher précisément la position de lecture multimédia dans une notification, il suffit de définir l'état de la position au moment opportun, comme indiqué ci-dessous. L'état de la position combine la vitesse de lecture des contenus multimédias, la durée et l'heure actuelle.
La durée doit être fournie et positive. La position doit être positive et inférieure à la durée. La vitesse de lecture doit être supérieure à 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();
});
Réinitialiser l'état de la position est aussi simple que de le définir sur null
.
// Reset position state when media is reset.
navigator.mediaSession.setPositionState(null);
Actions pendant la visioconférence
Lorsque l'utilisateur met son appel vidéo dans une fenêtre Picture-in-picture, le navigateur peut afficher des commandes pour le micro et la caméra, ainsi que pour raccrocher. Lorsque l'utilisateur clique dessus, le site Web les gère via les actions de visioconférence ci-dessous. Pour obtenir un exemple, consultez l'exemple de visioconférence.
Activer/Désactiver le micro
L'action "togglemicrophone"
indique que l'utilisateur souhaite couper ou réactiver le micro. La méthode setMicrophoneActive(isActive)
indique au navigateur si le site Web considère actuellement le micro comme actif.
let isMicrophoneActive = false;
navigator.mediaSession.setActionHandler('togglemicrophone', () => {
if (isMicrophoneActive) {
// Mute the microphone.
} else {
// Unmute the microphone.
}
isMicrophoneActive = !isMicrophoneActive;
navigator.mediaSession.setMicrophoneActive(isMicrophoneActive);
});
Activer/Désactiver l'appareil photo
L'action "togglecamera"
indique que l'utilisateur souhaite activer ou désactiver la caméra active. La méthode setCameraActive(isActive)
indique si le navigateur considère le site Web comme actif.
let isCameraActive = false;
navigator.mediaSession.setActionHandler('togglecamera', () => {
if (isCameraActive) {
// Disable the camera.
} else {
// Enable the camera.
}
isCameraActive = !isCameraActive;
navigator.mediaSession.setCameraActive(isCameraActive);
});
Raccrocher
L'action "hangup"
indique que l'utilisateur souhaite mettre fin à un appel.
navigator.mediaSession.setActionHandler('hangup', () => {
// End the call.
});
Actions de présentation de diapositives
Lorsque l'utilisateur place sa présentation dans une fenêtre Picture-in-Picture, le navigateur peut afficher des commandes permettant de naviguer dans les diapositives. Lorsque l'utilisateur clique dessus, le site Web les gère via l'API Media Session. Pour obtenir un exemple, consultez l'exemple de présentation de diapositives.
Diapositive précédente
L'action "previousslide"
indique que l'utilisateur souhaite revenir à la diapositive précédente lors de la présentation de diapositives.
navigator.mediaSession.setActionHandler('previousslide', () => {
// Show previous slide.
});
Navigateurs pris en charge
Diapositive suivante
L'action "nextslide"
indique que l'utilisateur souhaite passer à la diapositive suivante lors de la présentation de diapositives.
navigator.mediaSession.setActionHandler('nextslide', () => {
// Show next slide.
});
Navigateurs pris en charge
Exemples
Consultez des exemples de sessions multimédias avec la Blender Foundation et le travail de Jan Morgenstern.
Ressources
- Spécification de la session multimédia : wicg.github.io/mediasession
- Problèmes de spécification : github.com/WICG/mediasession/issues
- Bugs Chrome : crbug.com