Illustration of a bird flying.

Eventos baseados no tempo de vídeo do Youtube


Já teve a necessidade de incorporar um vídeo do Youtube em seu site e lançar algum evento em um determinado tempo da execução do mesmo? Se sim, este post é pra você.

Recentemente tive uma demanda com um cliente onde existia a necessidade de abrir uma modal alguns segundos antes do vídeo finalizar. Apesar de a documentação da API do Youtube disponibilizar a informação de como obter o tempo atual do vídeo, ela não mostra um exemplo prático. E é isso que venho te mostrar.

Pegue o seguinte código como exemplo:

HTML

<div id="player" data-video-id="ZZ5LpwO-An4"></div>

Javascript

Primeiramente adicione o jquery, só pra ficar fácil de trabalhar daqui pra frente.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

Depois inicie a configuração do player do Youtube.

<script>
// Adicionando o script do youtube iframe
var tag = document.createElement('script');
var firstScriptTag = document.getElementsByTagName('script')[0];

tag.src = 'https://www.youtube.com/iframe_api';
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// inicializando player
var playerDiv = $('#player');
var player = null;

// método chamado automaticamente pela API do Youtube
function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        height: 450, // qualquer altura desejada
        width: 800, // qualquer largura desejada
        videoId: $(playerDiv).attr('data-vide-id'),
        playerVars: { // adicionando algumas variáveis
            rel: 0, // não exibir videos relacionados ao final
            showinfo: 0, // ocultar informações do video
            autoplay: 1 // play automático
        }
    });
}
</script>

Feito isso já temos o seguinte resultado.

OnReady

A API do Youtube possui alguns eventos como o onReady que é lançado assim que o vídeo está pronto para a execução. Basta que adicionemos o evento vinculando à uma função que criaremos mais à frente.

// Nas inicializações das variáveis, adicione mais estas: videoDuration, videoTime e interval
var videoDuration = 0;
var videoTime = 0;
var interval = null;

// nas configurações do player adicione a configuração de eventos
// playersVars: {...},
events: {
    'onReady': onPlayerReady
}

Em seguida temos de criar nossa funcão onPlayerReady. Nele descobriremos qual é o tempo atual do vídeo e lançaremos uma ação em um determinado momento.

function onPlayerReady(event) {
    // obtendo o tempo atual do vídeo
    videoDuration = parseInt(player.getDuration());

    // aplicando um loop de 1 em 1s
    interval = setInterval(discoverTime, 1000);
}

Mas de onde o discoverTime? Esta função ainda criaremos e é nela a grande jogada para executar qualquer ação baseada no tempo do video.

E a mágica

Agora criaremos a função discoverTime.

// adicionando um tempo em específico para que uma ação seja executada.
var fireAt = 15;

function discoverTime() {
    // obtendo o tempo atual do video
    if (player && player.getCurrentTime) {
        videoTime = parseInt(player.getCurrentTime());
    }

    if (videoTime < videoDuration && videoTime === fireAt) {
        console.log('Aos ' + fireAt + 's, coloque aqui a sua mágica!');
    }

    // quando o video terminar, resetamos o interval
    if (videoTime > videoDuration) {
        clearInterval(interval);
    }
}

Pronto! Agora só lançar o que for preciso, a qualquer momento do vídeo.

É recomendado para saber quando o vídeo chegou ao fim?

Não. Para isso existe outro evento, o onStateChange. O que foi feito acima é um listener que roda a cada segundo, recomendado somente para situações em que você precise lançar algum evento durante a execução do video ou a alguns poucos segundos de sua finalização, como foi o caso que tive com um cliente recentemente. Veja abaixo um exemplo de como identificar diversos estados do vídeo, inclusive o momento em que ele chega ao fim.

// nas configurações de eventos
events: {
    'onReady': onPlayerready,
    'onStateChange': onPlayerStateChange
}...

function onPlayerStateChange(event) {
    switch (event.data) {
        case YT.PlayerState.ENDED:
            console.log('Finalizou execução do video');
            break;
        case YT.PlayerState.PLAYING:
            console.log('Assistindo');
            break;
        case YT.PlayerState.PAUSED:
            console.log('Pause');
            break;
        case YT.PlayerState.BUFFERING:
            console.log('carregando');
            break;
    }
}

That’s it!

Quer ver na prática? Então pega este gist que criei no dia em que implementei esta solução para meu cliente.