"Play () isteği bir pause () çağrısı" hatasıyla kesintiye uğradı nasıl önlenir?


107

Kullanıcı tıkladığında ses çıkardığı bir web sitesi yaptım. Sesin çakışmasını önlemek için kodu eklemem gerekiyordu:

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

Ancak bu, hataya neden olur: The play() request was interrupted by a call to pause()
Başka bir tetikleyiciden hemen sonra ses olayı her tetiklendiğinde ortaya çıkması. Sesler hala iyi çalışıyor, ancak bu hata mesajının sürekli olarak ortaya çıkmasını önlemek istiyorum. Herhangi bir fikir?


Bu bir hata mı yoksa bir uyarı mı?
dandavis

Bu bir hata, işte tam hata: Yakalanmamış (sözde) DOMException: play () isteği bir pause () çağrısı ile kesildi.
Owen M

7
bu daha yeni bir hata, endişelenmeyin: bugs.chromium.org/p/chromium/issues/detail?id=593273
dandavis

3
Bunun basit çözümü, birbiri ardına oynatmayı veya duraklamayı çağırmamaktır. Ne zaman duraklatılacağını veya oynatılacağını belirlemek için bunun yerine medya olaylarını kullanın. Örnek: onCanPlay(). Tüm bu cevaplar kirli haklardır.
Martin Dawson

1
Tam tersi problemim vardı. n.play() O zaman denedim n.pause(). Bunun için, bu Web Temelleri makalesi çözümü açıklamaktadır. tl; dr:n.play().then(() => { n.pause()})
totymedli

Yanıtlar:


84

Son zamanlarda bu sorunla da karşılaştım - bu, play()ve arasındaki bir yarış durumu olabilir pause(). Görünüşe göre bu konuya bir referans var veya burada ilgili bir şey var .

@ Patrick'in işaret ettiği gibi , pausebir söz (veya herhangi bir şey) geri dönmez, bu nedenle yukarıdaki çözüm işe yaramaz. MDN'de dokümanlar olmasa da pause(), Media Elements için WC3 taslağında şöyle diyor:

media.pause ()

Duraklatılmış özniteliği true olarak ayarlar, gerekirse medya kaynağını yükler.

Dolayısıyla paused, zaman aşımı geri aramasında özniteliği de kontrol edebilirsiniz .

Bu harika SO cevabına dayanarak , videonun gerçekten oynatılıp oynatılmadığını (veya oynamadığını) kontrol etmenin bir yolu, böylece hata olmadan bir oynatmayı () güvenli bir şekilde tetikleyebilirsiniz.

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

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

Aksi takdirde, @Patrick bireyin cevabı çalışmalıdır.


1
@ Regency-software'in dediği gibi, pause yöntemi bir Söz döndürmez (.pause () üzerinde belge yoktur), sadece "tanımsız". Dolayısıyla bu çözüm sadece play () ve ardından pause () vakalarında uygulanabilir.
Splact

Bilgi için teşekkürler - Cevabımı @regency yazılımının gönderdiği şeyi yansıtacak şekilde güncelledim, bu doğruydu ve ayrıca çalışan bir çözümü de vardı :-).
JohnnyCoder

bekleme süresi olarak 150 ms'ye nasıl ulaştınız? bir Chrome sorunu gibi görünüyor: bugs.chromium.org/p/chromium/issues/detail?id=593273
connect2krish

Bkz @Regency Yazılım 'ın cevabını zaman aşımı nedenle. İyi bir çözüm olan cevaplarını genişlettim. Ayrıca cevabım, cevabın başında verdiğiniz bağlantıya atıfta bulunuyor.
JohnnyCoder

Bu, video akışı için işe yaramaz. WebRTC videosunu başlattıysam, bu hala konsola istisna veriyor.
Stepan Yakovenko

70

Saatlerce araştırıp çalıştıktan sonra mükemmel bir çözüm buldum .

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

Bundan sonra, oynatma / duraklatma işlemini olabildiğince hızlı değiştirebilirsiniz , düzgün çalışacaktır .


1
Sorunu bu şekilde başardım. Bunun zaman aşımına güvenmekten çok daha iyi bir çözüm olduğunu düşünüyorum
Malcor

@Malcor Teşekkürler, bu herkes için sorunu çözecek
Nebojsa Sapic

Bazıları bu cevaba daha hızlı oy almak için bir ödül koyabilir mi?
AddingColor

1
Neden doğru cevap olarak işaretlenmemiş? Kesinlikle bu bir çözüm, zaman aşımına sahip bir hack değil.
jeron-diovis

15
Neden iki değişken gerekli? Bunun kötü bir çözüm olduğunu söylemiyorum. Sadece sallamaya çalışıyorum.
benevolentprof

20

Bu sorunu çözdüm ve pause () tuşuna basıp ardından play () tuşuna basmam gereken bir durum var ama pause () kullanılırken () tanımsız kalıyorum.

Duraklattıktan sonra 150 ms oynamaya başlarsam sorunu çözdüğünü gördüm. (Umarım Google yakında düzeltir)

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

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

150ms demek istiyorsan? Birkaç farklı değer denedim ve amacım için buna karar verdim. Chrome ve Android'i hedefliyordum ve uygulamamın ihtiyaçlarına uyuyordu. Daha düşük olabilir.
Patrick

3
bu nedenle, impl'nizden başka hiçbir şeyle ilgili olmadığı için neredeyse rastgele bir değerdir. açıklama için teşekkürler !
y_nk

Merak ediyorum, birden fazla ses çalmak için aynı öğeyi kullanıyor musunuz? Bu, yük sorununu açıklar; aynı eleman üzerinden başka bir ses çalmaya çalışırken bir ses hala yüklü. Gecikme "onu durdurabilir", ancak daha iyi / en iyi deneyim için kesin bir düzeltme ve daha uzun / daha kısa gecikmeler kullanılabilir. Öğeleri anında temizlemek ve yeniden oluşturmak, bir dizi ses / video ve bellek sızıntısını atlayan SOP'um oldu.
ağaç


8
Yarış koşullarını çözmek için rastgele setTimeout süreleri kullanılmamalıdır.
Gadget Blaster


5

dene

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


2

Çözümünüzü ne kadar karmaşık istediğinize bağlı olarak, bu yararlı olabilir:

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

Bu biraz abartılıdır, ancak benzersiz senaryolarda bir Sözü işlerken yardımcı olur.


2

Burada önerilen çözümler benim için ya da nerede işe yaramadı, bu yüzden başka bir şey arıyordum ve @dighan tarafından önerilen çözümü bountysource.com/issues/ adresinde buldum.

İşte sorunumu çözen kod:

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

Yine de konsola bir hata atıyor, ancak en azından video oynatılıyor :)


1

Belki de anladığım kadarıyla bunun için daha iyi bir çözüm. Spec, @JohnnyCoder'den alıntılandığı gibi:

media.pause ()

Duraklatılmış özniteliği true olarak ayarlar, gerekirse medya kaynağını yükler.

-> yükleniyor

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

medyanın hazır olma durumunu gösterir HAVE_ENOUGH_DATA = 4

Temel olarak videoyu yalnızca önceden yüklenmemişse yükleyin. Video yüklenmediği için benim için belirtilen bir hata oluştu. Belki zaman aşımı kullanmaktan daha iyidir.


1

tüm hataları kaldırdı: (typcript)

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

1

Canlı yayınla aynı sorunla karşı karşıyaydım. ve benim düzeltmem bu. Html video TAG'den "otomatik oynatmayı" kaldırdığınızdan emin olun ve oynatmak için aşağıdaki kodu kullanın.

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
Harika çözüm !!
Cüneyd Muhtar

1

Chrome, en yeni sürümlerde bir Söz verir. Aksi takdirde, basitçe:

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

1

Aynı sorunu yaşıyorum, sonunda şu şekilde çözüyorum:

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

1

Bu kod parçası benim için düzeltildi!

@JohnnyCoder'ın değiştirilmiş kodu

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

Bunu aşağıdaki kodlarla düzelttim:

Oynamak istediğinizde aşağıdakileri kullanın:

var video_play = $('#video-play');
video_play.on('canplay', function() {
 video_play.trigger('play');
});

Benzer şekilde, duraklatmak istediğinizde:

var video_play = $('#video-play');
video_play.trigger('pause');

video_play.on('canplay', function() {
  video_play.trigger('pause');
});

0

Nedeni video indirmenizin çok yavaş olması ve videonun arabelleğe alınmamış olmasıysa, işte başka bir çözüm:

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


0

Görünüşe göre pek çok programcı bu sorunla karşılaştı. bir çözüm oldukça basit olmalıdır. medya öğesi Promiseeylemlerden geri dönüyor

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

hile yapmalı


0

işte googler blogundan bir çözüm:

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

Tüm yeni tarayıcı destekli videolar, yalnızca sessize alınarak otomatik olarak oynatılacak, bu nedenle lütfen Şuna benzer bir şey koyun

<video autoplay muted="muted" loop id="myVideo">
  <source src="https://w.r.glob.net/Coastline-3581.mp4" type="video/mp4">
</video>

Siteniz https ile çalışıyorsa videonun URL'si SSL durumuyla eşleşmelidir, bu durumda video URL'si de https'de olmalı ve HTTP için aynı olmalıdır


0

En temiz ve en basit çözüm:

var p = video.play();
if (p !== undefined) p.catch(function(){});

0

Birinci sebep - oyun vaadinin çözülmesini beklemeden duraklama çağrısı

bu senaryo için çok fazla yanıt var, bu yüzden bu sorun için en iyi belgeye başvuracağım:

https://developers.google.com/web/updates/2017/06/play-request-was-interrupted

İkinci neden - sekme odaklanmadığında oyunu çağırmak

Bu durumda tarayıcı , sekme odaklanmadığında playarayarak kesebilir pause. Etkin sekme için kaynakları kaydetmek için.

Böylece, oynatmayı çağırmadan önce sekmenin odaklanmasını bekleyebilirsiniz:


async function waitForTabFocus() {
  return new Promise((resolve, reject) => {
    const onFocus = () => { resolve(); window.removeEventListener('focus', onFocus) };
    window.addEventListener('focus', onFocus)
  })
}
if (!document.hasFocus()) await this.waitForTabFocus();
videoEl.play();

-1

Aynı sorunla karşılaştım ve autoplaykullanmak yerine özelliği dinamik olarak ekleyerek çözdüm play(). Bu şekilde tarayıcı yarış durumuna girmeden oynamayı anladı.


-1

Otomatik oynatılan bir videonun play()bittiğinde arayarak döngüye girmesini sağlamaya çalışırken , zaman aşımı geçici çözümü benim için işe yaramadı (zaman aşımı ne kadar uzun olursa olsun).

Ama bittiğinde videoyu jQuery ile klonlayarak / değiştirerek düzgün bir şekilde döndüğünü keşfettim.

Örneğin:

<div class="container">
  <video autoplay>
    <source src="video.mp4" type="video/mp4">
  </video>
</div>

ve

$(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 bit) / OS X 10.11.6 kullanıyorum


-1

Sanırım html5 videosunu güncellediler ve bazı kodekleri kullanımdan kaldırdılar. Codec bileşenlerini kaldırdıktan sonra benim için çalıştı.

Aşağıdaki örnekte:

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


-1

İle ilgili bir hata gördüğünüzde Uncaught (in promise)Bu sadece sözünüzü bir ile yerine getirmeniz gerektiği anlamına gelir .catch()Bu durumda .play()bir söz verir. Bir mesajı günlüğe kaydetmek, bazı kod çalıştırmak veya hiçbir şey yapmamak isteyip istemediğinize karar verebilirsiniz, ancak .catch()hatayı aldığınız sürece ortadan kalkacaktır.

var n = new Audio();
n.pause();
n.currentTime = 0;
n.play().catch(function(e) {
  // console.log('There was an error', e);
});

bir söz vermiyor
Martin Dawson

@MartinMazzaDawson Bir söz veriyor. "Bu bir hata, işte tam hata: Yakalanmamış (sözde) DOMException: play () isteği bir pause () çağrısı ile kesintiye uğradı."
seantomburke

-5

Bu sorunu çözmek için bir numara kullandım. Global değişken var ses tanımlayın;

ve işlev kontrolünde

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

ve durdurma işlevinde

audio.pause();
audio = undefined;

bu yüzden sonraki çağrı audio.play, ses '0' geçerliTime'dan hazır olacak

kullandım

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

ama işe yaramadı. Teşekkürler.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.