Vídeo de carregamento lento

Publicado em 16 de agosto de 2019

Assim como nos elementos de imagem, você também pode fazer o carregamento lento de vídeos. Os vídeos geralmente são carregados com o elemento <video>, mas para vídeos hospedados em outros serviços, como o YouTube, eles podem usar <iframe>s. Nesse caso, confira o artigo sobre iframes de carregamento lento.

A forma de carregar <video> de forma lenta depende do caso de uso, já que há algumas soluções diferentes.

Para vídeos que não começam automaticamente

A prática recomendada é evitar a reprodução automática de vídeos, porque isso deixa o controle com o usuário. Nesses casos, especificar o atributo preload no elemento <video> é a melhor maneira de evitar o carregamento de todo o vídeo:

<video controls preload="none" poster="one-does-not-simply-placeholder.jpg">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

O exemplo anterior usa um atributo preload com um valor de none para impedir que os navegadores carreguem qualquer dado de vídeo. O atributo poster dá ao elemento <video> um marcador de posição que ocupa o espaço enquanto o vídeo é carregado.

Na maioria dos navegadores, o padrão de preload é metadata, e uma parte do vídeo é pré-carregada usando o cabeçalho Content-Range. Isso pode resultar em mais dados sendo transferidos do que o desejado, principalmente se o cabeçalho Content-Range não tiver suporte do navegador. Mesmo com suporte, os navegadores não podem saber em quais bytes os metadados estão armazenados, e eles podem não estar no início do arquivo. Portanto, a melhor chance de evitar o carregamento do vídeo é especificar none e usar preload="none".

Isso pode ser aprimorado para pré-carregar os metadados quando o usuário passa o cursor sobre o vídeo com um atributo onmouseenter (ou com o manipulador de eventos mouseenter equivalente):

<video controls
  preload="none"
  poster="one-does-not-simply-placeholder.jpg"
  onmouseenter="event.target.setAttribute('preload','metadata')">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

Isso não apenas reduz o atraso quando o usuário começa a assistir o vídeo, mas também mostra a duração do vídeo assim que ele.

Os vídeos podem se qualificar como candidatos para a LCP. Uma imagem poster será carregada mais rápido do que o vídeo. Portanto, se esse for um candidato a LCP, use uma imagem de capa, mas também pré-carregue com um valor de atributo fetchpriority de "high":

<link rel="preload" href="one-does-not-simply-placeholder.jpg" as="image" fetchpriority="high">
<video controls preload="none"
  poster="one-does-not-simply-placeholder.jpg"
  onmouseenter="event.target.setAttribute('preload','metadata')">
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

Para vídeos usados como substitutos de GIFs animados

Os vídeos com reprodução automática são mais usados para animações rápidas no estilo GIF. Os GIFs animados são amplamente usados, mas são inferiores aos seus equivalentes em vídeo de várias maneiras, principalmente com relação ao tamanho do arquivo. Os GIFs animados podem ter vários megabytes de dados. Os vídeos de qualidade visual semelhante tendem a ser muito menores.

O uso do elemento <video> como substituto de GIFs animados não é tão simples quanto o elemento <img>. Os GIFs animados têm três características:

  1. Eles são reproduzidos automaticamente quando carregados.
  2. Eles se repetem continuamente (embora esse não seja sempre o caso).
  3. Eles não têm uma faixa de áudio.

Conseguir isso com o elemento <video> fica assim:

<video autoplay muted loop playsinline>
  <source src="one-does-not-simply.webm" type="video/webm">
  <source src="one-does-not-simply.mp4" type="video/mp4">
</video>

Os atributos autoplay, muted e loop são autoexplicativos. playsinline é necessário para que a reprodução automática ocorra no iOS. Agora você tem um vídeo que serve como substituto do GIF e funciona em diferentes plataformas. Mas como fazer o carregamento lento? Para começar, modifique a marcação <video> de maneira apropriada:

<video class="lazy" autoplay muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">
  <source data-src="one-does-not-simply.webm" type="video/webm">
  <source data-src="one-does-not-simply.mp4" type="video/mp4">
</video>

Você vai notar a adição do atributo poster, que permite especificar um marcador de posição para ocupar o espaço do elemento <video> até que o vídeo seja carregado lentamente. Assim como nos exemplos de carregamento lento de <img>, armazene o URL do vídeo no atributo data-src de cada elemento <source>. Em seguida, use um código JavaScript semelhante aos exemplos de carregamento lento de imagem baseado no Intersection Observer:

document.addEventListener("DOMContentLoaded", function() {
  var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));

  if ("IntersectionObserver" in window) {
    var lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(video) {
        if (video.isIntersecting) {
          for (var source in video.target.children) {
            var videoSource = video.target.children[source];
            if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") {
              videoSource.src = videoSource.dataset.src;
            }
          }

          video.target.load();
          video.target.classList.remove("lazy");
          lazyVideoObserver.unobserve(video.target);
        }
      });
    });

    lazyVideos.forEach(function(lazyVideo) {
      lazyVideoObserver.observe(lazyVideo);
    });
  }
});

Ao fazer o carregamento lento de um elemento <video>, é necessário iterar por todos os elementos <source> filhos e inverter os atributos data-src para src. Depois disso, é preciso acionar o carregamento do vídeo chamando o método load do elemento. Depois disso, a mídia será reproduzida automaticamente pelo atributo autoplay.

Com esse método, você tem uma solução de vídeo que emula o comportamento de GIFs animados, mas não resulta no mesmo uso intensivo de dados. Assim, conseguimos carregar esse conteúdo lentamente.

Bibliotecas de carregamento lento

As bibliotecas a seguir podem ajudar você a carregar vídeos de forma lenta:

  • vanilla-lazyload e lozad.js são opções super leves que usam apenas o Intersection Observer. Sendo assim, eles têm alto desempenho, mas precisam ser polifilados antes de serem usados em navegadores mais antigos.
  • yall.js é uma biblioteca que usa o Intersection Observer e volta para gerenciadores de eventos. Ele também pode fazer o carregamento lento de imagens poster de vídeo usando um atributo data-poster.
  • Se você precisar de uma biblioteca de carregamento lento específica para React, considere areact-lazyload. Embora não use o Intersection Observer, ele oferece um método conhecido de carregamento lento de imagens para aqueles que estão acostumados a desenvolver aplicativos com o React.

Cada uma dessas bibliotecas de carregamento lento é bem documentada e tem vários padrões de marcação para diversas aplicações de carregamento lento.