DOMException - Die play() -Anfrage wurde unterbrochen.

François Beaufort
François Beaufort

Bist du gerade auf diesen unerwarteten Medienfehler in der JavaScript-Konsole der Chrome-Entwicklertools gestoßen?

oder

Dann bist du hier richtig. Keine Angst. Im Folgenden erfahren Sie, wodurch das Problem verursacht wird und wie Sie es beheben können.

Ursache

Der folgende JavaScript-Code reproduziert den Fehler "Uncaught (in promise)":

Don'ts
<video id="video" preload="none" src="https://example.com/file.mp4"></video>

<script>
  video.play(); // <-- This is asynchronous!
  video.pause();
</script>

Der obige Code führt in den Chrome-Entwicklertools zu dieser Fehlermeldung:

_Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().

Da das Video aufgrund von preload="none" nicht geladen wird, beginnt die Videowiedergabe nicht unbedingt sofort, nachdem video.play() ausgeführt wurde.

Seit Chrome 50 gibt ein play()-Aufruf für ein <video>- oder <audio>-Element ein Promise zurück. Dies ist eine Funktion, die ein einzelnes Ergebnis asynchron zurückgibt. Wenn die Wiedergabe erfolgreich ist, ist das Versprechen erfüllt und das Ereignis playing wird gleichzeitig ausgelöst. Wenn die Wiedergabe fehlschlägt, wird das Promise zusammen mit einer Fehlermeldung abgelehnt, die den Fehler erklärt.

Das passiert jetzt:

  1. video.play() beginnt mit dem asynchronen Laden des Videocontents.
  2. video.pause() unterbricht das Laden des Videos, da es noch nicht bereit ist.
  3. video.play() lehnt asynchron laut ab.

Da wir das Promise für die Videowiedergabe in unserem Code nicht verarbeiten, wird in den Chrome-Entwicklertools eine Fehlermeldung angezeigt.

Lösung

Da wir nun die Ursache kennen, sehen wir uns nun an, wie wir das Problem beheben können.

Sie sollten nie davon ausgehen, dass ein Medienelement (Video oder Audio) abgespielt wird. Sehen Sie sich das Promise-Objekt an, das von der play-Funktion zurückgegeben wurde, um festzustellen, ob es abgelehnt wurde. Das Versprechen wird erst erfüllt, wenn die Wiedergabe tatsächlich gestartet wurde. Das bedeutet, dass der Code in then() erst dann ausgeführt wird, wenn das Medium abgespielt wird.

Das sollten Sie tun:

Beispiel: Autoplay

<video id="video" preload="none" src="https://example.com/file.mp4"></video>

<script>
  // Show loading animation.
  var playPromise = video.play();

  if (playPromise !== undefined) {
    playPromise.then(_ => {
      // Automatic playback started!
      // Show playing UI.
    })
    .catch(error => {
      // Auto-play was prevented
      // Show paused UI.
    });
  }
</script>
Das sollten Sie tun:

Beispiel: Wiedergabe und Pause

<video id="video" preload="none" src="https://example.com/file.mp4"></video>
 
<script>
  // Show loading animation.
  var playPromise = video.play();
 
  if (playPromise !== undefined) {
    playPromise.then(_ => {
      // Automatic playback started!
      // Show playing UI.
      // We can now safely pause video...
      video.pause();
    })
    .catch(error => {
      // Auto-play was prevented
      // Show paused UI.
    });
  }
</script>

Für dieses einfache Beispiel ist das großartig, aber was ist, wenn Sie mit video.play() ein Video später abspielen können?

Ich verrate dir ein Geheimnis. Sie müssen nicht video.play() verwenden, sondern video.load(). Gehen Sie dazu so vor:

Das sollten Sie tun:

Beispiel: Abruf & Wiedergabe

<video id="video"></video>
<button id="button"></button>

<script>
  button.addEventListener('click', onButtonClick);

  function onButtonClick() {
    // This will allow us to play video later...
    video.load();
    fetchVideoAndPlay();
  }

  function fetchVideoAndPlay() {
    fetch('https://example.com/file.mp4')
    .then(response => response.blob())
    .then(blob => {
      video.srcObject = blob;
      return video.play();
    })
    .then(_ => {
      // Video playback started ;)
    })
    .catch(e => {
      // Video playback failed ;(
    })
  }
</script>

Support für das Promise-Spiel bei Google Play

Beim Erstellen dieses Dokuments gibt HTMLMediaElement.play() ein Promise in Chrome, Edge, Firefox, Opera und Safari zurück.

Gefahrenbereich

<source> in <video> macht play() zusagen, wird nie abgelehnt

Für <video src="not-existing-video.mp4"\> wird das Promise play() wie erwartet abgelehnt, da das Video nicht existiert. Bei <video><source src="not-existing-video.mp4" type='video/mp4'></video> lehnt das Promise play() niemals ab. Dies geschieht nur, wenn keine gültigen Quellen vorhanden sind.

Chromium-Programmfehler