Veiculação de áudio e vídeo em cache

Há alguns problemas na forma como alguns navegadores processam solicitações de recursos de mídia, ou seja, o URL especificado no atributo src dos elementos <video> e <audio>, o que pode levar ao comportamento incorreto de veiculação, a menos que você tome medidas específicas ao configurar o Workbox.

O problema

As complexidades dos problemas que os navegadores têm na veiculação de recursos de áudio e vídeo são explicadas em detalhes nesta discussão do problema do GitHub. O quadro completo é complicado, mas os pontos principais são:

  • A caixa de trabalho precisa ser instruída a respeitar os cabeçalhos de solicitação Range usando o módulo workbox-range-requests da estratégia usada como gerenciador.
  • Os elementos <video> ou <audio> precisam ativar o modo CORS com o atributo crossorigin.
  • Se você quiser disponibilizar mídia do cache, adicione-a explicitamente a ele com antecedência. Você pode fazer isso com o armazenamento prévio em cache, com o cache.add() ou usando o método saveStrategyCache em receitas da caixa de trabalho. Armazenar o recurso de mídia em cache durante o streaming durante a execução não vai funcionar, já que somente conteúdo parcial é buscado na rede durante a reprodução.

Confira como atender a esses requisitos no Workbox, começando com a marcação adequada para um recurso de mídia:

<!-- In your page: -->

<!-- You need to set `crossorigin`, even for same-origin URLs! -->
<video src="movie.mp4" crossorigin="anonymous"></video>
<audio src="song.mp3" crossorigin="anonymous"></audio>

Em seguida, no service worker, use o plug-in workbox-range-request para processar os recursos de mídia corretamente:

// sw.js
import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';
import {RangeRequestsPlugin} from 'workbox-range-requests';

// In your service worker:
// It's up to you to either precache, use warmRuntimeCache, or
// explicitly call cache.add() to populate the cache with media assets.
// If you choose to cache media assets up front, do so with care,
// as they can be quite large and exceed storage quotas.
//
// This route will go to the network if there isn't a cache match,
// but it won't populate the cache at runtime because the response for
// the media asset will be a partial 206 response. If there is a cache
// match, then it will properly serve partial responses.
registerRoute(
  ({request}) => {
    const {destination} = request;

    return destination === 'video' || destination === 'audio'
  },
  new CacheFirst({
    cacheName: 'your-cache-name-here',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [200]
      }),
      new RangeRequestsPlugin(),
    ],
  }),
);

Com essa abordagem, é possível garantir que os recursos de mídia do seu site sejam devidamente buscados e armazenados em cache pelo service worker, considerando as solicitações de intervalo e outras armadilhas em potencial relacionadas a solicitações de mídia.