Service Worker 可拦截并重写媒体请求,实现私有格式视频前端播放,核心是请求调度与响应注入而非解码;通过 fetch 拦截 m3u8/ts 请求,调用后端或 SDK 获取真实清单并转译为标准 HLS 结构,再构造合法 Response 返回;利用 MSE 和主线程协同完成解密与解封装,需注意 iOS Safari 兼容性、HTTPS 同源要求及避免覆盖 onmessage。

Service Worker 可以拦截并重写媒体请求,从而在不修改页面播放器逻辑的前提下,实现私有格式视频(如加密分片、自定义封装、非标准协议)的前端播放。其核心不是“解码”,而是“请求调度与响应注入”——把原始不可播的请求,转换为浏览器能识别的格式(如标准 HLS 或 MSE 兼容的 ArrayBuffer 流)。
劫持 m3u8/ts 请求并动态转译
当播放器发起 m3u8 请求时,Service Worker 通过 fetch 事件捕获该请求,不直接转发,而是:
- 向后端或本地 SDK(如 XP2P_MAIN_SDK)发起适配调用,获取真实可用的播放清单(可能为 JSON 描述、加密索引或 P2P 资源列表)
- 将原始私有格式解析为标准 HLS 结构(含
#EXTM3U头、#EXT-X-KEY、#EXTINF和可播放的.ts或.mp4地址) - 构造合法响应,设置
Content-Type: application/vnd.apple.mpegurl,返回给播放器
后续每个 .ts 请求同样被拦截,Worker 向主线程查询对应分片数据(可能来自内存缓存、P2P 网络或解密后的 ArrayBuffer),再包装成 Response 返回,Content-Type 设为 video/MP2T 或 video/mp4。
绕过浏览器原生限制的关键点
标准 <video></video> 标签无法直接加载私有协议(如 xp2p:// 或加密二进制流),但 Service Worker 的 fetch 拦截发生在网络层之上、渲染层之下,因此:
立即学习“前端免费学习笔记(深入)”;
- 播放器仍使用标准
src="https://example.com/video.m3u8",完全无感知 - Worker 可返回
Response对象(而非真实 URL),支持arrayBuffer()、stream()等方式构造响应体 - 配合 Media Source Extensions(MSE),Worker 还可将私有帧数据组装为
SourceBuffer可接受的Uint8Array片段,实现全自定义解封装
与主线程协同处理私有逻辑
Service Worker 本身无 DOM、无 window、不能直接调用 WebCrypto 或 WebAssembly 模块,复杂解密/解封装必须交由主线程:
- Worker 收到 ts 请求后,用
self.clients.matchAll()找到主页面 client,通过postMessage发送请求 ID 和原始密文 - 主线程收到后,调用本地 SDK 或 WASM 模块完成解密,再将明文 ArrayBuffer 通过
message回传 - Worker 构造
new Response(body, { headers: { 'Content-Type': 'video/MP2T' } })并 resolve fetch
注意:需忽略所有带 xp2pType 字段的 message,避免与 P2P SDK 内部通信冲突。
兼容性与部署注意事项
iOS Safari 对 Service Worker 支持有限(仅从 iOS 17.4 起全面启用),且强制要求 HTTPS + 同源注册。实际接入时需:
- 确保
sw.js注册路径为根目录(/sw.js),作用域覆盖全部媒体资源路径 - 在
install阶段预加载必要脚本(如解密库的 worker 版本),避免运行时加载失败 - 对非支持环境(如旧版 Safari)降级为传统 HLS 或提供 fallback 提示
- 禁止在主线程或 Worker 中覆盖
navigator.serviceWorker.onmessage,否则会中断 XP2P_SDK 的内部通信链路


















