Hier ist ein Szenario. Sie starten einen krachenden Kendrick Lamar Track in einem Ihrer vielen offenen Browser-Tabs. Sie lieben es, aber jemand kommt herein und Sie müssen ihn pausieren. Welcher Tab ist es? Browser versuchen, dabei ein wenig zu helfen. Sie können wahrscheinlich den gesamten Systemton stummschalten. Aber wäre es nicht schön, die Audiowiedergabe tatsächlich steuern zu können, ohne unbedingt zu diesem Tab zurückkehren zu müssen?
Die Media Session API macht dies möglich. Sie gibt der Wiedergabe von Medien Zugriff für den Benutzer, *außerhalb* des Browser-Tabs, in dem sie abgespielt wird. Wenn sie implementiert ist, wird sie an verschiedenen Stellen auf dem Gerät verfügbar sein, darunter
- der Benachrichtigungsbereich auf vielen Mobilgeräten,
- auf anderen Wearables und
- dem Medien-Hub-Bereich vieler Desktop-Geräte.
Zusätzlich erlaubt uns die Media Session API, die Medienwiedergabe mit Medientasten und Sprachassistenten wie Siri, Google Assistant, Bixby oder Alexa zu steuern.

Die Media Session API
Die Media Session API besteht hauptsächlich aus den folgenden zwei Schnittstellen:
MediaMetadataMediaSession
Die MediaMetadata-Schnittstelle liefert Daten über die abgespielten Medien. Sie ist dafür verantwortlich, uns den Titel, das Album, das Artwork und den Künstler (in diesem Beispiel Kendrick Lamar) der Medien mitzuteilen. Die MediaSession-Schnittstelle ist für die Funktionalität der Medienwiedergabe zuständig.
Bevor wir uns eingehend mit dem Thema beschäftigen, müssen wir die Feature-Erkennung berücksichtigen. Es ist gute Praxis zu prüfen, ob ein Browser ein Feature unterstützt, bevor man es implementiert. Um zu prüfen, ob ein Browser die Media Session API unterstützt, müssten wir Folgendes in unsere JavaScript-Datei aufnehmen:
if ('mediaSession' in navigator) {
// Our media session api that lets us seek to the beginning of Kendrick Lamar's "Alright"
}
Die MediaMetadata-Schnittstelle
Der Konstruktor, MediaMetadata.MediaMetadata(), erstellt ein neues MediaMetadata-Objekt. Nach dessen Erstellung können wir die folgenden Eigenschaften hinzufügen:
MediaMetadata.titlelegt den Titel der abgespielten Medien fest oder ruft ihn ab.MediaMetadata.artistlegt den Namen des Künstlers oder der Gruppe der abgespielten Medien fest oder ruft ihn ab.MediaMetadata.albumlegt den Namen des Albums fest, das die abgespielten Medien enthält, oder ruft ihn ab.MediaMetadata.artworklegt das Array von Bildern fest, die mit den abgespielten Medien verknüpft sind, oder ruft es ab.
Der Wert der artwork-Eigenschaft des MediaMetadata-Objekts ist ein Array von MediaImage-Objekten. Ein MediaImage-Objekt enthält Details, die ein Bild beschreiben, das mit den Medien verknüpft ist. Die Objekte haben die folgenden drei Eigenschaften:
src: die URL des Bildessizes: gibt die Größe des Bildes an, damit ein Bild nicht skaliert werden musstype: der MIME-Typ des Bildes
Erstellen wir ein MediaMetadata-Objekt für Kendrick Lamars „Alright“ aus seinem Album 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
]
});
}
Die MediaSession-Schnittstelle
Wie bereits erwähnt, ermöglicht dies dem Benutzer die Steuerung der Wiedergabe der Medien. Über diese Schnittstelle können wir folgende Aktionen auf den abgespielten Medien ausführen:
play: die Medien abspielenpause: die Medien pausierenprevioustrack: zum vorherigen Titel wechselnnexttrack: zum nächsten Titel wechselnseekbackward: von der aktuellen Position einige Sekunden zurückspringenseekforward: von der aktuellen Position einige Sekunden vorwärts springenseekto: zu einer bestimmten Zeit von der aktuellen Position aus springenstop: die Medienwiedergabe stoppenskipad: die laufende Werbung überspringen, falls vorhanden
Der aufgezählte Typ MediaSessionAction macht diese Aktionen als String-Typen verfügbar. Um eine dieser Aktionen zu unterstützen, müssen wir die Methode setActionHandler() von MediaSession verwenden, um einen Handler für diese Aktion zu definieren. Die Methode nimmt die Aktion und eine Callback-Funktion entgegen, die aufgerufen wird, wenn der Benutzer die Aktion auslöst. Lassen Sie uns einen nicht zu tiefen Einblick nehmen, um es besser zu verstehen.
Um Handler für die Aktionen play und pause festzulegen, nehmen wir Folgendes in unsere JavaScript-Datei auf:
let alright = new HTMLAudioElement();
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('play', () => {
alright.play();
});
navigator.mediaSession.setActionHandler('pause', () => {
alright.pause();
});
}
Hier legen wir fest, dass der Titel abgespielt wird, wenn der Benutzer ihn über die Media-Oberfläche abspielt, und pausiert wird, wenn der Benutzer ihn pausiert.
Für die Aktionen previoustrack und nexttrack nehmen wir Folgendes auf:
let u = new HTMLAudioElement();
let forSaleInterlude = new HTMLAudioElement();
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('previoustrack', () => {
u.play();
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
forSaleInterlude.play();
});
}
Dies ist möglicherweise nicht vollständig selbsterklärend, wenn Sie kein großer Kendrick Lamar-Fan sind, aber hoffentlich verstehen Sie das Wesentliche. Wenn der Benutzer den vorherigen Titel abspielen möchte, stellen wir den vorherigen Titel zum Abspielen ein. Wenn es sich um den nächsten Titel handelt, ist es der nächste Titel.
Um die Aktionen seekbackward und seekforward zu implementieren, nehmen wir Folgendes auf:
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);
});
}
Da ich keines davon für selbsterklärend halte, möchte ich eine prägnante Erklärung zu den Aktionen seekbackward und seekforward geben. Die Handler für beide Aktionen, seekbackward und seekforward, werden, wie ihre Namen vermuten lassen, ausgelöst, wenn der Benutzer um einige Sekunden zurück- oder vorwärts springen möchte. Das MediaSessionActionDetails-Dictionary liefert uns die „einige Sekunden“ in einer Eigenschaft, seekOffset. Die seekOffset-Eigenschaft ist jedoch nicht immer vorhanden, da nicht alle User Agents gleich agieren. Wenn sie nicht vorhanden ist, sollten wir den Titel so einstellen, dass er um eine für uns sinnvolle Anzahl von Sekunden vor- oder zurückspringt. Daher verwenden wir 10 Sekunden, da dies eine beträchtliche Anzahl ist. Kurz gesagt, wir stellen den Titel so ein, dass er um seekOffset Sekunden springt, wenn dies angegeben ist. Wenn es nicht angegeben ist, springen wir um 10 Sekunden.
Um die seekto-Funktionalität zu unserer Media Session API hinzuzufügen, nehmen wir den folgenden Snippet auf:
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('seekto', (details) => {
if (details.fastSeek && 'fastSeek' in alright) {
alright.fastSeek(details.seekTime);
return;
}
alright.currentTime = details.seekTime;
});
}
Hier liefert das MediaSessionActionDetails-Dictionary die Eigenschaften fastSeek und seekTime. fastSeek ist im Grunde ein schnelles Springen (wie Vorspulen oder Zurückspulen), während seekTime die Zeit ist, zu der der Titel springen soll. Während fastSeek eine optionale Eigenschaft ist, liefert das MediaSessionActionDetails-Dictionary immer die seekTime-Eigenschaft für den seekto-Aktionshandler. Grundsätzlich stellen wir den Titel auf fastSeek auf die seekTime ein, wenn die Eigenschaft verfügbar ist und der Benutzer schnell springt, während wir ihn einfach auf die seekTime einstellen, wenn der Benutzer einfach zu einer bestimmten Zeit springt.
Obwohl ich nicht wüsste, warum jemand einen Kendrick-Song stoppen möchte, schadet es nicht, den stop-Aktionshandler der MediaSession-Schnittstelle zu beschreiben.
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('stop', () => {
alright.pause();
alright.currentTime = 0;
});
}
Der Benutzer löst den skipad-Aktionshandler (im Sinne von „Werbung überspringen“ statt „Ski-Pad“) aus, wenn eine Werbung abgespielt wird und er sie überspringen möchte, um weiter Kendrick Lamars „Alright“-Titel hören zu können. Wenn ich ehrlich bin, sind die vollständigen Details des skipad-Aktionshandlers außerhalb des Rahmens meines Verständnisses der „Media Session API“. Daher sollten Sie dies wahrscheinlich nach dem Lesen dieses Artikels selbst nachschlagen, wenn Sie es tatsächlich implementieren möchten.
Zusammenfassung
Wir sollten uns etwas merken. Immer wenn der Benutzer den Titel abspielt, springt oder die Wiedergaberate ändert, müssen wir den Positionsstatus auf der von der Media Session API bereitgestellten Oberfläche aktualisieren. Um dies zu implementieren, verwenden wir die Methode setPositionState() des mediaSession-Objekts, wie im Folgenden dargestellt:
if ('mediaSession' in navigator) {
navigator.mediaSession.setPositionState({
duration: alright.duration,
playbackRate: alright.playbackRate,
position: alright.currentTime
});
}
Darüber hinaus möchte ich Sie daran erinnern, dass nicht alle Browser der Benutzer alle Aktionen unterstützen. Daher wird empfohlen, die Aktionshandler in einem try...catch-Block festzulegen, wie im Folgenden dargestellt:
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`);
}
}
Wenn wir alles bisherige zusammenfügen, erhalten wir Folgendes:
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`);
}
}
}
Hier ist eine Demo der API:
Ich habe sechs der Aktionen implementiert. Fühlen Sie sich frei, die restlichen in Ihrer Freizeit auszuprobieren.
Wenn Sie sich den Pen auf Ihrem Mobilgerät ansehen, achten Sie darauf, wie er in Ihrem Benachrichtigungsbereich angezeigt wird.

Wenn Ihre Smartwatch mit Ihrem Gerät gekoppelt ist, werfen Sie einen Blick darauf.
Wenn Sie den Pen auf Chrome auf dem Desktop anzeigen, navigieren Sie zum Medien-Hub und spielen Sie mit den Medientasten dort herum. Die Demo hat sogar mehrere Titel, sodass Sie das Vorwärts-/Rückwärtsspringen zwischen den Titeln ausprobieren können.
Wenn Sie es bis hierher geschafft haben (oder auch nicht), danke fürs Lesen, und bitte implementieren Sie diese API bei Ihrer nächsten App mit Medienfunktionalität.
Großartig! Ich habe vor, es eines Tages zu implementieren, danke, mein Herr.
Gern geschehen!
Es ist weit mehr als das! Einige Headsets oder Kopfhörer verfügen über automatische Pausenfunktionen, die ein Wiedergabe-/Pausesignal an jede Bluetooth-Quelle senden, mit der sie verbunden sind. Ich bin absolut begeistert, endlich in der Lage zu sein, jedes YouTube-Video oder jede Bootcamp-Playlist anzuhalten, indem ich einfach mein Headset abnehme oder es mit der Hand berühre, wenn jemand anfängt, mit mir zu interagieren.
Ich muss zugeben, es funktioniert sogar bei einigen alten Webplayern, bei denen ich nicht dachte, dass sie es wirklich implementiert hätten. Vielleicht, weil solche Websites Standard-HTML-Audiowiedergabe verwenden, kann der Browser es steuern.
Auf jeden Fall vielen Dank für diesen Artikel.
Ich habe es in der Einleitung tatsächlich erwähnt, dass Medientasten (wie die Wiedergabe-/Pausetaste auf Ihren Kopfhörern) mit der API unterstützt werden. YouTube implementiert ebenfalls die API.
Gern geschehen.
Ich habe eine Medientaste, deren Namen ich nicht kenne, aber jedes Mal, wenn ich darauf klicke, öffnet sich youtube.com O_o
Wie bekomme ich eine Liste unterstützter Medientasten?
Ich würde vorschlagen, dass Sie die Spezifikationen des Geräts mit den Medientasten nachschlagen.
Hey, funktionierte die Media Session API in einer Android-App?
Bitte machen Sie ein Tutorial oder demonstrieren Sie es.
Ja, die API kann in einer Android-App implementiert werden, aber das liegt außerhalb meines Zuständigkeitsbereichs.
Sie finden Tutorials im Web dafür.
Ist es möglich,
MediaMetadataohne ein<audio/>- oder<video/>-Element zu verwenden?Ich möchte Audio-Metadaten von der SoundCloud-API anzeigen – also ohne Angabe einer
source–, aber soweit ich das verstehe, erfordert die Verwendung vonMediaMetadatadasplay()en eines dieser beiden Elemente, oder?Gibt es einen Trick, um diese Anforderung zu umgehen?
Kael, Sie können einfach new Audio() oder new Video() in Javascript verwenden. Wenn Sie die Quelle ausblenden möchten, um zu verhindern, dass Personen die tatsächliche Datei herunterladen, können Sie sie im Speicher speichern und von dort laden. Einige Tricks, wenn Sie den Dateipfad vom Server senden, bestehen darin, ihn beim Initialisieren in den Speicher zu laden und den Wert aus dem Attribut zu entfernen, damit die Leute den Pfad nicht durch Inspektion sehen können, es sei denn, sie wissen, dass Sie diesen Trick anwenden und setzen Breakpoints, bevor Ihre Initialisierung ausgeführt wird.
Bei der Implementierung habe ich festgestellt, dass manchmal, wenn man Code zu Javascript hinzufügt und aktualisiert (auch mit deaktiviertem Cache), der Player in Chrome aus irgendeinem Grund nicht richtig lädt. Sie müssen einen neuen Tab öffnen und die Seite erneut laden. Ich habe dies mit verschiedenen Codes von verschiedenen Leuten ausprobiert und das Ergebnis ist dasselbe, daher glaube ich, dass es sich um ein Chrome-Problem handelt.
Das zweite, was mir aufgefallen ist, ist, dass MediaSession keine Lautstärkeregelung hat. Unter iOS gibt es eine Lautstärkeleiste, die also nicht mit der Lautstärke im Web übereinstimmt.
let alright = new HTMLAudioElement();wirftUncaught TypeError: Illegal constructor