Как предотвратить "Требование play() было прервано ошибкой вызова pause()"?
Я сделал сайт, где, если пользователь нажимает, он воспроизводит звук. Чтобы звук не перекрывался, мне пришлось добавить код:
n.pause();
n.currentTime = 0;
n.play();
Но это вызывает ошибку: The play() request was interrupted by a call to pause()
Подниматься каждый раз, когда звуковое событие запускается сразу после другого триггера. Звук по-прежнему играет нормально, но я хочу, чтобы это сообщение об ошибке постоянно появлялось. Есть идеи?
Ответы
Ответ 1
Я также недавно столкнулся с этой проблемой - это может быть условие гонки между play()
и pause()
. Похоже, что есть ссылка на эту проблему, или что-то связанное здесь.
Как указывает @Patrick, pause
не возвращает обещание (или что-либо еще), поэтому приведенное выше решение не будет работать. Хотя в MDN нет документов по pause()
, в проекте WC3 для Media Elements говорится:
media.pause()
Устанавливает для атрибута paused значение true, при необходимости загружая медиаресурс.
Таким образом, можно также проверить атрибут paused
в их обратном вызове тайм-аута.
Основываясь на этом великолепном ответе SO, здесь вы можете проверить, действительно ли видео воспроизводится (или нет), поэтому вы можете безопасно запустить play() без ошибки.
var isPlaying = video.currentTime > 0 && !video.paused && !video.ended
&& video.readyState > 2;
if (!isPlaying) {
video.play();
}
В противном случае ответ @Patrick должен работать.
Ответ 2
После нескольких часов поисков и работы я нашел идеальное решение.
// 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();
}
}
После этого вы можете переключать воспроизведение/паузу так быстро, как сможете, это будет работать правильно.
Ответ 3
Я столкнулся с этой проблемой и имею случай, когда мне нужно было нажать pause(), затем play(), но при использовании pause(). then() Я получаю undefined.
Я обнаружил, что если я начал играть за 150 мс после паузы, он решил проблему. (Надеюсь, Google скоро исправится)
playerMP3.volume = 0;
playerMP3.pause();
//Avoid the Promise Error
setTimeout(function () {
playerMP3.play();
}, 150);
Ответ 4
попробуйте
n.pause();
n.currentTime = 0;
var nopromise = {
catch : new Function()
};
(n.play() || nopromise).catch(function(){}); ;
Ответ 5
Я только что опубликовал статью об этой точной проблеме в https://developers.google.com/web/updates/2017/06/play-request-was-interrupted, которая сообщает вам, что именно происходит, и как исправить его.
Ответ 6
Это решение помогло мне:
n.cloneNode(true).play();
Ответ 7
В зависимости от того, насколько сложным вы хотите решение, это может быть полезно:
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);
}
}
Это немного перебор, но помогает при обработке обещаний в уникальных сценариях.
Ответ 8
Решения, предлагаемые здесь, либо не работали для меня, либо там, где они были большими,
поэтому я искал что-то еще и нашел решение, предложенное @dighan на bountysource.com/issues/
Итак, вот код, который решил мою проблему:
var media = document.getElementById("YourVideo");
const playPromise = media.play();
if (playPromise !== null){
playPromise.catch(() => { media.play(); })
}
Он по-прежнему вызывает ошибку в консоли, но по крайней мере воспроизводится видео:)
Ответ 9
Я исправил это с помощью кода ниже:
Когда вы хотите играть, используйте следующее:
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');
});
Ответ 10
Возможно, лучшее решение для этого, как я понял.
Spec говорит, как цитируется @JohnnyCoder:
media.pause()
Устанавливает атрибут паузы в значение true, при необходимости загружая медиа-ресурс.
- > Загрузка
if (videoEl.readyState !== 4) {
videoEl.load();
}
videoEl.play();
указывает состояние готовности среды
HAVE_ENOUGH_DATA = 4
В основном загружать видео, если он еще не загружен. Упомянутая ошибка возникла для меня, потому что видео не было загружено.
Возможно, лучше, чем использовать таймаут.
Ответ 11
удалены все ошибки: (typescript)
audio.addEventListener('canplay', () => {
audio.play();
audio.pause();
audio.removeEventListener('canplay');
});
Ответ 12
С потоковой трансляцией я столкнулся с той же проблемой. и мое исправление - это.
Из html видео TAG убедитесь, что удалить "автовоспроизведение"
и используйте этот ниже код для воспроизведения.
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;
}
}
});
}
Ответ 13
Chrome возвращает Promise в новейших версиях.
В противном случае просто:
n.pause();
n.currentTime = 0;
setTimeout(function() {n.play()}, 0);
Ответ 14
У меня такая же проблема, наконец, я решаю:
video.src = 'xxxxx';
video.load();
setTimeout(function() {
video.play();
}, 0);
Ответ 15
Этот кусок кода исправлен для меня!
Модифицированный код @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();
}
};
};
}
});
Ответ 16
Вот еще одно решение, если причина в том, что ваша загрузка видео очень медленная и видео не буферизовано:
if (videoElement.state.paused) {
videoElement.play();
} else if (!isNaN(videoElement.state.duration)) {
videoElement.pause();
}
Ответ 17
Похоже, что многие программисты столкнулись с этой проблемой.
решение должно быть довольно простым. media element возвращает Promise
из действий, поэтому
n.pause().then(function(){
n.currentTime = 0;
n.play();
})
должен сделать трюк
Ответ 18
вот решение из блога 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)
}
Ответ 19
Все новые браузеры поддерживают видео для автоматического воспроизведения с отключенным звуком, поэтому, пожалуйста, установите что-то вроде этого
<video autoplay muted="muted" loop id="myVideo">
<source src="https://w.r.glob.net/Coastline-3581.mp4" type="video/mp4">
</video>
URL-адрес видео должен соответствовать статусу SSL, если ваш сайт работает с https, тогда URL-адрес видео также должен быть в https и такой же для HTTP
Ответ 20
Я столкнулся с той же проблемой и разрешил ее, динамически добавляя атрибут autoplay
, а не используя play()
. Таким образом, браузер решил сыграть, не вбегая в состояние гонки.
Ответ 21
Попытка получить автовоспроизведение видео в цикле, вызвав 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
Ответ 22
Я думаю, они обновили видео 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>
Ответ 23
Когда вы видите ошибку с 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);
});
Ответ 24
Я использовал трюк, чтобы противостоять этой проблеме.
Определить глобальную переменную var audio;
и в функции check
if(audio === undefined)
{
audio = new Audio(url);
}
и в функции останова
audio.pause();
audio = undefined;
так что следующий вызов audio.play
, звук будет готов от '0' currentTime
Я использовал
audio.pause();
audio.currentTime =0.0;
но это не сработало.
Спасибо.