How to prevent "The play() request was interrupted by a call to pause()" error?

JavascriptHtmlGoogle ChromeAudio

Javascript Problem Overview


I made a website where if the user clicks, it plays a sound. To prevent the sound from overlapping, I had to add the code:

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

But that causes the error: The play() request was interrupted by a call to pause()
To come up each time the sound event is triggered right after another trigger. The sounds still plays fine, but I want to prevent this error message constantly popping up. Any ideas?

Javascript Solutions


Solution 1 - Javascript

I have encountered this issue recently as well - this could be a race condition between play() and pause(). It looks like there is a reference to this issue, or something related here.

As @Patrick points out, pause does not return a promise (or anything), so the above solution won't work. While MDN does not have docs on pause(), in the WC3 draft for Media Elements, it says:

> media.pause()
> > Sets the paused attribute to true, loading the media resource if necessary.

So one might also check the paused attribute in their timeout callback.

Based on this great SO answer, here's a way you can check if the video is (or isn't) truly playing, so you can safely trigger a play() without the error.

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

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

Otherwise, @Patrick's answer should work.

Solution 2 - Javascript

After hours of seaching and working, i found perfect solution.

// Initializing values
var isPlaying = true;

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

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

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

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

After that, you can toggle play/pause as fast as you can, it will work properly.

Solution 3 - Javascript

I have hit this issue, and have a case where I needed to hit pause() then play() but when using pause().then() I get undefined.

I found that if I started play 150ms after pause it resolved the issue. (Hopefully Google fixes soon)

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

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

Solution 4 - Javascript

try it

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

Solution 5 - Javascript

I've just published an article about this exact issue at https://developers.google.com/web/updates/2017/06/play-request-was-interrupted that tells you exactly what is happening and how to fix it.

Solution 6 - Javascript

This solution helped me:

n.cloneNode(true).play();

Solution 7 - Javascript

Depending on how complex you want your solution, this may be useful:

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);
    }
}

This is a bit overkill, but helps when handling a Promise in unique scenarios.

Solution 8 - Javascript

Solutions proposed here either didn't work for me or where to large, so I was looking for something else and found the solution proposed by @dighan on https://www.bountysource.com/issues/33984649-uncaught-in-promise-domexception-the-play-request-was-interrupted-by-a-new-load-request">bountysource.com/issues/</a>

So here is the code that solved my problem:

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

It still throws an error into console, but at least the video is playing :)

Solution 9 - Javascript

I've fixed it with some code bellow:

When you want play, use the following:

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

Similarly, when you want pause:

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

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

Solution 10 - Javascript

Maybe a better solution for this as I figured out. Spec says as cited from @JohnnyCoder :

> media.pause() > > Sets the paused attribute to true, loading the media resource if necessary.

--> loading it

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

indicates the readiness state of the media HAVE_ENOUGH_DATA = 4

Basically only load the video if it is not already loaded. Mentioned error occurred for me, because video was not loaded. Maybe better than using a timeout.

Solution 11 - Javascript

removed all errors: (typescript)

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

Solution 12 - Javascript

With live streaming i was facing the same issue. and my fix is this. From html video TAG make sure to remove "autoplay" and use this below code to play.

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;
                    }
                }
            });
        }

Solution 13 - Javascript

It looks like a lot of programmers encountered this problem. a solution should be quite simple. media element return Promise from actions so

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

should do the trick

Solution 14 - Javascript

Chrome returns a Promise in newest versions. Otherwise, simply:

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

Solution 15 - Javascript

I have the same issue, finally i solve by:

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

Solution 16 - Javascript

This piece of code fixed for me!

Modified code of @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();
                }
            };
        };
       }
      });

Solution 17 - Javascript

Reason one - calling pause without waiting for play promise to resolve

too many answer fo this scenario, so I will just refer to the best doc for that issue:

https://developers.google.com/web/updates/2017/06/play-request-was-interrupted

Reason two - calling play when the tab is not focused

In this case, the browser could interrupt the play by calling pause when the tab is not focus. in order to save resources for the active tab.

So you could just wait for the tab to be focused before calling play:


async function waitForTabFocus() {
  return new Promise((resolve, reject) => {
    const onFocus = () => { resolve(); window.removeEventListener('focus', onFocus) };
    window.addEventListener('focus', onFocus)
  })
}
if (!document.hasFocus()) await this.waitForTabFocus();
videoEl.play();

Solution 18 - Javascript

I have a similar issue, I think doing something like this is the easiest :

video.play().then(() => {
    video.pause();
    video.currentTime = 0;
    video.play();
})

no matter if the video was playing or not, at the end the video will be paused without exception, then reset to zero and played again.

Calling play() even if the video is already playing is working fine, it returns a promise as expected.

Solution 19 - Javascript

Here is another solution if the reason is that your video download is super slow and the video hasn't buffered:

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

Solution 20 - Javascript

here is a solution from googler blog:

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

Solution 21 - Javascript

All new browser support video to be auto-played with being muted only so please put Something like the this

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

URL of video should match the SSL status if your site is running with https then video URL should also in https and same for HTTP

Solution 22 - Javascript

The cleanest and simplest solution:

var p = video.play();
if (p !== undefined) p.catch(function(){});

Solution 23 - Javascript

I ran into the same issue and resolved it by dynamically adding the autoplay attribute rather than using play(). That way the browser figured out to play without running into the race condition.

Solution 24 - Javascript

Trying to get an autoplaying video to loop by calling play() when it ends, the timeout workaround did not work for me (however long the timeout is).

But I discovered that by cloning/replacing the video with jQuery when it ended, it would loop properly.

For example:

<div class="container">
  <video autoplay>
    <source src="video.mp4" type="video/mp4">
  </video>
</div>

and

$(document).ready(function(){
  function bindReplay($video) {
    $video.on('ended', function(e){
      $video.remove();
      $video = $video.clone();
      bindReplay($video);
      $('.container').append($video);
    });
  }
  var $video = $('.container video');
  bindReplay($video);
});

I'm using Chrome 54.0.2840.59 (64-bit) / OS X 10.11.6

Solution 25 - Javascript

I think they updated the html5 video and deprecated some codecs. It worked for me after removing the codecs.

In the below example:

<video>
    <source src="sample-clip.mp4" type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'">
    <source src="sample-clip.webm" type="video/webm; codecs='vp8, vorbis'"> 
</video>

    must be changed to

<video>
    <source src="sample-clip.mp4" type="video/mp4">
    <source src="sample-clip.webm" type="video/webm">
</video>

Solution 26 - Javascript

When you see an error with Uncaught (in promise) This just means that you need to handle the promise with a .catch() In this case, .play() returns a promise. You can decide if you want to log a message, run some code, or do nothing, but as long as you have the .catch() the error will go away.

var n = new Audio();
n.pause();
n.currentTime = 0;
n.play().catch(function(e) {
  // console.log('There was an error', e);
});

Solution 27 - Javascript

Here's my solution (tongue-in-cheek answer):

Sentry.init({
  // ...
  ignoreErrors: [
    'AbortError: The play() request was interrupted',
  ],
});

This error is pointless. If play() was interrupted, then it was interrupted. No need to throw an error about it.

Solution 28 - Javascript

I have used a trick to counter this issue. Define a global variable var audio;

and in the function check

if(audio === undefined)
{
   audio = new Audio(url);
}

and in the stop function

audio.pause();
audio = undefined;

so the next call of audio.play, audio will be ready from '0' currentTime

I used

audio.pause();
audio.currentTime =0.0; 

but it didn't work. Thanks.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOwen MView Question on Stackoverflow
Solution 1 - JavascriptUser 1058612View Answer on Stackoverflow
Solution 2 - JavascriptNebojsa SapicView Answer on Stackoverflow
Solution 3 - JavascriptElimGarakView Answer on Stackoverflow
Solution 4 - JavascriptgestView Answer on Stackoverflow
Solution 5 - JavascriptFrançois BeaufortView Answer on Stackoverflow
Solution 6 - JavascriptDmitry KovganovView Answer on Stackoverflow
Solution 7 - JavascriptThe Blue CrayonView Answer on Stackoverflow
Solution 8 - JavascriptSharpeyView Answer on Stackoverflow
Solution 9 - JavascriptDuc NguyenView Answer on Stackoverflow
Solution 10 - JavascriptChristoph EberlView Answer on Stackoverflow
Solution 11 - JavascriptryanrainView Answer on Stackoverflow
Solution 12 - JavascriptNeutro SolutionsView Answer on Stackoverflow
Solution 13 - Javascriptpery mimonView Answer on Stackoverflow
Solution 14 - JavascriptDavidView Answer on Stackoverflow
Solution 15 - JavascriptlichenbulirenView Answer on Stackoverflow
Solution 16 - JavascriptEliotjseView Answer on Stackoverflow
Solution 17 - Javascriptjony89View Answer on Stackoverflow
Solution 18 - JavascriptLk77View Answer on Stackoverflow
Solution 19 - JavascriptTayskyView Answer on Stackoverflow
Solution 20 - JavascriptstackFishView Answer on Stackoverflow
Solution 21 - JavascriptShobhit VermaView Answer on Stackoverflow
Solution 22 - JavascriptlapinView Answer on Stackoverflow
Solution 23 - JavascriptJannis HellView Answer on Stackoverflow
Solution 24 - JavascriptSilvainView Answer on Stackoverflow
Solution 25 - JavascriptAmrView Answer on Stackoverflow
Solution 26 - JavascriptseantomburkeView Answer on Stackoverflow
Solution 27 - JavascriptffxsamView Answer on Stackoverflow
Solution 28 - JavascriptGippy AulakhView Answer on Stackoverflow