如何防止“播放()请求被暂停()调用打断”错误?

我做了一个网站,如果用户点击,它播放声音。为了防止声音重叠,我必须添加代码:

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

但这导致了错误: The play() request was interrupted by a call to pause()
每次声音事件在另一个触发器之后被触发时都会出现。声音仍然播放良好,但我想防止这个错误消息不断弹出。有什么想法吗?

201405 次浏览

我最近也遇到过这个问题-这可能是 play()pause()之间的竞争条件。看起来有一个关于这个问题的参考,或者与 给你相关的东西。

正如 @ Patrick指出的,pause不返回承诺(或任何东西) ,因此上述解决方案不会起作用。虽然 MDN 在 pause()上没有文档,但在 WC3媒体元素草案上,它说:

媒体,暂停()

将暂停属性设置为 true,必要时加载媒体资源。

因此,人们还可以在超时回调中检查 paused属性。

基于 这个伟大的答案,这里有一种方法可以检查视频是否真正在播放,所以您可以安全地触发播放()没有错误。

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


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

否则,@ Patrick回答应该可以工作。

我碰到了这个问题,并且有一个情况,我需要按下 stop ()然后播放() ,但是当使用 stop ()时。然后()我得到未定义的。

我发现如果我在暂停后开始播放150毫秒,问题就解决了。(希望谷歌能尽快修复)

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


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

根据您希望解决方案的复杂程度,这可能是有用的:

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

这有点过分了,但是在独特的情况下处理一个斜面有所帮助。

我遇到了同样的问题,并通过动态添加 autoplay属性而不是使用 play()来解决它。这样浏览器就不会陷入比赛状态。

我使用了一种技巧来解决这个问题。 定义一个全局变量 var 音频;

在功能检查中

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

以及停止功能

audio.pause();
audio = undefined;

因此,下一次调用 audio.play,音频将从’0’当前时间准备

我用过

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

但没成功。 谢谢。

试图让一个自动播放视频循环通过调用 play()当它结束时,超时解决方案不适合我(无论超时多长)。

但是我发现,通过在视频结束时用 jQuery 克隆/替换视频,它会正确地循环。

例如:

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

还有

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

我使用的是 Chrome 54.0.2840.59(64位)/OS X 10.11.6

我想他们更新了 html5视频,并且废弃了一些解码器。 我把解码器去掉之后就成功了。

在下面的例子中:

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

我用下面的代码修复了它:

当你想玩的时候,用下面的方法:

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

同样,当你想要暂停时:

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


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

经过几个小时的寻找和工作,我找到了完美的 解决方案

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

然后,你可以尽快切换 播放/暂停它会正常工作

试试看

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

当你看到一个错误与 Uncaught (in promise)这只是意味着你需要处理的承诺与 .catch()在这种情况下,.play()返回一个承诺。您可以决定是否要记录消息、运行一些代码或什么都不做,但是只要您有 .catch(),错误就会消失。

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

这里提出的解决方案要么对我不起作用,要么对大公司不起作用, 所以我在寻找其他的东西,发现了@dighan 提出的解决 bountysource.com/issues/

下面是解决我问题的代码:

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

它仍然会在控制台中抛出一个错误,但至少视频正在播放:)

也许我找到了更好的解决办法。 Spec 引自@JohnnyCoder:

媒体,暂停()

将暂停属性设置为 true,必要时加载媒体资源。

—— > 载入

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

显示媒体的准备状态 有足够的数据 = 4

基本上只加载视频,如果它还没有加载。我提到的错误发生了,因为视频没有加载。 也许比暂停要好。

如果你的视频下载速度非常慢而且没有缓冲,这里还有另一个解决方案:

如果(video Element.state 暂停){ Play () ; } else if (! isNaN (video Element.state. 期)){ 暂停() ; }

这个解决方案帮助了我:

n.cloneNode(true).play();

删除所有错误: (打字稿)

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

在直播的时候,我也面临着同样的问题,而我的解决办法就是这个。 从 html 视频标签确保 删除“自动播放” 并使用下面的代码来播放。

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

我刚刚在 https://developers.google.com/web/updates/2017/06/play-request-was-interrupted上发表了一篇关于这个问题的文章,告诉你正在发生什么和 怎么补救

看起来很多程序员都遇到了这个问题。 一个解决方案应该相当简单。 media 元素从操作返回 Promise,因此

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

应该能行

这里有一个来自谷歌博客的解决方案:

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

Chrome 在最新版本中返回了一个承诺。 否则,简单地说:

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

我有同样的问题,最后我解决了:

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

这段代码是为我修好的!

@ JohnnyCoder 的修改代码

HTML:

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

约翰逊:

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

所有新的浏览器支持视频将自动播放与静音只,所以请把这样的东西

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

如果您的站点使用 https 运行,视频的 URL 应该匹配 SSL 状态,那么视频的 URL 也应该使用 https,HTTP 也是如此

最干净的最简单的解决方案:

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

原因一呼叫暂停而不等待游戏承诺解决

对于这种情况,答案太多了,所以我只需要参考这个问题的最佳文档:

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

当选项卡未被聚焦时两次调用播放的原因

在这种情况下,当选项卡不是焦点时,浏览器可以通过调用 pause来中断 play。以便为活动选项卡节省资源。

因此,你可以等待标签被集中,然后再调用 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();

我有一个类似的问题,我认为做这样的事情是最容易的:

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

无论视频是否播放,视频结束时都会无一例外地暂停,然后重置为零,再次播放。

调用 play()即使视频已经播放正常工作,它返回一个预期的承诺。

以下是我的解决方案(开玩笑的回答) :

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

这个错误是没有意义的。如果 play()被中断,那么它就被中断了。没有必要抛出关于它的错误。