O vídeo é um recurso difícil de gerenciar. O streaming consome muita largura de banda, e o armazenamento em cache não é simples. Esses problemas se agravam quando os vídeos são reproduzidos em loop, como em um quiosque. Por exemplo, se uma empresa tiver centenas de dispositivos reproduzindo 30 vídeos em repetição o dia todo, todos os dias, isso pode sobrecarregar a rede rapidamente. Ao veicular os vídeos do cache em vez de fazer streaming, você incorre no custo de download apenas uma vez, acelera as reproduções subsequentes e as disponibiliza para reprodução off-line. Para isso, aproveite os recursos de armazenamento do navegador, em que a API Cache Storage e o IndexedDB são os mais adequados para armazenar arquivos de vídeo. Embora ambas sejam boas opções, vamos nos concentrar na API Cache Storage devido à integração dela com a biblioteca Workbox do service worker, que é muito usada.
Como armazenar vídeos em cache de um service worker
Como o download e o armazenamento em cache de recursos grandes, como vídeos, podem ser uma tarefa particularmente demorada e intensiva para o processador, faça isso em segundo plano fora da linha de execução principal. Os service workers são especialmente úteis para descarregar tarefas de armazenamento em cache. Eles atuam como um proxy entre a página e a rede, permitindo interceptar solicitações e aplicar lógica adicional à resposta da rede, por exemplo, uma estratégia de cache.
Existem várias estratégias de cache diferentes, e cada uma delas foi projetada para ajudar em diferentes casos de uso. Por exemplo, para veicular um arquivo de um cache, se disponível, ou voltar para a rede, se não estiver, você pode escrever o seguinte código.
self.addEventListener('fetch', function (event) { event.respondWith( caches.match(event.request).then(function (response) { return response || fetch(event.request); }), ); });
Gerenciar isso para diferentes tipos de recursos ou URLs que exigem estratégias de cache diferentes pode ser um processo repetitivo e sujeito a erros. O Workbox oferece um conjunto de ferramentas, incluindo helpers de rotas e estratégias de cache, que permitem escrever código de service worker de uma maneira mais declarativa e reutilizável.
A estratégia anterior é chamada de cache first. Para escrever a mesma coisa usando o Workbox, inclua o seguinte:
registerRoute( ({ request }) => request.destination === 'video', new CacheFirst() );
O Workbox oferece receitas semelhantes para outras estratégias de cache e tarefas comuns de service worker, incluindo a integração com ferramentas de build como Webpack e Rollup.
Com o Workbox configurado, você precisa escolher quando vai armazenar em cache seus vídeos. Aqui, há duas abordagens: de forma imediata no carregamento da página ou de forma lenta quando o vídeo é solicitado.
Abordagem rápida
O pré-armazenamento em cache é uma técnica em que os arquivos são salvos no cache durante a instalação do service worker, disponibilizando-os assim que o service worker estiver pronto. O Workbox pode configurar automaticamente o pré-armazenamento em cache para arquivos que podem ser acessados durante o processo de build.
O código do Workbox a seguir pode ser usado no service worker para pré-armazenar arquivos em cache:
import { addPlugins, precacheAndRoute } from 'workbox-precaching'; import { RangeRequestsPlugin } from 'workbox-range-requests'; addPlugins([new RangeRequestsPlugin()]); precacheAndRoute(self.__WB_MANIFEST);
import(s) - Carregue as vinculações necessárias dos módulos do Workbox correspondentes. Como os service workers ainda não oferecem suporte universal aos ESModules, o service worker com tecnologia Workbox precisa ser transmitido por um bundler para funcionar em produção.RangeRequestsPlugin: permite que uma solicitação com um cabeçalhoRangeseja atendida por uma resposta em cache. Isso é necessário porque os navegadores geralmente usam um cabeçalhoRangepara conteúdo de mídia.addPlugins: permite adicionar plug-ins do Workbox a todas as solicitações do Workbox.precacheAndRoute: adiciona entradas à lista de pré-cache e cria uma rota para processar as solicitações de busca correspondentes.__WB_MANIFEST: um marcador de posição que a CLI do Workbox (ou plug-ins de ferramentas de build) substitui pelo manifesto de pré-cache.
Transmita o service worker para a CLI do Workbox ou para a ferramenta de build escolhida e configure como o pré-cache será gerado. Um arquivo workbox-config.js, como o seguinte,informa à CLI como renderizar o service worker:
module.exports = { globDirectory: '.', globPatterns: ['**/*.{html,mp4}'], maximumFileSizeToCacheInBytes: 5000000, swSrc: 'sw.js', swDest: 'sw.js', };
globDirectory: a pasta raiz para começar a procurar arquivos de pré-cache.globPatterns: os padrões de arquivo ("globs") que precisam ser pré-armazenados em cache.maximumFileSizeToCacheInBytes: um limite superior para o tamanho de um arquivo que pode ser pré-armazenado em cache, em bytes.swSrc: o local do arquivo que será usado para gerar o service worker.swDest: o destino do service worker gerado. Pode ser o mesmo do arquivo de origem, mas verifique seself.__WB_MANIFESTestá presente em cada execução.
Quando o processo de build é executado, uma nova versão do service worker é gerada, e self.__WB_MANIFEST é substituído por uma lista de arquivos, cada um com um hash para indicar a revisão:
precacheAndRoute([ { revision: '524ac4b453c83f76eb9caeec11854ca5', url: 'ny.mp4', }, ]);
Sempre que o processo de build é executado, essa lista é reescrita com o conjunto atual de arquivos correspondentes e os hashes de revisão atuais. Isso garante que, sempre que um arquivo for adicionado, removido ou alterado, o service worker vai atualizar o cache na próxima instalação.
Abordagem lenta
Quando você não tem todos os vídeos disponíveis no momento da criação ou só quer armazenar em cache os vídeos quando eles são necessários, use uma abordagem de carregamento lento. Essa abordagem exige que o armazenamento em cache e a veiculação sejam separados. Como apenas conteúdo parcial é buscado da rede durante a reprodução de vídeo, o armazenamento em cache de arquivos durante o streaming não funciona.
Armazenamento em cache dos arquivos
Os caches podem ser criados usando Cache.open(), e os arquivos podem ser adicionados ao cache usando Cache.add() ou Cache.addAll(). Se o app receber uma lista JSON de vídeos para armazenar em cache, eles poderão ser adicionados a um cache de vídeo da seguinte maneira:
// Open video cache const cache = await caches.open('video-cache'); // Fetch list of videos const videos = await (await fetch('/video-list.json')).json(); // Add videos to cache await cache.addAll(videos);
A vantagem dessa abordagem é que você pode controlar a etapa de armazenamento em cache de forma independente do ciclo de vida do service worker, mesmo de outros web workers. A desvantagem é que a parte de gerenciamento de armazenamento fica a cargo do desenvolvedor: é necessário escrever seu próprio algoritmo para rastrear mudanças nos arquivos, rastrear os arquivos armazenados em cache no navegador e gerenciar atualizações de arquivos para garantir que apenas os arquivos alterados sejam atualizados.
Veiculação de arquivos de vídeo armazenados em cache
Uma estratégia de armazenamento em cache de tempo de execução do service worker, como cache first, pode ser usada para veicular os arquivos de vídeo armazenados em cache anteriormente:
import { registerRoute } from 'workbox-routing'; import { CacheFirst } from 'workbox-strategies'; import { CacheableResponsePlugin } from 'workbox-cacheable-response'; import { RangeRequestsPlugin } from 'workbox-range-requests'; registerRoute( ({ request }) => request.destination === 'video', new CacheFirst({ cacheName: 'video-cache', plugins: [ new CacheableResponsePlugin({ statuses: [200], }), new RangeRequestsPlugin(), ], }), );
import(s): carrega as vinculações necessárias dos módulos do Workbox correspondentes.registerRoute: encaminha solicitações para funções (estratégias de cache e plug-ins) que fornecem respostas.CacheFirst: estratégia de armazenamento em cache que atende à solicitação do cache, se disponível. Caso contrário, busca na rede e atualiza o cache.CacheableResponsePlugin: usado para indicar quais cabeçalhos precisam estar presentes para que a resposta possa ser armazenada em cache. Inclua apenas 200 status para rotas de cache de vídeo para evitar que respostas de conteúdo parcial (206) sejam armazenadas em cache durante o streaming de vídeos.RangeRequestsPlugin: plug-in que permite que uma solicitação com um cabeçalhoRangeseja atendida por uma resposta em cache. Isso é necessário porque os navegadores geralmente usam um cabeçalhoRangepara conteúdo de mídia.
Otimizar o carregamento de vídeo é uma tarefa importante para apps que fazem streaming intensivo. Ao aproveitar a API de armazenamento em cache do navegador e o Workbox, você pode tornar essa tarefa difícil gerenciável, economizando a largura de banda dos usuários, reduzindo a carga do servidor, alcançando uma reprodução de vídeo mais rápida e permitindo que seus vídeos sejam executados mesmo off-line.