传送缓存的音频和视频

某些浏览器处理媒体资源请求(即在 <video><audio> 元素的 src 属性中指定的网址)的方式上存在一些小问题,这可能会导致错误的投放行为,除非您在配置 Workbox 时执行特定步骤。

问题

如需详细了解浏览器在传送音频和视频资源方面所面临的复杂问题,请参阅这篇 GitHub 问题讨论。整体情况十分复杂,但要点如下:

  • 必须通过对用作处理程序的策略使用 workbox-range-requests 模块,来告知 Workbox 遵循 Range 请求标头
  • <video><audio> 元素需要通过 crossorigin 属性选择启用 CORS 模式。
  • 如果您想从缓存中提供媒体,则应提前将其明确添加到缓存。为此,您可以进行预缓存,或使用 cache.add(),或在工作箱配方中使用 hotStrategyCache 方法。在运行时流式传输的媒体资产无法缓存,因为在播放期间只从网络中提取部分内容。

下文介绍了如何在 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> 

然后,在 Service Worker 中,使用 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(),     ],   }), ); 

通过这种方法,您可以确保 Service Worker 正确提取和缓存网站的媒体资源,同时将范围请求和其他与媒体请求相关的潜在隐患考虑在内。