DOMException : la requête play() a été interrompue.

François Beaufort
François Beaufort

Est-ce que vous venez de tomber sur cette erreur multimédia inattendue dans les outils pour les développeurs Chrome ? Console JavaScript ?

ou

Vous êtes au bon endroit. N'ayez crainte. Je vais vous expliquer la cause de ce problème et comment le résoudre.

Quelle en est la cause ?

Vous trouverez ci-dessous du code JavaScript qui reproduit le message "Uncaught (in promesse)" (Uncaught (dans la promesse) ci-dessous). l'erreur qui s'affiche:

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

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

Le code ci-dessus génère le message d'erreur suivant dans les outils pour les développeurs Chrome:

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

La vidéo n'étant pas chargée en raison de preload="none", la lecture de la vidéo ne s'effectue pas correctement. ne démarre pas nécessairement immédiatement après l'exécution de video.play().

De plus, depuis Chrome 50, un appel play() sur un <video> ou un <audio> renvoie une promesse, une fonction qui renvoie un seul résultat. de manière asynchrone. Si la lecture réussit, la promesse est remplie et l'erreur L'événement playing est déclenché en même temps. En cas d'échec de la lecture, la promesse est rejetées avec un message d'erreur expliquant l'échec.

Voici ce qui se passe:

  1. video.play() commence à charger du contenu vidéo de manière asynchrone.
  2. video.pause() interrompt le chargement de la vidéo, car elle n'est pas encore prête.
  3. video.play() rejette de manière asynchrone fort.

Étant donné que nous ne gérons pas la promesse de lecture vidéo dans notre code, un message d'erreur s'affiche dans les outils pour les développeurs Chrome.

Solution

Maintenant que nous avons identifié la cause racine, voyons ce que nous pouvons faire pour résoudre ce problème.

Tout d'abord, ne présumez jamais qu'un élément multimédia (vidéo ou audio) va être lu. Regardez La promesse renvoyée par la fonction play pour voir si elle a été refusée. Il est sachez que la promesse ne sera honorée que lorsque la lecture a démarré, ce qui signifie que le code dans then() ne s'exécutera que lorsque le média en cours de lecture.

À faire

Exemple: lecture automatique

<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>
À faire

Exemple: Jouer et Mettre en 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>

C'est parfait pour cet exemple simple, mais que se passe-t-il si vous utilisez video.play() pour être de pouvoir lire une vidéo plus tard ?

Je vais te raconter un secret. Vous n'êtes pas obligé d'utiliser video.play(), vous pouvez utiliser video.load(), puis procédez comme suit:

À faire

Exemple: Extraire et Lire

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

Assistance Play Prom

Au moment de la rédaction de ce document, HTMLMediaElement.play() renvoie une promesse dans Chrome, Edge, Firefox, Opera et Safari.

Zone de danger

Avec <source> dans <video>, play() promet de ne jamais refuser

Pour <video src="not-existing-video.mp4"\>, la promesse play() rejette la requête attendu, car la vidéo n'existe pas. Pour <video><source src="not-existing-video.mp4" type='video/mp4'></video>, la promesse play() ne rejette jamais. Cela ne se produit que s'il n'y a pas de source valide.

Bug Chromium