Cómo entregar audio y video almacenados en caché

Existen algunas diferencias en la forma en que algunos navegadores manejan las solicitudes de elementos multimedia (es decir, la URL especificada en el atributo src de los elementos <video> y <audio>), lo que puede generar un comportamiento de publicación incorrecto, a menos que tomes pasos específicos al configurar Workbox.

El problema

Las particularidades del problema que tienen los navegadores en cuanto a la entrega de elementos de audio y video se explican en detalle en este debate sobre un problema en GitHub. El panorama completo es complicado, pero los puntos clave son los siguientes:

  • Se debe solicitar al equipo de trabajo que respete los encabezados de solicitud Range mediante el módulo workbox-range-requests para la estrategia utilizada como controlador.
  • Los elementos <video> o <audio> deben habilitar el modo CORS con el atributo crossorigin.
  • Si quieres entregar medios desde la caché, debes agregarlo explícitamente a la caché con anticipación. Puedes hacerlo mediante el almacenamiento previo en caché, con cache.add() o con el método cleanStrategyCache en workbox-recipes. El almacenamiento en caché del elemento multimedia mientras se transmite en el tiempo de ejecución no funciona, ya que solo se recupera contenido parcial de la red durante la reproducción.

Aquí te mostramos cómo cumplir con estos requisitos en Workbox comenzando con el lenguaje de marcado adecuado para un recurso multimedia:

<!-- 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>

Luego, en tu service worker, usa el complemento workbox-range-request para controlar los elementos multimedia según corresponda:

// 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(),
    ],
  }),
);

Con este enfoque, puedes asegurarte de que tu service worker recupere y almacene en caché los recursos multimedia de tu sitio web, a la vez que se tienen en cuenta las solicitudes de rango y otras posibles dificultades relacionadas con las solicitudes de medios.