Как предотвратить ошибку" запрос play() был прерван вызовом pause ()"?

Я сделал веб-сайт, где, если пользователь нажимает, он воспроизводит звук. Чтобы звук не перекрывался, мне пришлось добавить код:

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

но это вызывает ошибку: The play() request was interrupted by a call to pause()
появляться каждый раз, когда звуковое событие запускается сразу после другого триггера. Звуки по-прежнему отлично воспроизводятся, но я хочу, чтобы это сообщение об ошибке постоянно появлялось. Есть идеи?

спасибо заранее!

23 ответов


Я недавно столкнулся с этой проблемой - это может быть условие гонки между play() и pause(). Похоже, есть ссылка на эту проблему, или что-то связанное здесь.

As @Patrick указывает pause не возвращает обещание (или что-то еще), поэтому вышеупомянутое решение не будет работать. Хотя MDN не имеет документов на pause(), в проект WC3 для медиа-элементов он говорит:

СМИ.pause()

устанавливает атрибут paused в true, при необходимости загружая медиа-ресурс.

таким образом, можно также проверить paused атрибут в их обратном вызове тайм-аута.

на основе это великий так ответ, вот как вы можете проверить, действительно ли видео (или нет) играет, поэтому вы можете безопасно запустить play() без ошибки.

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

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

иначе @Patrickответ должны работать.


после нескольких часов работы и работы я нашел идеальный решение.

// Initializing values
var onplaying = true;
var onpause = false;

// On video playing toggle values
video.onplaying = function() {
    onplaying = true;
    onpause = false;
};

// On video pause toggle values
video.onpause = function() {
    onplaying = false;
    onpause = true;
};

// Play video function
function playVid() {      
    if (video.paused && !onplaying) {
        video.play();
    }
} 

// Pause video function
function pauseVid() {     
    if (!video.paused && !onpause) {
        video.pause();
    }
}

после этого, вы можете переключаться воспроизведение/пауза как быстро, как вы можете, он будет работать должным образом.


Я попал в эту проблему, и у меня есть случай, когда мне нужно было нажать pause() затем play (), но при использовании pause().затем () я получаю неопределенное.

Я обнаружил, что если я начал играть 150ms после паузы, это решило проблему. (Надеюсь, Google исправляет в ближайшее время)

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

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

попробуй

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

Это решение помогло мне:

n.cloneNode(true).play();

Я только что опубликовал статью об этой точной проблеме в https://developers.google.com/web/updates/2017/06/play-request-was-interrupted это говорит вам точно, что происходит и как исправить это.


в зависимости от того, насколько сложным вы хотите, чтобы ваше решение, это может быть полезно:

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

Это немного перебор, но помогает при обработке обещания в уникальных сценариях.


решения, предлагаемые здесь, либо не работали для меня, либо где большой, поэтому я искал что-то еще и нашел решение, предложенное @dighan on bountysource.com/issues/

Итак, вот код, который решил мою проблему:

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

Он по-прежнему выдает ошибку в консоли, но по крайней мере на видео :)


может быть, лучшее решение для этого, как я понял. Spec говорит, как цитируется из @JohnnyCoder:

СМИ.pause()

задает для атрибута paused значение true, при необходимости загружая медиаресурс.

--> загрузки

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

указывает состояние готовности носителя HAVE_ENOUGH_DATA = 4

в основном загружайте видео, только если оно еще не загружено. Упомянутая ошибка для меня, потому что видео было не загружать. Может быть, лучше, чем использовать тайм-аут.


удалены все ошибки: (typescript)

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

С live streaming я столкнулся с той же проблемой. и вот мое решение. Из тега html video убедитесь, что удалить "автозапуск" и используйте этот код ниже, чтобы играть.

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

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>

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

я исправил это с помощью некоторого кода ниже:

когда вы хотите играть, используйте следующую конструкцию:

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

вот еще одно решение, если причина в том, что загрузка видео очень медленная, и видео не буферизовано:

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


похоже, что многие программисты сталкивались с этой проблемой. решение должно быть довольно простым. media element return Promise от действий

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

должен делать трюк


вот решение из блога 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)
}

я столкнулся с той же проблемой и решил ее, динамически добавив вместо play(). Таким образом, браузер выяснил, чтобы играть без запуска в состояние гонки.


попытка получить автозапуск видео в цикл, позвонив 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>

когда вы видите ошибку 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);
});

я использовал трюк, чтобы противостоять этой проблеме. Определите глобальную переменную var audio;

и в функции check

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

и в функции stop

audio.pause();
audio = undefined;

Итак, следующий вызов audio.play, аудио будет готово от' 0 ' currentTime

Я

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

но это не сработало. Спасибо.