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?
This question is related to
javascript
html
google-chrome
audio
The cleanest and simplest solution:
var p = video.play();
if (p !== undefined) p.catch(function(){});
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);
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)
}
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
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');
});
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
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();
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 bountysource.com/issues/
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 :)
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.
This solution helped me:
n.cloneNode(true).play();
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;
}
}
});
}
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
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.
I have the same issue, finally i solve by:
video.src = 'xxxxx';
video.load();
setTimeout(function() {
video.play();
}, 0);
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();
}
};
};
}
});
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.
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.
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();
}
I think they updated the html5 video and deprecated some codecs. It worked for me after removing the codecs.
In the below example:
<video>_x000D_
<source src="sample-clip.mp4" type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'">_x000D_
<source src="sample-clip.webm" type="video/webm; codecs='vp8, vorbis'"> _x000D_
</video>_x000D_
_x000D_
must be changed to_x000D_
_x000D_
<video>_x000D_
<source src="sample-clip.mp4" type="video/mp4">_x000D_
<source src="sample-clip.webm" type="video/webm">_x000D_
</video>
_x000D_
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.
Chrome returns a Promise in newest versions. Otherwise, simply:
n.pause();
n.currentTime = 0;
setTimeout(function() {n.play()}, 0);
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);
});
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
removed all errors: (typescript)
audio.addEventListener('canplay', () => {
audio.play();
audio.pause();
audio.removeEventListener('canplay');
});
try it
n.pause();
n.currentTime = 0;
var nopromise = {
catch : new Function()
};
(n.play() || nopromise).catch(function(){}); ;
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
function playVid() {
if (video.paused && !isPlaying) {
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.
Source: Stackoverflow.com