Você se deparou com um erro de mídia inesperado no Chrome DevTools? Console JavaScript?
ou
Você está no lugar certo. Não tenha medo. Vamos explicar o que está causando esse problema e como corrigir.
O que está causando isso
Veja um código JavaScript abaixo que reproduz a mensagem "Não capturado (em promessa)" erro que você está vendo:
<video id="video" preload="none" src="https://example.com/file.mp4"></video> <script> video.play(); // <-- This is asynchronous! video.pause(); </script>
O código acima resulta nesta mensagem de erro no Chrome DevTools:
_Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().
Como o vídeo não carregou devido a preload="none"
, a reprodução não
vai começar logo depois que video.play()
for executado.
Além disso, desde o Chrome 50, uma chamada play()
em uma <video>
ou <audio>
retorna uma promessa, uma função que retorna um único resultado.
de forma assíncrona. Se a reprodução for bem-sucedida, a promessa é atendida e o
O evento playing
é disparado ao mesmo tempo. Se a reprodução falhar, a promessa será
rejeitado e uma mensagem de erro explicando a falha.
Aqui está o que está acontecendo:
video.play()
começa a carregar o conteúdo de vídeo de forma assíncrona.video.pause()
interrompe o carregamento do vídeo porque ele ainda não está pronto.video.play()
rejeita de forma assíncrona em volume alto.
Como não processamos a promessa de reprodução de vídeo no código, uma mensagem de erro aparece no Chrome DevTools.
Como corrigir o problema
Agora que entendemos a causa raiz, vamos ver o que podemos fazer para corrigir isso.
Primeiro, não presuma que um elemento de mídia (vídeo ou áudio) será reproduzido. Confira
a promessa retornada pela função play
para ver se ela foi rejeitada. É
A promessa não será cumprida até que a reprodução
iniciado, o que significa que o código dentro da then()
não será executado até que a mídia
está tocando.
Exemplo: reprodução automática
<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>
Exemplo: Play & Pausar
<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>
Isso é ótimo para este exemplo simples, mas e se você usar video.play()
para ser
pode reproduzir um vídeo mais tarde?
Vou te contar um segredo. Não é necessário usar video.play()
, você pode usar
video.load()
. Veja como fazer isso:
Exemplo: Buscar e Reproduzir
<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>
Suporte ao Play Commit
No momento da gravação, HTMLMediaElement.play()
retorna uma promessa em
Chrome, Edge, Firefox, Opera e Safari.
Zona de perigo
<source>
em <video>
faz com que a promessa play()
nunca seja rejeitada.
Para <video src="not-existing-video.mp4"\>
, a promessa play()
é rejeitada como
esperado, pois o vídeo não existe. Para <video><source
src="not-existing-video.mp4" type='video/mp4'></video>
, a promessa play()
nunca rejeita. Isso só acontece quando não há fontes válidas.