如何从ServiceWorker流式传输视频?

13

我有一个服务工作者,它会捕获页面的请求(fetch事件),当URL匹配某个特定模式时,它会获取另一个URL并用那个新内容替换响应。

对于文本数据(JS、XML等)或二进制数据(例如图像),它可以完美地工作,但是在处理视频时会出现故障。

我正在使用OSX上的Chrome 41。

以下是我的工作者的简化代码:

self.addEventListener('fetch', function(event) {
  var url = event.request.url;
  console.log('SW: fetch', url);
  if (/\.mp4$/.test(url)) {
    url = 'https://vjs.zencdn.net/v/oceans.mp4';
    var options = {
      credentials: 'include',
      mode: 'no-cors'
    };
    event.respondWith(fetch(url, options));
  }
});

这是我 HTML 页面中简化后的代码:

navigator.serviceWorker.register('sw.js').then(function(reg) {
  console.info('ServiceWorker registration successful for', reg.scope);

  var video = document.createElement('video');
  video.src = '/video.mp4';
  video.controls = true;
  video.autoplay = true;
  video.onerror = function(err) {
    console.error('Video load fail', err);
  }
  video.onload = function(data) {
    console.info('Video load success');
  }
  document.body.appendChild(video);

}).catch(function(err) {
  console.error('ServiceWorker registration failed:', err);
});

第一次加载页面时,worker被安装,因此视频请求未被捕获,导致失败。但是当您重新加载页面(而不清除缓存)时,它成功被捕获,并且worker成功加载视频(在其检查器中为HTTP 200),但由于某种原因,主页面会抛出net::ERR_FAILED

我无法手动读取/流式传输它,因为它来自不同的源,导致“opaque” Response类型:http://www.w3.org/TR/service-workers/#cross-origin-resources

更新:升级到Chrome 42后,错误现在为HTTP 400 Service Worker Fallback Required (from ServiceWorker)。奇怪的是,源代码(第510行)表明,仅当CORS标头丢失时才会引发此错误,但这里的模式是no-cors

1个回答

7

首先,我建议您在当前的Chrome Canary中尝试,这对应于版本44.0.2371.0。随着每个新的Chrome版本的推出,围绕服务工作者的开发工具不断改进,在43+版本中已经得到了很大的改善。

看起来不能将不透明的Response对象用于<video>元素的src,我认为这是有意为之的。(不透明的Response可用于某些目的,但恐怕我没有一个完整的列表来说明什么能用、什么不能用不透明的Response。)

但无论如何,你很幸运,因为vjs.zencdn.net支持CORS,所以你可以使用默认的、启用CORS的Request,它会给你一个非透明的Response

你不能使用credentials: 'include'在你的CORS Request中,因为这会导致错误:Fetch API cannot load https://vjs.zencdn.net/v/oceans.mp4. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. 这似乎不是你特定的主机的问题,因为不需要验证凭据。

当我将你的代码切换为event.respondWith(fetch('https://vjs.zencdn.net/v/oceans.mp4'));时,一切正常。


非常感谢Jeff,CORS头确实是问题所在! - Antoine
我已经在Chromium跟踪器上开了一个问题,以改进调试:https://code.google.com/p/chromium/issues/detail?id=477685 - Antoine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接