腾讯云X-P2P接入 service worker(iOS)_音视频解决方案_同尘科技
本文档适用于 iOS Safari 浏览器的 HLS 播放, 提供 P2P 功能 XP2P 提供了两个 SDK:XP2P_MAIN_SDK和XP2P_SW_SDKXP2P_MAIN_SDK 用于主线程XP2P_SW_SDK 用于service worker内部
接入原理
交互示意
safari 播放器 service worker(XP2P_SW_SDK) XP2P_MAIN_SDK
交互描述
1. 播放器发出的 m3u8 请求service worker 拦截播放器发出的 m3u8 请求service worker 直接请求 m3u8 并返回给播放器 (XP2P_SW_SDK 已实现)2. 播放器发出的 ts 请求service worker 拦截播放器的 ts 请求worker 内部的 XP2P_SW_SDK 向主线程 XP2P_MAIN_SDK 查询这个 ts (XP2P_SW_SDK 已实现)XP2P_MAIN_SDK 通过 P2P 或者 http 获取到 ts, 返回给 service worker (XP2P_SW_SDK 已实现)service worker 将 ts 返回给播放器
demo
参见 我们的接入邮件 demo/sw 目录
实际接入
接入前准备
1. 按照接入说明中的接入前准备
2. 忽略 message 事件中 XP2P 的消息
xp2p XP2P_MAIN_SDK 和 XP2P_SW_SDK 之间的通信, 依赖于 service worker 的 message 通信机制,因此如果您使用到了 message 事件或者设置了 onmessage
请忽略 XP2P 传递的消息,忽略方法如下
/** * 主线程内, 如果使用message事件接收service worker消息 * @param {MessageEvent} event */self.navigator.serviceWorker.addEventListener('message', (event) => { // 判断xp2p消息的方法, 如果是XP2P消息, 请务必忽略, 不要处理或修改 if (!Object.prototype.hasOwnProperty.call(event.data, 'xp2pType')) { return; }});
/** *或者 如果您在主线程使用onmessage接收service worker消息 * @param {MessageEvent} event */navigator.serviceWorker.onmessage = (event) => { // 判断xp2p消息的方法, 如果是XP2P消息, 请务必忽略, 不要处理或修改 if (!Object.prototype.hasOwnProperty.call(event.data, 'xp2pType')) { return; }};
/** * 在service worker内如果使用message事件接收主线程消息 * @param {MessageEvent} event */self.addEventListener('message', (event) => { // 判断xp2p消息的方法, 如果是XP2P消息, 请务必忽略, 不要处理或修改 if (!Object.prototype.hasOwnProperty.call(event.data, 'xp2pType')) { return; }});/** * 或者 如果您在service worker内部使用onmessage接受主线程消息 * @param {MessageEvent} event */self.onmessage = (event) => { // 判断xp2p消息的方法, 如果是XP2P消息, 请务必忽略, 不要处理或修改 if (!Object.prototype.hasOwnProperty.call(event.data, 'xp2pType')) { return; }};
3. 设置 service worker 文件的拦截作用域
这一步的目的是确保 sw.js 可以拦截到播放器的 ts 和 m3u8 请求说明:参考 https://www.w3.org/TR/service-workers/#service-worker-allowed(1) 设置 sw.js 的 http response header
// 增加一个 response header, 设置sw.js的作用域是跟路径Service-Worker-Allowed : "/"
(2) service worker 代码内设置作用域
// 提升sw.js的拦截作用域, 虽然sw.js的路径是在/js/目录下, 但是可以拦截根路径的请求navigator.serviceWorker.register("/js/sw.js", {scope: "/"}).then(() => { console.log("Install succeeded as the max allowed scope was overriden to '/'.");});
SDK 代码接入
说明:相关的 SDK API 请参考 API 文档
主线程 XP2P 接入代码(XP2P_MAIN_SDK)
1. 创建 sdk 实例2. 播放器播放
// 判断当前浏览器环境是否支持XP2Pif (!HLSP2P.isSupportedInServiceWorker()) { alert('浏览器不支持'); return;}
// TODO 配置的详细内容请参考API文档const config = { // 如下为必传参数 enableServiceWorker: true, // 仅在service worker环境中开启, 不传默认为false // 如下为必传参数 videoId: 'video_id', // 特别注意是
service worker 内部接入代码(XP2P_SW_SDK)
1. 加载 XP2P_SW_SDK2. 创建 XP2P_SW_SDK 实例3. 监听 fetch event 并拦截必要的请求: 包括 xp2p 内部请求, m3u8 请求, ts 请求
// 在service worker内部加载XP2P_SW_SDKvar xp2pswUrl = '这里写XP2P_SW_SDK的url'importScripts(xp2pswUrl);
// 创建sw内的XP2P SDK实例, 并绑定在self作用域// 此处create函数返回单例self.xp2pIns = XP2PSW.XP2PSWLib.create();
/** * TODO 这里您可以自行实现, 请仅拦截视频正片的ts和m3u8 * @param url * @return {boolean} */function isTsOrM3u8Url(url) { return url.indexOf(".ts") > -1 || url.indexOf(".m3u8") > -1;}
// 在fetch事件中, 使用XP2P处理必要的请求self.addEventListener('fetch', /** * @param {FetchEvent} event */ (event) => { // TODO XP2P 拦截两种请求: xp2p自身的请求和 HLS请求 // TODO 您可以根据自己的灰度策略, 选择只开启部分资源走P2P if (self.xp2pIns && (self.xp2pIns.detectXP2PRequest(event) || isTsOrM3u8Url(event.request.url))) { return event.respondWith( // 调用XP2P的match方法来处理fetch event, 尝试请求 self.xp2pIns.match(event) .then(response => { // 通过XP2P SDK请求成功, 返回response给fetch请求 // TODO 如果需要对respone进行处理, 可以在这里做 return response; }) .catch((e) => { // TODO 重要! 当XP2P请求失败或者XP2P关闭了service worker功能的时候会走到这里, 需要在这里兜底请求一次 // 注意: safari会增加pragma header,导致发出不必要的cors preflight请求, 会导致请求失败. 这里删除掉 const r = new Request(event.request); r.headers.delete('pragma'); // TODO 如果需要对respone进行处理, 可以在这里做 return fetch(r); }) ); } // TODO 对于不需要XP2P处理的其他请求, 您可以在此处自行处理 });
测试
如何确认 XP2P 已经启动
观察网络面板, XP2P_MAIN_SDK 启动一段时间后, 会发出 https://xw.xp2p/hello
请求, 如果响应如下则表示启动成功
statusCode: 200body: { code: 0}
如何确认是否成功收到 P2P 数据
1. XP2P_MAIN_SDK 提供了数据统计接口,包含了 P2P 和 cdn 字节数, 可以参考 API 文档2. 可以观察浏览器网络面板, 对于一个ts请求例如: 1.ts如果没有 P2P 成功, 则会在 network 面板上观察到两个 1.ts 请求, 分别由播放器和 XP2P_MAIN_SDK 发出如果 P2P 成功, 则在 network 面板上指挥看到一个 1.ts 请求, 由播放器发出
对音视频的解决方案有疑惑?想了解解决方案收费? 联系解决方案专家
腾讯云限时活动1折起,即将结束: 马上收藏
同尘科技为腾讯云授权服务中心,购买腾讯云享受折上折,更有现金返利:同意关联,立享优惠
阿里云解决方案也看看?: 点击对比阿里云的解决方案
暂无评论,你要说点什么吗?