DOMException - Die play() -Anfrage wurde unterbrochen.

François Beaufort
François Beaufort

Haben Sie gerade diesen unerwarteten Medienfehler in der JavaScript-Konsole der Chrome-Entwicklertools gesehen?

oder

Dann sind Sie hier genau richtig. Keine Sorge. Ich erkläre Ihnen, was die Ursache dafür ist und wie Sie das Problem beheben.

Woran liegt das?

Im folgenden JavaScript-Code wird der Fehler „Uncaught (in promise)“ reproduziert:

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

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

Der Code oben 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 nach der Ausführung von preload="none".video.play()

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

So funktionierts:

  1. video.play() startet das asynchrone Laden von Videoinhalten.
  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 nicht in unserem Code verarbeiten, wird in den Chrome-Entwicklertools eine Fehlermeldung angezeigt.

Lösung

Nachdem wir die Ursache gefunden haben, können wir uns überlegen, wie wir das Problem beheben können.

Gehen Sie nicht davon aus, dass ein Medienelement (Video oder Audio) abgespielt wird. Prüfe, ob das von der play-Funktion zurückgegebene Versprechen abgelehnt wurde. Hinweis: Das Versprechen wird erst erfüllt, wenn die Wiedergabe tatsächlich gestartet wurde. Das bedeutet, dass der Code in then() erst ausgeführt wird, wenn die Medien wiedergegeben werden.

Do

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>
Do

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>

Das ist für dieses einfache Beispiel in Ordnung. Was ist aber, wenn du video.play() verwendest, um ein Video später abzuspielen?

Ich verrate Ihnen ein Geheimnis. Sie müssen nicht video.play() verwenden, sondern können auch video.load() verwenden. So gehts:

Do

Beispiel: „Abrufen und wiedergeben“

<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 Play-Versprechen

Zum Zeitpunkt der Erstellung dieses Artikels gibt HTMLMediaElement.play() in Chrome, Edge, Firefox, Opera und Safari ein Promise zurück.

Gefahrenzone

<source> in <video> macht play()-Versprechen, das niemals abgelehnt wird

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

Chromium-Fehler