DOMException - play() isteği kesintiye uğradı

François Beaufort
François Beaufort

Chrome Geliştirici Araçları JavaScript Konsolu'nda bu beklenmedik medya hatasıyla karşılaştınız mı?

veya

O halde doğru yerdesiniz. Endişelenmeyin. Bu soruna neyin neden olduğunu ve nasıl düzeltileceğini açıklayacağım.

Bunun nedeni

Aşağıda, gördüğünüz "Uncaught (in promise)" hatasını yeniden üreten bir JavaScript kodu verilmiştir:

Yapılmaması gerekenler:
<video id="video" preload="none" src="https://example.com/file.mp4"></video>

<script>
  video.play(); // <-- This is asynchronous!
  video.pause();
</script>

Yukarıdaki kod, Chrome Geliştirici Araçları'nda şu hata mesajıyla sonuçlanır:

_Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().

Video, preload="none" nedeniyle yüklenmediğinden video oynatma işlemi video.play() çalıştırıldıktan hemen sonra başlamayabilir.

Ayrıca Chrome 50'den beri, <video> veya <audio> öğesinde play() çağrısı, tek bir sonucu eşzamansız olarak döndüren bir işlev olan Promise döndürür. Oynatma başarılı olursa Promise yerine getirilir ve aynı anda playing etkinliği tetiklenir. Oynatma başarısız olursa Promise, hatayı açıklayan bir hata mesajıyla birlikte reddedilir.

Şu anda şu işlemler gerçekleşiyor:

  1. video.play(), video içeriğini eşzamansız olarak yüklemeye başlar.
  2. video.pause() henüz hazır olmadığı için video yüklemeyi kesintiye uğratır.
  3. video.play(), eşzamansız olarak yüksek sesle reddediyor.

Video oynatma Promise'ini kodumuzda işlemediğimiz için Chrome Geliştirici Araçları'nda bir hata mesajı görünüyor.

Nasıl giderilir?

Temel nedeni anladığımıza göre, sorunu düzeltmek için neler yapabileceğimize bakalım.

Öncelikle, bir medya öğesinin (video veya ses) oynatılacağı varsaymayın. Reddedildiyse play işlevi tarafından döndürülen Promise'e bakın. Promise'in, oynatma gerçekten başlatılana kadar yerine getirilmeyeceğini belirtmek gerekir. Yani then() içindeki kod, medya oynatılana kadar yürütülmez.

Yapılması gerekenler

Örnek: Otomatik oynatma

<video id="video" preload="none" src="https://example.com/file.mp4"></video>

<script>
  // Show loading animation.
  var playPromise = video.play();

  if (playPromise !== undefined) {
    playPromise.then(_ => {
      // Automatic playback started!
      // Show playing UI.
    })
    .catch(error => {
      // Auto-play was prevented
      // Show paused UI.
    });
  }
</script>
Yapılması gerekenler

Örnek: Oynatma ve Duraklatma

<video id="video" preload="none" src="https://example.com/file.mp4"></video>
 
<script>
  // Show loading animation.
  var playPromise = video.play();
 
  if (playPromise !== undefined) {
    playPromise.then(_ => {
      // Automatic playback started!
      // Show playing UI.
      // We can now safely pause video...
      video.pause();
    })
    .catch(error => {
      // Auto-play was prevented
      // Show paused UI.
    });
  }
</script>

Bu basit örnek için harika bir yöntem olsa da videoyu daha sonra oynatabilmek için video.play() kullanırsanız ne olur?

Size bir sır vereceğim. video.play() yerine video.load() kullanabilirsiniz. Bunun için:

Yapılması gerekenler

Örnek: Getir ve Oyna

<video id="video"></video>
<button id="button"></button>

<script>
  button.addEventListener('click', onButtonClick);

  function onButtonClick() {
    // This will allow us to play video later...
    video.load();
    fetchVideoAndPlay();
  }

  function fetchVideoAndPlay() {
    fetch('https://example.com/file.mp4')
    .then(response => response.blob())
    .then(blob => {
      video.srcObject = blob;
      return video.play();
    })
    .then(_ => {
      // Video playback started ;)
    })
    .catch(e => {
      // Video playback failed ;(
    })
  }
</script>

Play Promise desteği

Bu makalenin yazıldığı sırada HTMLMediaElement.play(), Chrome, Edge, Firefox, Opera ve Safari'de bir promise döndürüyor.

Tehlike bölgesi

<source> içindeki <video>, play()'nin hiçbir zaman reddetmeyeceğini vaat eder

<video src="not-existing-video.mp4"\> için play() vaadi, video mevcut olmadığından beklendiği gibi reddedilir. <video><source src="not-existing-video.mp4" type='video/mp4'></video> için play() vaadi hiçbir zaman reddetmez. Bu durum yalnızca geçerli kaynak yoksa ortaya çıkar.

Chromium Hatası