Wie erzielst du die beste mobile Medienerfahrung im Web? So einfach ist das. Das hängt vom Nutzer-Engagement und von der Bedeutung ab, die Sie den Medien auf einer Webseite beimessen. Wenn ein Video der Hauptgrund für den Besuch eines Nutzers ist, muss die Nutzererfahrung immersiv und wiederholbar sein.

In diesem Artikel zeige ich Ihnen, wie Sie mithilfe einer Vielzahl von Web-APIs Ihre Medienerfahrung auf progressive Weise verbessern und immersiver gestalten können. Deshalb entwickeln wir einen einfachen mobilen Player mit benutzerdefinierten Steuerelementen, Vollbildwiedergabe und Hintergrundwiedergabe. Sie können das Beispiel jetzt ausprobieren und den Code in unserem GitHub-Repository finden.
Benutzerdefinierte Steuerelemente

Wie Sie sehen, ist das HTML-Layout, das wir für unseren Mediaplayer verwenden, ziemlich einfach: Ein <div>
-Stammelement enthält ein <video>
-Medienelement und ein <div>
-untergeordnetes Element für die Videosteuerung.
Zu den Videosteuerungen, die wir später behandeln, gehören: eine Schaltfläche für die Wiedergabe/Pause, eine Schaltfläche für den Vollbildmodus, Schaltflächen zum Zurück- und Vorspulen sowie einige Elemente für die aktuelle Zeit, die Dauer und die Zeiterfassung.
<div id="videoContainer">
<video id="video" src="file.mp4"></video>
<div id="videoControls"></div>
</div>
Videometadaten lesen
Warten wir zuerst, bis die Videometadaten geladen sind, um die Videodauer, die aktuelle Zeit und die Fortschrittsanzeige zu initialisieren. Die Funktion secondsToTimeCode()
ist eine benutzerdefinierte Dienstprogrammfunktion, die ich geschrieben habe. Sie wandelt eine Anzahl von Sekunden in einen String im Format „hh:mm:ss“ um, was in unserem Fall besser geeignet ist.
<div id="videoContainer">
<video id="video" src="file.mp4"></video>
<div id="videoControls">
<strong>
<div id="videoCurrentTime"></div>
<div id="videoDuration"></div>
<div id="videoProgressBar"></div>
</strong>
</div>
</div>
video.addEventListener('loadedmetadata', function () {
videoDuration.textContent = secondsToTimeCode(video.duration);
videoCurrentTime.textContent = secondsToTimeCode(video.currentTime);
videoProgressBar.style.transform = `scaleX(${
video.currentTime / video.duration
})`;
});

Video abspielen/anhalten
Nachdem die Videometadaten geladen wurden, fügen wir die erste Schaltfläche hinzu, mit der Nutzer das Video je nach Wiedergabestatus mit video.play()
und video.pause()
wiedergeben und pausieren können.
<div id="videoContainer">
<video id="video" src="file.mp4"></video>
<div id="videoControls">
<strong><button id="playPauseButton"></button></strong>
<div id="videoCurrentTime"></div>
<div id="videoDuration"></div>
<div id="videoProgressBar"></div>
</div>
</div>
playPauseButton.addEventListener('click', function (event) {
event.stopPropagation();
if (video.paused) {
video.play();
} else {
video.pause();
}
});
Anstatt die Videosteuerung im click
-Ereignis-Listener anzupassen, verwenden wir die Videoereignisse play
und pause
. Wenn wir unsere Steuerelemente ereignisbasiert gestalten, sind sie flexibler (wie wir später bei der Media Session API sehen werden) und wir können sie synchron halten, wenn der Browser in die Wiedergabe eingreift.
Wenn das Video wiedergegeben wird, ändern wir den Schaltflächenstatus in „Pausieren“ und blenden die Videosteuerelemente aus. Wenn das Video angehalten wird, ändern wir einfach den Schaltflächenstatus in „Wiedergabe“ und zeigen die Videosteuerelemente an.
video.addEventListener('play', function () {
playPauseButton.classList.add('playing');
});
video.addEventListener('pause', function () {
playPauseButton.classList.remove('playing');
});
Wenn sich die Zeit, die durch das Videoattribut currentTime
über das Videoereignis timeupdate
geändert hat, aktualisieren wir auch unsere benutzerdefinierten Steuerelemente, sofern sie sichtbar sind.
video.addEventListener('timeupdate', function () {
if (videoControls.classList.contains('visible')) {
videoCurrentTime.textContent = secondsToTimeCode(video.currentTime);
videoProgressBar.style.transform = `scaleX(${
video.currentTime / video.duration
})`;
}
});
Wenn das Video zu Ende ist, ändern wir einfach den Schaltflächenstatus in „Wiedergabe“, setzen currentTime
auf 0 zurück und zeigen die Videosteuerelemente an. Wir können auch ein anderes Video automatisch laden, wenn der Nutzer eine Art „Autoplay“-Funktion aktiviert hat.
video.addEventListener('ended', function () {
playPauseButton.classList.remove('playing');
video.currentTime = 0;
});
Zurück- und Vorspulen
Fahren wir fort und fügen die Schaltflächen „Zurück“ und „Vor“ hinzu, damit Nutzer Inhalte ganz einfach überspringen können.
<div id="videoContainer">
<video id="video" src="file.mp4"></video>
<div id="videoControls">
<button id="playPauseButton"></button>
<strong
><button id="seekForwardButton"></button>
<button id="seekBackwardButton"></button
></strong>
<div id="videoCurrentTime"></div>
<div id="videoDuration"></div>
<div id="videoProgressBar"></div>
</div>
</div>
var skipTime = 10; // Time to skip in seconds
seekForwardButton.addEventListener('click', function (event) {
event.stopPropagation();
video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
});
seekBackwardButton.addEventListener('click', function (event) {
event.stopPropagation();
video.currentTime = Math.max(video.currentTime - skipTime, 0);
});
Wie zuvor passen wir das Video-Styling nicht in den click
-Ereignis-Listenern dieser Schaltflächen an, sondern verwenden die ausgelösten seeking
- und seeked
-Videoereignisse, um die Videohelligkeit anzupassen. Meine benutzerdefinierte CSS-Klasse seeking
ist so einfach wie filter: brightness(0);
.
video.addEventListener('seeking', function () {
video.classList.add('seeking');
});
video.addEventListener('seeked', function () {
video.classList.remove('seeking');
});
Unten sehen Sie, was wir bisher erstellt haben. Im nächsten Abschnitt implementieren wir die Schaltfläche für den Vollbildmodus.
Vollbild
Hier nutzen wir mehrere Web-APIs, um ein perfektes und nahtloses Vollbilderlebnis zu schaffen. In diesem Beispiel sehen Sie, wie das funktioniert.
Natürlich müssen Sie nicht alle verwenden. Wählen Sie einfach die aus, die für Sie sinnvoll sind, und kombinieren Sie sie, um Ihren benutzerdefinierten Ablauf zu erstellen.
Automatischen Vollbildmodus verhindern
Auf iOS-Geräten wechseln video
-Elemente automatisch in den Vollbildmodus, wenn die Medienwiedergabe beginnt. Wir versuchen, die Medienwiedergabe in mobilen Browsern so weit wie möglich anzupassen und zu steuern. Daher empfehle ich, das playsinline
-Attribut des video
-Elements so festzulegen, dass die Wiedergabe auf dem iPhone gezwungenermaßen im Inline-Modus erfolgt und nicht in den Vollbildmodus wechselt, wenn die Wiedergabe beginnt. Dies hat keine Auswirkungen auf andere Browser.
<div id="videoContainer"></div>
<video id="video" src="file.mp4"></video><strong>playsinline</strong></video>
<div id="videoControls">...</div>
</div>
Vollbildmodus per Klick auf Schaltfläche ein-/ausschalten
Da wir den automatischen Vollbildmodus verhindern, müssen wir den Vollbildmodus für das Video mit der Vollbild-API selbst verwalten. Wenn der Nutzer auf die Schaltfläche „Vollbild“ klickt, beenden wir den Vollbildmodus mit document.exitFullscreen()
, wenn der Vollbildmodus derzeit vom Dokument verwendet wird. Andernfalls kannst du den Vollbildmodus für den Videocontainer mit der Methode requestFullscreen()
anfordern, sofern verfügbar, oder nur auf iOS-Geräten auf webkitEnterFullscreen()
zurückgreifen.
<div id="videoContainer">
<video id="video" src="file.mp4"></video>
<div id="videoControls">
<button id="playPauseButton"></button>
<button id="seekForwardButton"></button>
<button id="seekBackwardButton"></button>
<strong><button id="fullscreenButton"></button></strong>
<div id="videoCurrentTime"></div>
<div id="videoDuration"></div>
<div id="videoProgressBar"></div>
</div>
</div>
fullscreenButton.addEventListener('click', function (event) {
event.stopPropagation();
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
requestFullscreenVideo();
}
});
function requestFullscreenVideo() {
if (videoContainer.requestFullscreen) {
videoContainer.requestFullscreen();
} else {
video.webkitEnterFullscreen();
}
}
document.addEventListener('fullscreenchange', function () {
fullscreenButton.classList.toggle('active', document.fullscreenElement);
});
Vollbildmodus bei Änderung der Bildschirmausrichtung umschalten
Wenn der Nutzer das Gerät in den Querformatmodus dreht, sollten wir intelligent vorgehen und automatisch den Vollbildmodus anfordern, um ein immersives Erlebnis zu schaffen. Dazu benötigen wir die Screen Orientation API, die noch nicht überall unterstützt wird und in einigen Browsern noch einen Präfix hat. Dies ist also unsere erste progressive Verbesserung.
So funktioniert's Sobald wir eine Änderung der Bildschirmausrichtung erkennen, fordern wir den Vollbildmodus an, wenn sich das Browserfenster im Querformat befindet (d. h., wenn seine Breite größer als seine Höhe ist). Andernfalls beenden wir den Vollbildmodus. Das ist alles.
if ('orientation' in screen) {
screen.orientation.addEventListener('change', function () {
// Let's request fullscreen if user switches device in landscape mode.
if (screen.orientation.type.startsWith('landscape')) {
requestFullscreenVideo();
} else if (document.fullscreenElement) {
document.exitFullscreen();
}
});
}
Sperrbildschirm im Querformat durch Klicken auf die Schaltfläche sperren
Da sich Videos möglicherweise besser im Querformat ansehen lassen, sollten wir den Bildschirm im Querformat sperren, wenn der Nutzer auf die Schaltfläche „Vollbild“ klickt. Wir kombinieren die bisher verwendete Screen Orientation API mit einigen Mediaabfragen, um die Nutzerfreundlichkeit zu optimieren.
Sie können den Bildschirm im Querformat ganz einfach durch Aufrufen von screen.orientation.lock('landscape')
sperren. Dies sollte jedoch nur erfolgen, wenn sich das Gerät im Hochformat mit matchMedia('(orientation: portrait)')
befindet und mit matchMedia('(max-device-width: 768px)')
in einer Hand gehalten werden kann, da dies für Nutzer auf einem Tablet nicht optimal ist.
fullscreenButton.addEventListener('click', function (event) {
event.stopPropagation();
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
requestFullscreenVideo();
<strong>lockScreenInLandscape();</strong>;
}
});
function lockScreenInLandscape() {
if (!('orientation' in screen)) {
return;
}
// Let's force landscape mode only if device is in portrait mode and can be held in one hand.
if (
matchMedia('(orientation: portrait) and (max-device-width: 768px)').matches
) {
screen.orientation.lock('landscape');
}
}
Display bei Änderung der Geräteausrichtung entsperren
Möglicherweise haben Sie bemerkt, dass der gerade erstellte Sperrbildschirm nicht perfekt ist, da wir keine Änderungen der Bildschirmausrichtung erhalten, wenn das Display gesperrt ist.
Um dieses Problem zu beheben, verwenden wir die Device Orientation API, sofern verfügbar. Diese API liefert Informationen von der Hardware, die die Position und Bewegung eines Geräts im Raum misst: Gyroskop und digitaler Kompass für die Ausrichtung und Beschleunigungsmesser für die Geschwindigkeit. Wenn wir eine Änderung der Geräteausrichtung erkennen, entsperren wir den Bildschirm mit screen.orientation.unlock()
, wenn der Nutzer das Gerät im Hochformat hält und der Bildschirm im Querformat gesperrt ist.
function lockScreenInLandscape() {
if (!('orientation' in screen)) {
return;
}
// Let's force landscape mode only if device is in portrait mode and can be held in one hand.
if (matchMedia('(orientation: portrait) and (max-device-width: 768px)').matches) {
screen.orientation.lock('landscape')
<strong>.then(function() {
listenToDeviceOrientationChanges();
})</strong>;
}
}
function listenToDeviceOrientationChanges() {
if (!('DeviceOrientationEvent' in window)) {
return;
}
var previousDeviceOrientation, currentDeviceOrientation;
window.addEventListener(
'deviceorientation',
function onDeviceOrientationChange(event) {
// event.beta represents a front to back motion of the device and
// event.gamma a left to right motion.
if (Math.abs(event.gamma) > 10 || Math.abs(event.beta) < 10) {
previousDeviceOrientation = currentDeviceOrientation;
currentDeviceOrientation = 'landscape';
return;
}
if (Math.abs(event.gamma) < 10 || Math.abs(event.beta) > 10) {
previousDeviceOrientation = currentDeviceOrientation;
// When device is rotated back to portrait, let's unlock screen orientation.
if (previousDeviceOrientation == 'landscape') {
screen.orientation.unlock();
window.removeEventListener(
'deviceorientation',
onDeviceOrientationChange,
);
}
}
},
);
}
Wie Sie sehen, ist das der nahtlose Vollbildmodus, den wir gesucht haben. In diesem Beispiel sehen Sie, wie das funktioniert.
Hintergrundwiedergabe
Wenn Sie feststellen, dass eine Webseite oder ein Video auf der Webseite nicht mehr sichtbar ist, sollten Sie Ihre Analysen entsprechend aktualisieren. Dies kann sich auch auf die aktuelle Wiedergabe auswirken, z. B. wenn ein anderer Titel ausgewählt oder die Wiedergabe pausiert wird oder dem Nutzer benutzerdefinierte Schaltflächen angezeigt werden.
Video bei Änderung der Seitensichtbarkeit pausieren
Mit der Page Visibility API können wir die aktuelle Sichtbarkeit einer Seite ermitteln und über Änderungen der Sichtbarkeit benachrichtigt werden. Mit dem Code unten wird das Video pausiert, wenn die Seite ausgeblendet wird. Das passiert beispielsweise, wenn die Displaysperre aktiv ist oder Sie den Tab wechseln.
Da die meisten mobilen Browser jetzt Steuerelemente außerhalb des Browsers bieten, mit denen ein pausiertes Video fortgesetzt werden kann, empfehlen wir, dieses Verhalten nur festzulegen, wenn der Nutzer die Wiedergabe im Hintergrund zulassen darf.
document.addEventListener('visibilitychange', function () {
// Pause video when page is hidden.
if (document.hidden) {
video.pause();
}
});
Schaltfläche zum Stummschalten bei Änderung der Sichtbarkeit des Videos anzeigen/ausblenden
Wenn Sie die neue Intersection Observer API verwenden, können Sie kostenlos noch detailliertere Informationen abrufen. Mit dieser API erfahren Sie, wann ein beobachtetes Element den Darstellungsbereich des Browsers betritt oder verlässt.
Wir können die Schaltfläche „Stummschalten“ je nach Sichtbarkeit des Videos auf der Seite ein- oder ausblenden. Wenn ein Video wiedergegeben wird, aber derzeit nicht sichtbar ist, wird rechts unten auf der Seite eine Mini-Stummschaltungsschaltfläche angezeigt, über die Nutzer den Videoton steuern können. Mit dem Videoereignis volumechange
wird das Design der Stummschaltungsschaltfläche aktualisiert.
<button id="muteButton"></button>
if ('IntersectionObserver' in window) {
// Show/hide mute button based on video visibility in the page.
function onIntersection(entries) {
entries.forEach(function (entry) {
muteButton.hidden = video.paused || entry.isIntersecting;
});
}
var observer = new IntersectionObserver(onIntersection);
observer.observe(video);
}
muteButton.addEventListener('click', function () {
// Mute/unmute video on button click.
video.muted = !video.muted;
});
video.addEventListener('volumechange', function () {
muteButton.classList.toggle('active', video.muted);
});
Nur ein Video gleichzeitig wiedergeben
Wenn sich auf einer Seite mehrere Videos befinden, sollten Sie nur eines davon wiedergeben und die anderen automatisch pausieren, damit Nutzer nicht mehrere Audiotracks gleichzeitig hören müssen.
// This array should be initialized once all videos have been added.
var videos = Array.from(document.querySelectorAll('video'));
videos.forEach(function (video) {
video.addEventListener('play', pauseOtherVideosPlaying);
});
function pauseOtherVideosPlaying(event) {
var videosToPause = videos.filter(function (video) {
return !video.paused && video != event.target;
});
// Pause all other videos currently playing.
videosToPause.forEach(function (video) {
video.pause();
});
}
Medienbenachrichtigungen anpassen
Mit der Media Session API kannst du auch Medienbenachrichtigungen anpassen, indem du Metadaten für das gerade wiedergegebene Video angibst. Außerdem können Sie damit Medienereignisse wie das Suchen oder Ändern von Titeln verarbeiten, die von Benachrichtigungen oder Medientasten stammen können. In diesem Beispiel sehen Sie, wie das funktioniert.
Wenn in Ihrer Webanwendung Audio oder Video wiedergegeben wird, wird bereits eine Medienbenachrichtigung im Benachrichtigungs-Steuerfeld angezeigt. Unter Android versucht Chrome, geeignete Informationen anzuzeigen. Dazu verwendet es den Titel des Dokuments und das größte Symbolbild, das es finden kann.
Sehen wir uns an, wie Sie diese Medienbenachrichtigung anpassen, indem Sie mit der Media Session API einige Metadaten der Mediensitzung wie Titel, Künstler, Albumname und Artwork festlegen.
playPauseButton.addEventListener('click', function(event) {
event.stopPropagation();
if (video.paused) {
video.play()
<strong>.then(function() {
setMediaSession();
});</strong>
} else {
video.pause();
}
});
function setMediaSession() {
if (!('mediaSession' in navigator)) {
return;
}
navigator.mediaSession.metadata = new MediaMetadata({
title: 'Never Gonna Give You Up',
artist: 'Rick Astley',
album: 'Whenever You Need Somebody',
artwork: [
{src: 'https://dummyimage.com/96x96', sizes: '96x96', type: 'image/png'},
{
src: 'https://dummyimage.com/128x128',
sizes: '128x128',
type: 'image/png',
},
{
src: 'https://dummyimage.com/192x192',
sizes: '192x192',
type: 'image/png',
},
{
src: 'https://dummyimage.com/256x256',
sizes: '256x256',
type: 'image/png',
},
{
src: 'https://dummyimage.com/384x384',
sizes: '384x384',
type: 'image/png',
},
{
src: 'https://dummyimage.com/512x512',
sizes: '512x512',
type: 'image/png',
},
],
});
}
Nach der Wiedergabe müssen Sie die Mediensitzung nicht „freigeben“, da die Benachrichtigung automatisch verschwindet. Beachte, dass der aktuelle navigator.mediaSession.metadata
verwendet wird, wenn die Wiedergabe gestartet wird. Daher müssen Sie es aktualisieren, damit in der Medienbenachrichtigung immer relevante Informationen angezeigt werden.
Wenn Ihre Webanwendung eine Playlist enthält, können Sie den Nutzern erlauben, direkt über die Medienbenachrichtigung mithilfe der Symbole „Vorheriger Titel“ und „Nächster Titel“ durch die Playlist zu blättern.
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('previoustrack', function () {
// User clicked "Previous Track" media notification icon.
playPreviousVideo(); // load and play previous video
});
navigator.mediaSession.setActionHandler('nexttrack', function () {
// User clicked "Next Track" media notification icon.
playNextVideo(); // load and play next video
});
}
Media-Aktions-Handler bleiben erhalten. Das ist dem Ereignis-Listener-Muster sehr ähnlich, mit der Ausnahme, dass beim Bearbeiten eines Ereignisses das Standardverhalten des Browsers beendet wird und dies als Signal verwendet wird, dass Ihre Webanwendung die Medienaktion unterstützt. Daher werden die Medienaktionssteuerungen nur angezeigt, wenn Sie den richtigen Action-Handler festlegen.
Übrigens: Das Rücksetzen eines Media-Action-Handlers ist genauso einfach wie das Zuweisen an null
.
Mit der Media Session API können Sie Medienbenachrichtigungssymbole für „Zurückspulen“ und „Vorspulen“ anzeigen, wenn Sie die Zeitspanne steuern möchten, die übersprungen werden soll.
if ('mediaSession' in navigator) {
let skipTime = 10; // Time to skip in seconds
navigator.mediaSession.setActionHandler('seekbackward', function () {
// User clicked "Seek Backward" media notification icon.
video.currentTime = Math.max(video.currentTime - skipTime, 0);
});
navigator.mediaSession.setActionHandler('seekforward', function () {
// User clicked "Seek Forward" media notification icon.
video.currentTime = Math.min(video.currentTime + skipTime, video.duration);
});
}
Das Symbol „Wiedergabe/Pause“ wird immer in der Medienbenachrichtigung angezeigt und die zugehörigen Ereignisse werden automatisch vom Browser verarbeitet. Wenn das Standardverhalten aus irgendeinem Grund nicht funktioniert, können Sie weiterhin Medienereignisse vom Typ „Wiedergabe“ und „Pause“ verarbeiten.
Das Tolle an der Media Session API ist, dass Medienmetadaten und -steuerelemente nicht nur im Benachrichtigungs- bzw. Infobereich angezeigt werden. Die Medienbenachrichtigung wird automatisch mit allen gekoppelten Wearables synchronisiert. Außerdem wird sie auf dem Sperrbildschirm angezeigt.