Обслуживание кэшированного аудио и видео

Есть некоторые недостатки в том, как некоторые браузеры обрабатывают запросы на мультимедийные ресурсы, то есть URL-адрес, указанный в атрибуте src элементов <video> и <audio> , что может привести к некорректному поведению при обслуживании, если вы не предпримете определенные шаги при настройке Workbox.

Проблема

Тонкости проблем, с которыми сталкиваются браузеры при обслуживании аудио- и видеоресурсов, подробно объясняются в этом обсуждении проблемы на GitHub . Полная картина сложна, но ключевые моменты таковы:

  • Workbox необходимо указать, чтобы он уважал заголовки запросов Range , используя модуль workbox-range-requests для стратегии, используемой в качестве обработчика.
  • Элементы <video> или <audio> должны включить режим CORS с помощью атрибута crossorigin .
  • Если вы хотите обслуживать медиафайлы из кеша, вам следует заранее явно добавить их в кеш. Вы можете сделать это с помощью предварительного кэширования, с помощью метода cache.add() или с помощью метода WarmStrategyCache в рецептах рабочего ящика. Кэширование медиа-ресурса во время его потоковой передачи во время выполнения не будет работать, поскольку во время воспроизведения из сети извлекается только частичный контент.

Вот как удовлетворить эти требования в Workbox, начиная с правильной разметки для медиаресурса:

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

Затем в своем сервисном работнике используйте плагин workbox-range-request для соответствующей обработки медиа-ресурсов:

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

Используя этот подход, вы можете гарантировать, что медиа-ресурсы вашего веб-сайта правильно извлекаются и кэшируются вашим сервисным работником, принимая во внимание запросы диапазона и другие потенциальные ошибки, связанные с медиа-запросами.