sampotts / plyr

A simple HTML5, YouTube and Vimeo player
https://plyr.io
MIT License
26.13k stars 2.91k forks source link

Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause() #331

Open joseluisq opened 7 years ago

joseluisq commented 7 years ago

When the video is stopped and I'm dragging the plyr__progress bar to the next minute, it appears this error:

Plyr v1.8.12

image

sampotts commented 7 years ago

This seems to be a Chrome issue by the looks of things: https://bugs.chromium.org/p/chromium/issues/detail?id=593273

filoghost commented 7 years ago

There is a workaround, not pretty but it should work: http://stackoverflow.com/questions/36803176/how-to-prevent-the-play-request-was-interrupted-by-a-call-to-pause-error

sampotts commented 7 years ago

Closing this and waiting on a Chrome fix

neutrosolutions commented 7 years ago

From html video TAG remove autoplay and use this code to play. 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: // 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: // cannot recover hls.destroy(); break; } } });

alejandroiglesias commented 7 years ago

I would like to reopen this because the aforementioned Chrome issue says the error is fixed for when calling HTMLMediaElement.pause before HTMLMediaElement.play, but calling HTMLMediaElement.play and then HTMLMediaElement.pause while the media is loading still throws the error.

// fixed
media.pause();
media.play();

// won't fix; still shows the issue.
media.play();
media.pause();

HTMLMediaElement.play is async and returns a promise. The error complains about having called HTMLMediaElement.pause before the playback started.

I would like to quote to the Chromium issue owner:

This has been resolved a long time ago. If you are seeing an error but that your website otherwise behave exactly the same, this is not a bug in Chrome but in your website. If you are seeing an error in the console and your website stopped behaving properly, please file another bug with a test page.

In this case, everything behaves exactly the same and it won't get fixed by the Chromium team because the call to HTMLMediaElement.play returns a promise that gets resolved when the media element is ready to play. At that point, the call to HTMLMediaElement.pause can be made. Since we rely on Plyr to handle HTMLMediaElement, it should either know about the promise returned by HTMLMediaElement.play and smartly call HTMLMediaElement.pause when it's resolved, or at least provide a way to interact with the promise by returning it when calling plyr.play. I tried to look at plyr.isPaused() and plyr.getMedia().paused in order to work around it myself, but they're false even though they didn't start playing yet because of buffering. I also tried to use plyr.getMedia().play() instead of plyr.play() in order to get the promise and then always call pause/stop when the promise resolves, but eventually, I get the error again, so maybe I'm missing something. I think that Plyr could keep a track of this promise internally so that users don't need to worry about this issue.

laukstein commented 6 years ago

Chrome post about how to fix this issue https://developers.google.com/web/updates/2017/06/play-request-was-interrupted This issue still isn't fixed, tested on v2.0.13.

pionl commented 6 years ago

Hi there, this can't be fixed at our end, this is problem when the source is still loading and pause/destroy is called (event if the plyr container is removed from dom - chrome indicates pause event).

Only solution is to catch promise in the play/pause (this can be only done in plyr source). Martin.

lichenbuliren commented 6 years ago

I use pretty javascript code solve it:

video.src = 'xxx';
video.load();
setTimeout(function() {
    video.play();
}, 0);
mhluska commented 6 years ago

I'm not able to solve this problem when there are multiple video elements on the screen. The error seems to trigger when I call .play() on one while the previous one is still loading.

ramyahk02 commented 6 years ago

Is there any update on this issue? I still get the error "Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause()." Trying to use the Promise function to handle this gives 'playPromise.then is not a function' error. Any suggestion would help.

sampotts commented 6 years ago

No update but it can be safely ignored. v3 will return a Promise for calls to .play() and will be in beta very soon.

liamtarpey commented 5 years ago

I can still reproduce this when passing autoplay: true to the player config when mounting my component (not triggering play() manually)

Something like this fixes it for me:

if (autoplayWanted) {
    player.play();
}
clark-stevenson commented 5 years ago

I can confirm the same as @liamtarpey and also thank you for the work around.

intelligence commented 5 years ago

Yup, same here. Get Uncaught (in promise) DOMException thrown in my face if I set autoplay: true. If I remove it, the error disappears.

Hydra9268 commented 5 years ago

Can confirm that lichenbuliren's autoplay fix works for audio.

My code below:

var player = new Plyr('#player', { controls: [ 'restart', 'play', 'progress', 'mute', 'volume' ]});
player.source = {
    type: 'audio',
    sources: [{
        src: 'http://u7map-leaflet.s3.amazonaws.com/files/music/' + musicID + '.mp3',
        type: 'audio/mp3'
    }]
};
setTimeout(function() {
    player.play();
}, 0);

The 0ms timeout gives Plyr the time it needs to stop the current audio before the new is loaded and played thus resolving the race condition error. You can see the fix in action at http://kxmode.com/u7map/. Select a series of music pins on the map. Notice how the music stops playing before the new starts. Also notice no errors in the inspector console.

I feel like it would good to add that additional logic to plyr.js for the autoplay option. I don't imagine it would cause problems for a browser that doesn't need it, but it is definitely required for Chrome. If anything, it would be good boilerplate.

electroheadfx commented 5 years ago

I have the same issue with the last version on safari mac. Work in Firefox and chrome. The issue is here: https://github.com/sampotts/plyr/issues/1385

antongorodezkiy commented 5 years ago

Have the same issue in Chromium 75 on Ubuntu

laukstein commented 4 years ago

Why https://github.com/sampotts/plyr isn't considering fixing this issue?

Venryx commented 4 years ago

Just wanted to mention that for me, @lichenbuliren's solution didn't work (the error still showed).

This worked for me instead:

video.pause();
video.addEventListener("canplay", function onCanPlay() {
    video.removeEventListener("canplay", onCanPlay);
    video.play();
});
video.load();
karljakober commented 4 years ago

Still encountering this issue coming from plyr...

laukstein commented 4 years ago

If according to @karljakober this issue still accrues on the latest Plyr, why this issue isn't reopen?

laukstein commented 4 years ago

@karljakober can you add screenshot of issue you notice? Does it post console info or error? Ref https://github.com/pionl/plyr/commit/58677033cc9ec9c3aea1d77f0bd86b1b902034d9#diff-2999d34c7d48fa26668dd28082cd6303R2079

Benny739 commented 4 years ago

For me it's a console.error. Happens when die video is buffering and you press pause.

Edit: For me this looks like a console error. I'm using hls.js and this happens when the video is buffering and the user clicks pause while it's still buffering.

Bildschirmfoto 2020-06-18 um 17 48 05
kush1960 commented 2 years ago

We're still experiencing the same issue using HLS.js Same console error as Benny739 and only happens when pausing a video while it's still buffering.

dohahelmy commented 2 months ago

issue still happening, and no solutions seems to work

Hydra9268 commented 2 months ago

My code example above converted to a promise.

function initializePlayer(musicID) {
  return new Promise((resolve, reject) => {
    try {
      var player = new Plyr('#player', {
        controls: ['restart', 'play', 'progress', 'mute', 'volume']
      });

      player.source = {
        type: 'audio',
        sources: [{
          src: '[URL TO MP3 FILES]',
          type: 'audio/mp3'
        }]
      };

      // Wait for the player to be ready before playing
      player.once('ready', () => {
        player.play().then(() => {
          resolve(player);
        }).catch((error) => {
          reject(error);
        });
      });
    } catch (error) {
      reject(error);
    }
  });
}

// Usage
initializePlayer(musicID)
  .then((player) => {
    console.log('Player initialized and playing:', player);
  })
  .catch((error) => {
    console.error('Error initializing player:', error);
  });

This should resolve any interruption issues.