web-dev-qa-db-fra.com

Comment faire pour éviter l'erreur "La requête play () a été interrompue par un appel à pause ()"?

J'ai créé un site Web sur lequel, si l'utilisateur clique, un son est émis. Pour éviter le chevauchement du son, j'ai dû ajouter le code: 

n.pause();
n.currentTime = 0;
n.play();

Mais cela provoque l'erreur suivante: The play() request was interrupted by a call to pause()
À venir chaque fois que l'événement sonore est déclenché juste après un autre déclencheur. Les sons continuent à bien jouer, mais je veux éviter que ce message d'erreur n'apparaisse constamment. Des idées?

Merci d'avance!

95
Owen M

J'ai récemment rencontré ce problème également - il pourrait s'agir d'une situation de concurrence critique entre play() et pause(). On dirait qu'il y a une référence à cette question, ou quelque chose en rapport avec ici .

Comme @Patrick le fait remarquer, pause ne retourne pas une promesse (ou quoi que ce soit), de sorte que la solution ci-dessus ne fonctionnera pas. Alors que MDN n'a pas de documentation sur pause(), dans le brouillon WC3 pour les éléments multimédias , il est indiqué:

media.pause () 

Définit l'attribut en pause sur true, chargeant la ressource multimédia si nécessaire.

Donc, on peut également vérifier l'attribut paused dans leur rappel de délai d'attente.

Sur la base de this great SO answer , voici un moyen de vérifier si la vidéo est (ou non) en cours de lecture, de sorte que vous puissiez déclencher un jeu () sans erreur.

var isPlaying = video.currentTime > 0 && !video.paused && !video.ended 
    && video.readyState > 2;

if (!isPlaying) {
  video.play();
}

Sinon, answer de @Patrick devrait fonctionner.

71
JohnnyCoder

Après des heures de recherche et de travail, j’ai trouvé la solution parfaitesolution.

// Initializing values
var onplaying = true;
var onpause = false;

// On video playing toggle values
video.onplaying = function() {
    onplaying = true;
    onpause = false;
};

// On video pause toggle values
video.onpause = function() {
    onplaying = false;
    onpause = true;
};

// Play video function
function playVid() {      
    if (video.paused && !onplaying) {
        video.play();
    }
} 

// Pause video function
function pauseVid() {     
    if (!video.paused && !onpause) {
        video.pause();
    }
}

Après cela, vous pouvez basculerplay/pauseaussi vite que possible,cela fonctionnera correctement.

60
Nebojsa Sapic

J'ai frappé ce problème, et j'ai eu un cas où j'avais besoin de frapper pause () puis play () mais lorsque j'utilise pause (). Then (), je suis indéfini.

J'ai trouvé que si je commençais à jouer 150 ms après une pause, le problème était résolu. (Espérons que Google corrige bientôt)

playerMP3.volume = 0;
playerMP3.pause();

//Avoid the Promise Error
setTimeout(function () {      
   playerMP3.play();
}, 150);
17
Patrick

l'essayer

n.pause();
n.currentTime = 0;
var nopromise = {
   catch : new Function()
};
(n.play() || nopromise).catch(function(){}); ;
5
gest

Je viens de publier un article sur cette question à l'adresse suivante: https://developers.google.com/web/updates/2017/06/play-request-was-interrupted qui vous explique exactementcomment le réparer.

4
François Beaufort

Cette solution m'a aidé à:

n.cloneNode(true).play();
3
Dmitry Kovganov

Les solutions proposées ici ne fonctionnaient pas pour moi ou pour les grands, alors je cherchais autre chose et trouvai la solution proposée par @dighan sur bountysource.com/issues/

Alors voici le code qui a résolu mon problème:

var media = document.getElementById("YourVideo");
const playPromise = media.play();
if (playPromise !== null){
    playPromise.catch(() => { media.play(); })
}

Il y a toujours une erreur dans la console, mais au moins, la vidéo est en cours de lecture :)

2
Sharpey

Selon la complexité de votre solution, cela peut être utile:

var currentPromise=false;    //Keeps track of active Promise

function playAudio(n){
    if(!currentPromise){    //normal behavior
        n.pause();
        n.currentTime = 0;
        currentPromise = n.play();    //Calls play. Will store a Promise object in newer versions of chrome;
                                      //stores undefined in other browsers
        if(currentPromise){    //Promise exists
            currentPromise.then(function(){ //handle Promise completion
                promiseComplete(n);
            });
        }
    }else{    //Wait for promise to complete
        //Store additional information to be called
        currentPromise.calledAgain = true;
    }
}

function promiseComplete(n){
    var callAgain = currentPromise.calledAgain;    //get stored information
    currentPromise = false;    //reset currentPromise variable
    if(callAgain){
        playAudio(n);
    }
}

C'est un peu exagéré, mais aide lors de la gestion d'une promesse dans des scénarios uniques.

2
The Blue Crayon

Ce morceau de code corrigé pour moi!

Code modifié de @JohnnyCoder 

HTML:

 <video id="captureVideoId" muted width="1280" height="768"></video>
                <video controls id="recordedVideoId" muted width="1280" 
 style="display:none;" height="768"></video>

JS:

  var recordedVideo = document.querySelector('video#recordedVideoId');
  var superBuffer = new Blob(recordedBlobs, { type: 'video/webm' });
  recordedVideo.src = window.URL.createObjectURL(superBuffer);
  // workaround for non-seekable video taken from
  // https://bugs.chromium.org/p/chromium/issues/detail?id=642012#c23
  recordedVideo.addEventListener('loadedmetadata', function () {
    if (recordedVideo.duration === Infinity) {
        recordedVideo.currentTime = 1e101;
        recordedVideo.ontimeupdate = function () {
            recordedVideo.currentTime = 0;
            recordedVideo.ontimeupdate = function () {
                delete recordedVideo.ontimeupdate;
                var isPlaying = recordedVideo.currentTime > 0 && 
     !recordedVideo.paused && !recordedVideo.ended && 
      recordedVideo.readyState > 2;
                if (isPlaying) {
                    recordedVideo.play();
                }
            };
        };
       }
      });
1
Eliotjse

Chrome renvoie une promesse dans les dernières versions . Sinon, simplement:

        n.pause();
        n.currentTime = 0;
        setTimeout(function() {n.play()}, 0);
1
David

Avec la diffusion en direct, je faisais face au même problème. et mon correctif est this . De la vidéo html TAG, assurez-vous de supprimer "autoplay" et utilisez le code ci-dessous pour le lire.

if (Hls.isSupported()) {
            var video = document.getElementById('pgVideo');
            var hls = new Hls();
            hls.detachMedia();
            hls.loadSource('http://wpc.1445X.deltacdn.net/801885C/lft/Apple/TSONY.m3u8');
            hls.attachMedia(video);
            hls.on(Hls.Events.MANIFEST_PARSED, function () {
                video.play();
            });
            hls.on(Hls.Events.ERROR, function (event, data) {
                if (data.fatal) {
                    switch (data.type) {
                        case Hls.ErrorTypes.NETWORK_ERROR:
                            // when try to recover network error
                            console.log("fatal network error encountered, try to recover");
                            hls.startLoad();
                            break;
                        case Hls.ErrorTypes.MEDIA_ERROR:
                            console.log("fatal media error encountered, try to recover");
                            hls.recoverMediaError();
                            break;
                        default:
                            // when cannot recover
                            hls.destroy();
                            break;
                    }
                }
            });
        }
1
Neutro Solutions

Peut-être une meilleure solution pour cela, comme je l'ai découvert . Spec dit comme cité dans @JohnnyCoder:

media.pause ()

Définit l'attribut en pause sur true, chargeant la ressource multimédia si nécessaire.

-> le charger

if (videoEl.readyState !== 4) {
    videoEl.load();
}
videoEl.play();

indique l'état de préparation du support HAVE_ENOUGH_DATA = 4

Fondamentalement, ne chargez la vidéo que si elle n'est pas déjà chargée. Une erreur mentionnée s'est produite pour moi, car la vidéo n'a pas été chargée ..__ Peut-être mieux que d'utiliser un délai d'attente.

1
Christoph Eberl

supprimé toutes les erreurs: (TypeScript) 

audio.addEventListener('canplay', () => {
    audio.play();
    audio.pause();
    audio.removeEventListener('canplay');
}); 
1
ryanrain

Je l'ai corrigé avec du code ci-dessous:

Lorsque vous voulez jouer, utilisez ce qui suit:

var video_play = $('#video-play');
video_play.on('canplay', function() {
 video_play.trigger('play');
});

De même, quand vous voulez faire une pause:

var video_play = $('#video-play');
video_play.trigger('pause');

video_play.on('canplay', function() {
  video_play.trigger('pause');
});
1
Duc Nguyen

J'ai le même problème, enfin je résous par:

video.src = 'xxxxx';
video.load();
setTimeout(function() {
  video.play();
}, 0);
1
lichenbuliren

Il semble que beaucoup de programmeurs ont rencontré ce problème. une solution devrait être assez simple. l'élément média renvoie Promise des actions afin 

n.pause().then(function(){
    n.currentTime = 0;
    n.play();
})

devrait faire l'affaire

0
pery mimon

voici une solution du blog googler:

var video = document.getElementById('#video')
var promise = video.play()
//chrome version 53+
if(promise){
    promise.then(_=>{
        video.pause()
    })
}else{
    video.addEventListener('canplaythrough', _=>{
        video.pause()
    }, false)
}
0
stackFish

Toutes les nouvelles vidéos prises en charge par le navigateur doivent être lues automatiquement, alors mettez s'il vous plaît quelque chose comme ceci

<video autoplay muted="muted" loop id="myVideo">
  <source src="https://w.r.glob.net/Coastline-3581.mp4" type="video/mp4">
</video>

L'URL de la vidéo doit correspondre au statut SSL si votre site fonctionne avec https. L'URL de la vidéo doit également être en https et identique pour HTTP

0
Shobhit Verma

Voici une autre solution si la raison en est que le téléchargement de votre vidéo est trop lent et que la vidéo n'a pas été mise en mémoire tampon:

if (videoElement.state.paused) { videoElement.play(); } else if (!isNaN(videoElement.state.duration)) { videoElement.pause(); }

0
Taysky