web-dev-qa-db-ja.com

「play()要求がpause()の呼び出しによって中断された」エラーを回避するにはどうすればよいですか?

ユーザーがクリックすると音を出すWebサイトを作りました。音が重ならないようにするために、コードを追加する必要がありました。

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

しかし、それはエラーを引き起こします:The play() request was interrupted by a call to pause()
サウンドイベントが別のトリガーの直後にトリガーされるたびに表示されます。それでもサウンドはうまく再生されますが、このエラーメッセージが常に表示されるのを防ぎたいと思います。何か案は?

97
Owen M

私も最近この問題に遭遇しました - これはplay()pause()の間の競合状態かもしれません。この問題への参照、または関連するもの があるようです

@ Patrick が指摘するように、pauseは約束(または何も)を返さないので、上記の解決策は機能しません。 MDNにはpause()に関する文書はありませんが、 メディア要素のためのWC3ドラフト には、こう書いてあります。

media.pause()

Paused属性をtrueに設定し、必要に応じてメディアリソースをロードします。

そのため、タイムアウトコールバックのpaused属性も確認することができます。

この素晴らしいSO回答 に基づいて、動画が本当に再生されているかどうかを確認できます。だからあなたは安全にエラーなしでplay()を引き起こすことができます。

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

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

そうでなければ、 @ Patrick答え はうまくいくはずです。

72
JohnnyCoder

何時間もの捜索と仕事の後、私は完璧な解決策を見つけました。

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

その後、できる限り早く再生/一時停止を切り替えることができます。正しく動作します

60
Nebojsa Sapic

私はこの問題にぶつかりました。そして、pause()をしてplay()を押す必要があるケースがありますが、pause()を使うときは未定義になります。

一時停止してから150ミリ秒後に再生を開始すると問題が解決することがわかりました。 (うまくいけば、グーグルはすぐに修正する)

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

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

それを試してみてください

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

この正確な問題に関する記事を https://developers.google.com/web/updates/2017/06/play-request-was-interrupted に掲載しました。正確には何が起こっているのか、そしてそれをどのように修正するか

4

この解決策は私を助けました:

n.cloneNode(true).play();
3
Dmitry Kovganov

ここで提案されている解決策は私にとってもどこでも大丈夫でもうまくいかなかったので、私は何か他のものを探していて bountysource.com/issues/ 上の@dighanによって提案された解決策を見つけました。

だからここに私の問題を解決したコードです:

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

それでもコンソールにエラーが発生しますが、少なくともビデオは再生されています:)

2
Sharpey

あなたがあなたの解決策を望む複雑さの程度に応じて、これは役に立つかもしれません:

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

これはやややり過ぎですが、独自のシナリオで約束を処理するときに役立ちます。

2
The Blue Crayon

このコードは修正されました。

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

Chromeは最新バージョンでPromiseを返します。そうでなければ、単に:

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

ライブストリーミングでも私は同じ問題に直面していました。そして私の修正はこれです。 htmlビデオTAGから "autoplay" を削除し、このコードを使用して再生してください。

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

私が考え出したようにこれのための多分よりよい解決策。仕様は@ JohnohCoderから引用されているように言っています:

media.pause()

Paused属性をtrueに設定し、必要に応じてメディアリソースをロードします。

- >それをロード

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

メディアのレディネス状態を示しますHAVE_ENOUGH_DATA = 4

基本的にはビデオがまだロードされていない場合にのみロードします。動画が読み込まれていないため、エラーが発生しました。タイムアウトを使うよりもたぶん良いです。

1
Christoph Eberl

すべてのエラーを削除しました:(TypeScript)

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

以下のコードで修正しました。

遊びたいときは、次のものを使います。

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');
});
1
Duc Nguyen

私は同じ問題を抱えています。

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

多くのプログラマーがこの問題に遭遇したようです。解決策は非常に単純なはずです。メディア要素はアクションからPromiseを返すので

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

トリックをするべきです

0
pery mimon

これはgooglerブログからの解決策です:

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

すべての新しいブラウザはミュートされているだけで自動再生されるようにビデオをサポートしています。

<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のために同じであるべきです

0
Shobhit Verma

動画のダウンロードが非常に遅く、動画がバッファリングされていないことが理由である場合は、別の解決策があります。

if (videoElement.state.paused) { videoElement.play(); } else if (!isNaN(videoElement.state.duration)) { videoElement.pause(); }

0
Taysky