DOMException - play() 요청이 중단되었습니다.

François Beaufort
François Beaufort

Chrome DevTools에서 예상치 못한 미디어 오류를 우연히 발견하셨나요? JavaScript 콘솔?

또는

그러면 올바른 위치로 이동하실 수 있습니다. 걱정하지 마십시오. 이 문제의 원인해결 방법을 설명해 드리겠습니다.

원인

다음은 '처리되지 않음 (프라미스에서)'을 재현하는 JavaScript 코드입니다. 다음과 같은 오류가 나타납니다.

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

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

위의 코드로 인해 Chrome DevTools에 다음 오류 메시지가 표시됩니다.

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

preload="none"로 인해 동영상이 로드되지 않으므로 동영상이 재생되지 않습니다. 반드시 video.play()가 실행된 직후에 시작됩니다.

또한 Chrome 50부터 <video> 또는 <audio>에서 play()가 호출됩니다. 요소는 단일 결과를 반환하는 함수인 프로미스를 반환합니다. 있습니다. 재생이 성공하면 프로미스가 이행되고 playing 이벤트가 동시에 시작됩니다. 재생이 실패하면 프로미스가 오류 메시지가 표시됩니다.

이제 다음과 같이 진행됩니다.

  1. video.play()가 동영상 콘텐츠를 비동기식으로 로드하기 시작합니다.
  2. video.pause()가 아직 준비되지 않아 동영상 로드를 중단합니다.
  3. video.play()는 비동기식으로 큰 소리로 거부됩니다.

이 코드에서는 동영상 재생 프로미스를 처리하지 않으므로 Chrome DevTools에 나타납니다.

해결 방법

근본 원인을 이해했으니 이제 이 문제를 해결하기 위해 무엇을 할 수 있는지 알아보겠습니다.

첫째, 미디어 요소 (동영상 또는 오디오)가 재생될 것이라고 가정하지 마세요. 보기 play 함수에서 반환한 프로미스가 거부되었는지 확인합니다. 그것은 재생이 실제로 완료되기 전에는 프라미스가 이행되지 않는다는 점에 유의해야 합니다 시작됩니다. 즉, 미디어가 실행될 때까지 then() 내부의 코드가 실행되지 않습니다. 확인할 수 있습니다.

권장사항

예: 자동재생

<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>
권장사항

예: Play & 일시중지

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

이 간단한 예에서는 훌륭하지만 video.play()를 사용하여 나중에 동영상을 재생할 수 있나요?

비밀을 하나 알려 줄게. video.play()를 사용하지 않아도 됩니다. video.load() 및 방법은 다음과 같습니다.

권장사항

예: 가져오기 및 재생

<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 프로미스 지원

작성 시점에는 HTMLMediaElement.play()Chrome, Edge, Firefox, Opera, Safari

위험 영역

<video><source>play() 프로미스를 거부하지 않도록 함

<video src="not-existing-video.mp4"\>의 경우 play() 프로미스는 다음과 같이 거부됩니다. 동영상이 존재하지 않기 때문입니다. <video><source src="not-existing-video.mp4" type='video/mp4'></video>의 경우 play() 프로미스 절대 거부되지 않습니다. 유효한 소스가 없는 경우에만 발생합니다.

Chromium 버그