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

IT技术 javascript html google-chrome audio
2021-01-28 11:31:17

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

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

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

6个回答

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

正如@Patrick指出的那样,pause不返回Promise(或任何东西),因此上述解决方案不起作用。虽然 MDN 没有关于 的文档pause(),但在WC3 的 Media Elements 草案中,它说:

媒体暂停()

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

因此,您还可以检查paused其超时回调中属性。

基于这个很好的 SO answer,这里有一种方法可以检查视频是否正在(或不是)真正播放,因此您可以安全地触发 play() 而不会出现错误。

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

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

否则,@Patrick答案应该有效。

有关超时原因,请参阅@Regency Software回答我扩展了他们的答案,这是一个很好的解决方案。另外,我的回答引用了您在回答开头提供的链接。
2021-03-18 11:31:17
你是如何到达 150ms 作为等待时间的?似乎是 chrome 问题:bugs.chromium.org/p/chromium/issues/detail?id=593273
2021-03-20 11:31:17
正如@regency-software 所说,pause 方法不返回 Promise(没有关于 .pause() 的文档),而只是“未定义”。所以这个解决方案只能应用于 play() 然后 pause() 的情况。
2021-03-26 11:31:17
这不适用于流媒体视频。如果我初始化了 WebRTC 视频,这仍然会给控制台带来异常。
2021-03-27 11:31:17
感谢您提供信息 - 我更新了我的答案以反映@regency 软件发布的内容,这是正确的,他也有一个可行的解决方案:-)。
2021-03-28 11:31:17

经过数小时的搜索和工作,我找到了完美的解决方案

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

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

为什么它没有被标记为正确答案?这绝对是一个解决方案,而不是超时的黑客攻击。
2021-03-19 11:31:17
这就是我解决问题的方法。我觉得这是一个比依赖超时更好的解决方案
2021-03-21 11:31:17
可以请一些人悬赏这个答案以使其更快地获得投票吗?
2021-03-28 11:31:17
@Malcor 谢谢,这将为每个人解决问题
2021-04-07 11:31:17
为什么需要两个变量?我并不是说这是一个糟糕的解决方案。只是试图理解它。
2021-04-08 11:31:17

我遇到了这个问题,并且有一个案例,我需要点击 pause() 然后 play() 但是当使用 pause().then() 时,我得到了未定义。

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

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

//Avoid the Promise Error
setTimeout(function () {      
   playerMP3.play();
}, 150);
所以它几乎是随机值,因为与你的 impl 无关。感谢您的澄清!
2021-03-16 11:31:17
我很好奇您是否使用相同的元素来播放多个声音?这将解释负载问题;尝试通过同一元素播放另一种声音时,仍然加载了一种声音。延迟“可以”阻止它,尽管它是一个笨拙的修复方法,并且可以使用更长/更短的延迟来获得更好/最好的体验。即时清除和重新创建元素是我的 SOP,它跳过了许多音频/视频和内存泄漏。
2021-03-19 11:31:17
不应使用任意的 setTimeout 持续时间来解决竞争条件。
2021-03-29 11:31:17
看起来像一个 chrome 错误:bugs.chromium.org/p/chromium/issues/detail?id=593273
2021-04-07 11:31:17
如果你的意思是150ms?我尝试了一些不同的值,并出于我的目的确定了这一点。我的目标是 Chrome 和 Android,它符合我的应用程序的需求。它可能会更低。
2021-04-11 11:31:17

试试看

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

我刚刚在https://developers.google.com/web/updates/2017/06/play-request-was-interrupted发表了一篇关于这个确切问题的文章,它告诉你到底发生了什么以及如何解决它