How to prevent "The play() request was interrupted by a call to pause()" error?
JavascriptHtmlGoogle ChromeAudioJavascript 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();
}
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.