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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36803176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:34:37  来源:igfitidea点击:

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

javascripthtmlgoogle-chromeaudio

提问by Owen M

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?

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

采纳答案by JohnnyCoder

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.

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

As @Patrickpoints out, pausedoes 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:

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

media.pause()

Sets the paused attribute to true, loading the media resource if necessary.

媒体暂停()

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

So one might also check the pausedattribute in their timeout callback.

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

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.

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

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

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

Otherwise, @Patrick's answershould work.

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

回答by Nebojsa Sapic

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/pauseas fast as you can, it will work properly.

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

回答by Patrick

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.

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

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

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

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

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

回答by Fran?ois Beaufort

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

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

回答by gest

try it

尝试一下

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

回答by Dmitry Kovganov

This solution helped me:

这个解决方案帮助了我:

n.cloneNode(true).play();

回答by Sharpey

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/

此处提出的解决方案要么对我不起作用,要么对我不起作用,所以我正在寻找其他解决方案,并在bountysource.com/issues/上找到了 @dighan 提出的解决方案

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

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

回答by The Blue Crayon

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.

这有点矫枉过正,但在特殊情况下处理 Promise 时会有所帮助。

回答by Christoph Eberl

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

正如我发现的那样,也许这是一个更好的解决方案。Spec 引用自 @JohnnyCoder :

media.pause()

Sets the paused attribute to true, loading the media resource if necessary.

媒体暂停()

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

--> loading it

--> 加载

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

indicates the readiness state of the media HAVE_ENOUGH_DATA = 4

表示媒体的就绪状态 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.

基本上只加载尚未加载的视频。提到的错误发生在我身上,因为视频没有加载。也许比使用超时更好。

回答by ryanrain

removed all errors: (typescript)

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

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