如何从 ServiceWorker 流式传输视频?
Posted
技术标签:
【中文标题】如何从 ServiceWorker 流式传输视频?【英文标题】:How can I stream a video from a ServiceWorker? 【发布时间】:2015-06-22 16:27:20 【问题描述】:我有一个服务工作者可以捕获我的页面请求(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 安装,所以视频请求没有被捕获,因此失败。但是当你重新加载页面(不清理缓存)时,它被成功捕获,并且工作人员成功加载了视频(其检查器中的 HTTP 200),但由于某种原因,主页抛出了net::ERR_FAILED
。
而且我无法手动读取/流式传输它,因为它来自不同的来源,导致“不透明”响应类型:http://www.w3.org/TR/service-workers/#cross-origin-resources
更新:更新到 Chrome 42,错误现在是 HTTP 400 Service Worker Fallback Required (from ServiceWorker)
。奇怪的是the source code(第 510 行)表明它只应在缺少 CORS 标头时引发,但这里的模式是no-cors
。
【问题讨论】:
【参考方案1】:首先,我建议尝试使用当前的Chrome Canary,它当前对应于版本 44.0.2371.0。随着每个新的 Chrome 版本发布,围绕服务工作人员的开发人员工具不断改进,总体而言,43+ 版本变得更好。
看起来opaque Response
对象不能用于<video>
元素的src
,我假设这是故意的。 (不透明的Response
s 可以用于某些目的,恐怕我没有一个完整的纲要,什么可以和不透明的Response
一起使用。)
但无论如何,您很幸运vjs.zencdn.net
支持 CORS,因此您可以使用默认启用 CORS 的Request
,这将为您提供不透明的Response
。
您不能做的一件事是在您的 CORS 中使用 credentials: 'include'
Request
,因为这会导致 Fetch API 无法加载 https://vjs.zencdn.net/v/oceans.mp4。当凭证标志为真时,不能在“Access-Control-Allow-Origin”标头中使用通配符“*”。错误。这似乎不是您的特定主机的问题,因为不需要凭据。
当我将您的代码切换为使用 event.respondWith(fetch('https://vjs.zencdn.net/v/oceans.mp4'));
时,一切正常。
【讨论】:
非常感谢 Jeff,CORS 标头确实是问题所在! 我在 Chromium 跟踪器上打开了一个问题以改进调试:code.google.com/p/chromium/issues/detail?id=477685以上是关于如何从 ServiceWorker 流式传输视频?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 iOS 设备(而不是自己的相机)流式传输 (RTMP) 视频