Videowiedergabe im mobilen Web

François Beaufort
François Beaufort

Wie schaffen Sie die beste mobile Medienerfahrung im Web? So einfach ist das. Alles hängt vom Nutzer-Engagement und der Bedeutung der Medien im Web ab. Seite. Ich denke, wir sind uns alle einig, dass, wenn das Video der Grund für den Besuch eines Nutzers ist, muss die User Experience fesselnd und neu ansprechend sein.

Videowiedergabe im mobilen Web

In diesem Artikel zeige ich Ihnen, wie Sie Ihre Medien und dank einer Fülle von Web-APIs intensiver erleben. Das sind warum wir einen einfachen mobilen Player mit benutzerdefinierten Steuerelemente, Vollbild und Hintergrundwiedergabe. Sie können das Beispiel jetzt ausprobieren. Den Code finden Sie in in unserem GitHub-Repository.

Benutzerdefinierte Einstellungen

<ph type="x-smartling-placeholder">
</ph> HTML-Layout <ph type="x-smartling-placeholder">
</ph> Abbildung 1: HTML-Layout

Wie Sie sehen, verwenden wir für den Mediaplayer das HTML-Layout. ziemlich einfach: Ein <div>-Stammelement enthält ein <video>-Medienelement und ein <div> untergeordnetes Element speziell für Videosteuerelemente.

Videosteuerelemente, die wir später behandeln werden, umfassen eine Wiedergabe-/Pause-Schaltfläche, eine Vollbild- Schaltflächen zum Vor- und Zurückspulen und einige Elemente für die aktuelle Uhrzeit die Aufzeichnung von Dauer und Zeit.

<div id="videoContainer">
  <video id="video" src="file.mp4"></video>
  <div id="videoControls"></div>
</div>

Videometadaten lesen

Warten Sie, bis die Videometadaten geladen sind, um das Video festzulegen. Dauer, aktuelle Uhrzeit und Initialisieren der Fortschrittsanzeige. Das Feld secondsToTimeCode() ist eine von mir geschriebene benutzerdefinierte Dienstfunktion, die wandelt eine Anzahl von Sekunden in einen String im Format "hh:mm:ss" um. das besser geeignet ist, in unserem Fall geeignet.

<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
  })`;
});
<ph type="x-smartling-placeholder">
</ph> Nur Videometadaten
. Abbildung 2: Mediaplayer mit Videometadaten

Video abspielen/anhalten

Nachdem die Videometadaten geladen wurden, fügen wir unsere erste Schaltfläche hinzu, mit der Nutzer das Video mit video.play() und video.pause() je nach Wiedergabestatus.

<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 Videosteuerelemente im click-Event-Listener anzupassen, verwenden wir die Videoereignisse play und pause. Basierend auf unseren Kontrollereignissen flexibel einsetzbar sein (wie Sie später bei der Media Session API sehen werden) zur Synchronisierung unserer Steuerelemente, falls der Browser in die Wiedergabe eingreift. Wenn das Video abgespielt wird, ändern wir Schaltflächenstatus auf „Pause“ und die Videosteuerelemente ausblenden. Wenn das Video pausiert, Ändere den Status der Schaltfläche einfach zu "Play" und die Videosteuerelemente einblenden.

video.addEventListener('play', function () {
  playPauseButton.classList.add('playing');
});

video.addEventListener('pause', function () {
  playPauseButton.classList.remove('playing');
});

Wenn sich die im Attribut currentTime des Videos angegebene Zeit über das timeupdate Videoereignis enthält, aktualisieren wir auch unsere benutzerdefinierten Steuerelemente, sichtbar sind.

video.addEventListener('timeupdate', function () {
  if (videoControls.classList.contains('visible')) {
    videoCurrentTime.textContent = secondsToTimeCode(video.currentTime);
    videoProgressBar.style.transform = `scaleX(${
      video.currentTime / video.duration
    })`;
  }
});

Am Ende des Videos ändern wir den Status der Schaltfläche in "Play", legen das Video fest currentTime auf 0 zurücksetzen und vorerst die Videosteuerelemente anzeigen. Beachten Sie, dass wir Sie können auch automatisch ein weiteres Video laden, wenn der Nutzer einige Art von „Autoplay“ .

video.addEventListener('ended', function () {
  playPauseButton.classList.remove('playing');
  video.currentTime = 0;
});

Vorwärts und rückwärts springen

Fügen wir nun „Zurückspringen“ hinzu, und „nach vorne springen“, Schaltflächen, damit Nutzende 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 sollten Sie den Videostil in den click-Ereignis-Listenern nicht anpassen. verwenden wir die ausgelösten Videoereignisse seeking und seeked, die Videohelligkeit anpassen. 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 Schaltfläche für den Vollbildmodus.

Vollbild

Wir nutzen verschiedene Web-APIs, um eine perfekte und nahtlose Vollbildnutzung. In der Beispiel:

Sie müssen natürlich nicht alle verwenden. Wählen Sie einfach diejenigen aus, und kombinieren sie, um einen benutzerdefinierten Ablauf zu erstellen.

Automatischen Vollbildmodus verhindern

Auf iOS-Geräten wechseln video-Elemente automatisch in den Vollbildmodus, wenn Medien die Wiedergabe beginnt. Da wir versuchen, unsere Kampagnen in mobilen Browsern angezeigt wird, sollten Sie die Einstellung playsinline des video-Elements, um die Inline-Wiedergabe auf dem iPhone zu erzwingen und nicht Vollbildmodus bei Wiedergabebeginn ein. Hinweis: Dies hat keine Nebenwirkungen. in anderen Browsern.

<div id="videoContainer"></div>
  <video id="video" src="file.mp4"></video><strong>playsinline</strong></video>
  <div id="videoControls">...</div>
</div>

Vollbild bei Klick auf Schaltfläche aktivieren/deaktivieren

Da wir nun den automatischen Vollbildmodus verhindern, mit der Fullscreen API in den Vollbildmodus des Videos ein. Wenn Nutzer auf die Schaltfläche für den Vollbildmodus klickt, document.exitFullscreen(), wenn der Vollbildmodus derzeit vom Dokument. Andernfalls fordern Sie mit der -Methode den Vollbildmodus für den Videocontainer an. requestFullscreen(), falls verfügbar, oder Fallback auf webkitEnterFullscreen() am das Videoelement nur unter iOS.

<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 aktivieren/deaktivieren

Da der Nutzer das Gerät im Querformat dreht, fordert automatisch den Vollbildmodus an, um ein immersives Erlebnis zu schaffen. In diesem Fall Sie benötigen die Screen Orientation API, die noch nicht unterstützt wird. und war damals in einigen Browsern immer noch aktiv. Dies ist also unserer ersten progressiven Verbesserung.

So funktioniert's Sobald sich die Bildschirmausrichtung ändert, Vollbild anfordern, wenn sich das Browserfenster im Querformat befindet (d. h. Breite größer als seine Höhe ist). Wenn nicht, 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 beim Klicken auf die Schaltfläche

Da Videos im Querformat besser angesehen werden können, empfehlen wir, den Bildschirm im wenn der Nutzer auf die Schaltfläche für den Vollbildmodus klickt. Wir kombinieren die zuvor verwendete Screen Orientation API und einige Medien Abfragen, um sicherzugehen, dass alles optimal funktioniert.

Sperrbildschirm im Querformat – so einfach wie Anrufe screen.orientation.lock('landscape') Dies sollten wir jedoch nur tun, im Hochformat mit matchMedia('(orientation: portrait)') und kann mit matchMedia('(max-device-width: 768px)') in einer Hand gehalten werden, für Nutzer von Tablets nicht geeignet.

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');
  }
}

Bildschirm bei Ausrichtung des Geräts entsperren

Vielleicht ist Ihnen schon aufgefallen, dass die soeben erstellte Sperrbildschirm-Oberfläche nicht aber perfekt, da bei gesperrtem Bildschirm keine Änderungen der Bildschirmausrichtung auftreten.

Um dieses Problem zu beheben, verwenden Sie am besten die Device Orientation API, verfügbar. Diese API liefert Informationen von der Hardware, die den Position und Bewegung im Weltraum: das Gyroskop und der digitale Kompass Ausrichtung und Beschleunigungsmesser für seine Geschwindigkeit. Wenn wir ein Gerät erkennen Ausrichtung ändern, entsperren wir das Display mit screen.orientation.unlock(), wenn Ein Nutzer hält das Gerät im Hochformat und der Bildschirm ist im Querformat gesperrt.

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 du siehst, ist dies die nahtlose Vollbilderfahrung, nach der wir gesucht haben. Sehen Sie sich das Beispiel an, um dies in Aktion zu sehen.

Hintergrundwiedergabe

Wenn Sie feststellen, dass eine Webseite oder ein Video auf der Webseite nicht mehr sichtbar ist, können Sie Ihre Analysedaten entsprechend aktualisieren. Das könnte sich auch auf wie Sie einen anderen Titel auswählen, ihn anhalten oder benutzerdefinierte Schaltflächen hinzufügen.

Video bei Änderung der Sichtbarkeit der Seite pausieren

Mit der Page Visibility API können wir die aktuelle Sichtbarkeit einer und werden über Änderungen bei der Sichtbarkeit informiert. Mit dem folgenden Code wird das Video pausiert, wenn ist ausgeblendet. Das passiert, wenn die Displaysperre aktiviert ist oder du Instanz.

Da die meisten mobilen Browser jetzt Steuerelemente außerhalb des Browsers anbieten, pausierte Videos fortgesetzt werden, sollten Sie dieses Verhalten nur festlegen, im Hintergrund zu spielen.

document.addEventListener('visibilitychange', function () {
  // Pause video when page is hidden.
  if (document.hidden) {
    video.pause();
  }
});

Schaltfläche „Stummschalten“ bei Änderung der Sichtbarkeit des Videos ein-/ausblenden

Mit der neuen Intersection Observer API können Sie noch detailliertere Einstellungen vornehmen. kostenlos. Diese API informiert Sie, wenn ein beobachtetes Element in den Darstellungsbereich des Browsers.

Hier wird eine Schaltfläche zum Ein-/Ausblenden der Stummschaltung angezeigt, die sich nach der Sichtbarkeit des Videos auf der Seite richtet. Wenn das Video zwar abgespielt, aber derzeit nicht sichtbar ist, erscheint eine Mini-Schaltfläche zum Stummschalten in rechts unten auf der Seite, um dem Nutzer die Kontrolle über den Videoton zu geben. Die Mit dem Videoereignis volumechange wird der Stil der Schaltfläche zum Stummschalten 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 abspielen

Wenn es auf einer Seite mehr als ein Video gibt, empfehle ich dir, nur eines abzuspielen. und die anderen automatisch pausieren, damit die Nutzenden mehrere Audiotracks gleichzeitig abgespielt werden.

// 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 können Sie Medien auch Benachrichtigungen erhalten. Dazu werden Metadaten für das aktuell wiedergegebene Video bereitgestellt. Außerdem ermöglicht die Verarbeitung medienbezogener Ereignisse wie Suchen oder Beobachten von Änderungen die von Benachrichtigungen oder Medientasten stammen. Um dies in Aktion zu sehen, aktivieren Sie Beispiel ansehen.

Wenn Ihre Web-App Audio- oder Videoinhalte wiedergibt, sehen Sie bereits ein Medium Benachrichtigung in der Benachrichtigungsleiste. Auf Android-Geräten bietet Chrome das Beste um die entsprechenden Informationen anzuzeigen, indem Sie den Titel und den größten Symbolbild, das gefunden werden kann.

Sehen wir uns an, wie du diese Medienbenachrichtigung anpassen kannst, indem du einige Medien festlegst Sitzungsmetadaten wie Titel, Künstler, Albumname und Artwork mit dem Media Session API

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',
      },
    ],
  });
}

Wenn die Wiedergabe abgeschlossen ist, Mediensitzung als verschwindet die Benachrichtigung automatisch. Denken Sie daran, dass die aktuellen navigator.mediaSession.metadata wird verwendet, wenn die Wiedergabe beginnt. Dieses sollten Sie sie aktualisieren, damit Ihre Anzeigen Informationen in der Medienbenachrichtigung.

Wenn Ihre Webanwendung eine Playlist bereitstellt, sollten Sie dem Nutzer die Navigation direkt in der Medienbenachrichtigung mit der Schaltfläche "Vorherige Titel“ und „Nächster Titel“ Symbole.

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
  });
}

Handler für Medienaktionen bleiben erhalten. Das ist dem Ereignis sehr ähnlich, Listener-Muster, außer dass der Browser durch die Verarbeitung eines Ereignisses und verwendet dies als Signal, dass Ihre Web-App die Media-Aktion unterstützen. Steuerelemente für Medienaktionen werden daher nur angezeigt, den richtigen Aktions-Handler festgelegt.

Übrigens, das geht genauso einfach wie das Zuweisen eines Handlers zu null.

Mit der Media Session API können Sie und „Nach vorn springen“ Benachrichtigungssymbole für Medien, wenn Sie festlegen möchten, wie lange die Anzeige übersprungen wird.

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);
  });
}

Die Schaltfläche „Wiedergabe/Pause“ wird immer in der Medienbenachrichtigung und in der zugehörigen Ereignisse werden automatisch vom Browser verarbeitet. Wenn aus irgendeinem Grund die Standardeinstellung nicht funktioniert, können Sie trotzdem die "Wiedergabe"-Schaltfläche und „Pausieren“ Medien Ereignisse.

Das Tolle an der Media Session API ist, dass die Benachrichtigungsleiste Metadaten und Steuerelemente für Medien sichtbar sind. Die Medien Benachrichtigungen werden automatisch mit jedem gekoppelten Wearable synchronisiert. Außerdem auf dem Sperrbildschirm angezeigt.

Feedback