Web 观播 SDK 提供看直播、发评论、参与抽奖等功能。本文介绍 Web 观播 SDK 的集成方法。
Web 观播 SDK 支持的功能情况,详见功能列表。
Web 观播 SDK 的最新版本号为 2.1.59。详见Web 观播 SDK 发布历史。直接修改 URL 中的版本号即可更新版本,同一终端的 CSS 和 JS 版本应保持一致。
企业直播提供了 byted-livesaas-dev Skill(技能),帮助您快速集成 Web SDK。您可通过命令或下载压缩包方式安装 Skill。详见使用 Skills 管理与集成。
方式一:打开本地的命令行工具,直接运行以下命令,将企业直播的所有 Skills 安装到本地。之后 Agent 将根据您的输入自动调用对应的 Skill:
npx bytedlive-cli skills add
方式二:点击下载观看页集成 Skill 压缩包,将其解压缩至您的项目文件夹中:
由于网络抖动或运营商域名劫持等原因,Web 观播 SDK 的静态资源有较小概率加载失败,导致 Web 观播 SDK 初始化失败。为避免此情况,提高 SDK 静态资源加载的稳定性,在使用 SDK 之前,您需配置资源加载重试机制。在静态资源加载失败时,系统将通过多个域名进行重试,最多可重试 9 次。
如果您是原生 Web 场景,请将以下代码添加到 HTML 的 <head> 标签中:
<html> <head> <script> function _slicedToArray(e,r){return _arrayWithHoles(e)||_iterableToArrayLimit(e,r)||_unsupportedIterableToArray(e,r)||_nonIterableRest()}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(e,r){if(e){if("string"==typeof e)return _arrayLikeToArray(e,r);var t=Object.prototype.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray(e,r):void 0}}function _arrayLikeToArray(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=new Array(r);t<r;t++)n[t]=e[t];return n}function _iterableToArrayLimit(e,r){var t=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=t){var n,o,i,a,u=[],f=!0,c=!1;try{if(i=(t=t.call(e)).next,0===r){if(Object(t)!==t)return;f=!1}else for(;!(f=(n=i.call(t)).done)&&(u.push(n.value),u.length!==r);f=!0);}catch(e){c=!0,o=e}finally{try{if(!f&&null!=t.return&&(a=t.return(),Object(a)!==a))return}finally{if(c)throw o}}return u}}function _arrayWithHoles(e){if(Array.isArray(e))return e}!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(e="undefined"!=typeof globalThis?globalThis:e||self).vcloudAssetsRetry=r()}(this,(function(){"use strict";var e="retryTimes",r="succeeded",t="failed",n="maxRetryCount",o="onRetry",i="onSuccess",a="onFail",u="domain",f="styleImageNoImportant",c="data-assets-retry-hooked",l="data-assets-retry-ignore",s="data-retry-id",d=window,y=window.document,h=d.HTMLElement,v=d.HTMLScriptElement,g=d.HTMLStyleElement,p=d.HTMLLinkElement,m=d.HTMLImageElement,b=function(e){return e},A=function(){},E=function(e,r,t){var n=e.indexOf(r);return-1===n?e:e.substring(0,n)+t+e.substring(n+r.length)},T=function(e){return[].slice.call(e)},w=function(e,r){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:A,n=arguments.length>3&&void 0!==arguments[3]&&arguments[3]||e.defer||e.async;if("loading"!==y.readyState||/Edge|MSIE|rv:/i.test(navigator.userAgent)||n){var o=y.createElement("script");Object.keys(v.prototype).forEach((function(r){if("src"!==r&&e[r]&&"object"!=typeof e[r])try{o[r]=e[r]}catch(e){}})),o.src=r,o.onload=e.onload,o.onerror=e.onerror,o.setAttribute(s,L());var i=e.getAttribute("nonce");i&&o.setAttribute("nonce",i),y.getElementsByTagName("head")[0].appendChild(o)}else{var a=L(),u=e.outerHTML.replace(/data-retry-id="[^"]+"/,"").replace(/src=(?:"[^"]+"|.+)([ >])/,`${s}=${a} src="${r}"$1`);y.write(u);var f=y.querySelector(`script[${s}="${a}"]`);f&&(f.onload=t)}},j=function(e){try{return e.rules}catch(r){try{return e.cssRules}catch(e){return null}}},I=function(e,r,t){var n=y.createElement("link");Object.keys(p.prototype).forEach((function(r){if("href"!==r&&e[r]&&"object"!=typeof e[r])try{n[r]=e[r]}catch(e){}})),n.href=r,n.onload=t||e.onload,n.onerror=e.onerror,n.setAttribute(s,L()),y.getElementsByTagName("head")[0].appendChild(n)},S=function(e){return e?e instanceof h?[e.nodeName,e.src,e.href,e.getAttribute(s)].join(";"):"not_supported":"null"},L=function(){return Math.random().toString(36).slice(2)},O=function(e){return e instanceof v||e instanceof m?e.src:e instanceof p?e.href:""},_={},k=function(e){return Array.isArray(e)?e.reduce((function(e,r,t,n){return e[r]=n[(t+1)%n.length],e}),{}):e},$=function(e,r){return e.substr(e.indexOf(r)+r.length,e.length)},x=function(e,r){return Object.keys(r).filter((function(r){return e.indexOf(r)>-1})).sort((function(e,r){return r.length-e.length}))[0]},M=function(n,o){var i=R(n,o),a=i[0],u=i[1];return a?(_[a]=_[a]||{[e]:0,[t]:[],[r]:[]},[u,_[a]]):[]},R=function(e,r){var t=x(e,r);return t?[$(e,t),t]:["",""]},H={};var N={},C=[],B=function(e,r){var t=["backgroundImage","borderImage","listStyleImage"];e.forEach((function(e){var n=j(e);if(null!==n){var i=T(n);i.forEach((function(n){t.forEach((function(t){!function(e,r,t,n,i){var a,f=i[u],c=i[o],l=null==(a=null==r?void 0:r.style)?void 0:a[e];if(l&&!/^url(["']?data:/.test(l)){var s=(l.match(/^url(["']?(.+?)["']?)/)||[])[1];if(s){var d=x(s,f);if(d){for(var y=d,h={[y]:!0};y&&f[y];){var v=f[y];if(h[v])break;h[v]=!0,y=v}var g=Object.keys(h).map((function(e){var r=E(s,d,e),t=c(r,s,null);return t?`url("${t}")`:null})).filter(Boolean).join(","),p=r.selectorText+`{ ${function(e){return e.replace(/([a-z])([A-Z])/g,(function(e,r,t){return`${r}-${t.toLowerCase()}`}))}(e)}: ${g} ${i.styleImageNoImportant?"":"!important"}; }`;try{t.insertRule(p,n.length)}catch(v){t.insertRule(p,0)}}}}}(t,n,e,i,r)}))})),e.href&&(N[e.href]=!0),e.ownerNode instanceof g&&C.push(e.ownerNode)}}))},W=function(e,r){return T(e).filter((function(e){if(!function(e){return!!j(e)}(e))return!1;if(!e.href){var t=e.ownerNode;return!(t instanceof g&&C.indexOf(t)>-1)}return!N[e.href]&&!!x(e.href,r)}))};return function(){var h=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};try{if("object"!=typeof h[u])throw new Error("opts.domain cannot be non-object.");var g=[a,u,"retryAsync",o,i,n,f],$=Object.keys(h).filter((function(e){return-1===g.indexOf(e)}));if($.length>0)throw new Error("option name: "+$.join(", ")+" is not valid.");var x={[n]:h[n]||3,[o]:h[o]||b,[i]:h[i]||A,[a]:h[a]||A,[u]:k(h[u]),[f]:h[f]||!1};return function(f){var d=f[o],h=f[i],g=f[a],b=f[u],A=function(r){if(r){var o=r.target||r.srcElement,i=O(o);if(i){var a=M(i,b),u=a[0],y=a[1],h=o instanceof HTMLElement&&o.hasAttribute(l);if(y&&u&&!h){y[e]++,y[t].push(i);var A=y[e]>f[n];if(A){var T=R(i,b)[0];g(T)}if(b[u]&&!A){var j=b[u],_=E(i,u,j),k=d(_,i,y);if(null!==k){if("string"!=typeof k)throw new Error('a string should be returned in "onRetry" function');if(o instanceof m&&o.src)return o.setAttribute(s,L()),void(o.src=k);var $=S(o);if(!H[$]){if(H[$]=!0,o instanceof v&&!o.getAttribute(c)&&o.src)return void w(o,k);if(o instanceof p&&!o.getAttribute(c)&&o.href)return void I(o,k)}}}}}}};y.addEventListener("error",A,!0),y.addEventListener("load",(function(e){if(e){var t=e.target||e.srcElement,n=O(t);if(n){var o=M(n,b)[1],i=_slicedToArray(R(n,b),1)[0],a=function(){o&&o[r].push(n),h(i)};if(t instanceof p){if(y.styleSheets){var u=T(y.styleSheets).filter((function(e){return e.href===t.href}))[0],f=j(u);if(null!==f){if(0===f.length)return void A(e);a()}}}else a()}}}),!0)}(x),function(e){var r=y.styleSheets,t=e[u];if(!r)return!1;setInterval((function(){var r=W(y.styleSheets,t);r.length>0&&B(r,e)}),250)}(x),_}catch(g){d.console&&console.error("[assetsRetry] error captured",g)}}})); </script> <script> try { window.vcloudAssetsRetry({ domain: ['unpkg.byted-static.com', 'lf-cdn-tos.bytescm.com/obj/unpkg', 'lf-livesaas.volccdn.com/obj/unpkg'], maxRetryCount: 9, }) window.vcloudAssetsRetry({ domain: ['mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client', 'lf-livesaas.volccdn.com/obj/vcloud-fe/livesaas-client', 'lf3-cm.ecombdstatic.com/obj/vcloud-fe/livesaas-client'], maxRetryCount: 9, }) } catch(_e) {} </script> </head>
完成以下步骤,将观播 SDK 集成到您的 Web 应用中。推荐您使用 byted-livesaas-dev Skill 快速集成。
您可选择使用 WebSDK Loader 接入,或手动指定 SDK 版本接入。推荐您使用 WebSDK Loader 加载观播 SDK。
WebSDK Loader 用于统一加载 Web 观播 SDK,可降低 SDK 接入、升级和问题排查成本。接入后,Loader 会前置加载稳定性监控能力,在 SDK 资源加载失败、初始化失败等异常发生时更早采集诊断日志,便于定位与解决问题;在您允许远程升级的前提下,Loader 可自动选择经过灰度验证的稳定版本,减少手动修改版本号和重新发版的成本,并支持快速回滚和异常自动兜底到稳定版本。
Loader 仅负责稳定性监控、版本决策和资源调度。接入时,您只需引入一个 Loader script,并在初始化 Web 观播 SDK 前等待 Loader 加载完成,无需在页面中手动引入 Web 观播 SDK 的 CSS 和 JS 资源。接入前,您可以结合 Loader 的体积和加载耗时评估对页面性能的影响。
参考以下代码,在本地项目工程的 index.html 文件内引入 WebSDK Loader。
<script id="livesaas-websdk-loader-script-tag" src="https://unpkg.byted-static.com/byted/livesaas-websdk-loader/1.0.3/dist/index.min.js" defer crossorigin="anonymous" data-access-type="mobile" data-fallback-version="2.1.55" data-allow-remote-update-sdk-version="true" data-decision-service-endpoint="https://live.byteoc.com/apiservice/websdk-loader-decision" data-fetch-timeout-ms="3000" data-live-activity-id="1815732009407497" ></script>
参数说明如下所示:
参数 | 是否必填 | 说明 |
|---|---|---|
| 是 | Loader script 标签的唯一标识。固定取值为 |
| 是 | WebSDK Loader 的资源地址。固定取值为 |
| 否 | 跨域资源加载配置。固定取值为 |
| 是 | 接入终端资源的类型。可取值:
注意
|
| 否 | 是否允许远程升级至稳定版本。默认为
|
| 是 | 当 |
| 否 | 单次资源加载超时时间,单位为毫秒。默认为 说明 该参数仅在 |
| 否 | 企业直播账号 ID。若您有定制化的版本需求,可联系技术支持,通过本参数指定企业直播账号。 说明 该参数仅在 |
| 否 | 直播间活动 ID。若您有直播间维度的定制化版本需求,可联系技术支持,通过本参数指定直播间。 说明 该参数仅在 |
| 否 | 观众的唯一标识。若您有观众维度的定制化版本需求,可联系技术支持,通过本参数指定观众。 说明 该参数仅在 |
参考以下代码,在本地项目工程的 index.html 文件内引入样式文件和脚本文件。
国内域名:https://mediaservice-fe.volccdn.com/obj/vcloud-fe
注意事项
// PC 端(仅支持模块化接入) <link rel="stylesheet" href="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/pc/css/index.2.1.59.css"> <script src="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/pc/js/index.2.1.59.js"></script> // PC 端(单独接入播放器模块,仅支持点播、直播、清晰度、倍速以及多线路等播放器相关功能。性能优于 PC 端模块化接入方式) <link rel="stylesheet" href="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/player-pc/css/index.2.1.59.css"> <script src="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/player-pc/js/index.2.1.59.js"></script> // 移动端(支持模块化接入或整页接入) <link rel="stylesheet" href="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/mobile/css/index.2.1.59.css"> <script src="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/mobile/js/index.2.1.59.js"></script> // 移动端(仅支持整页接入,性能优于其他移动端整页接入方式) <link rel="stylesheet" href="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/mobile-all/css/index.2.1.59.css"> <script src="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/mobile-all/js/index.2.1.59.js"></script> // 移动端(单独接入播放器模块,仅支持点播、直播、清晰度、倍速以及多线路等播放器相关功能。性能优于其他移动端模块化接入方式) <link rel="stylesheet" href="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/player-mobile/css/index.2.1.59.css"> <script src="https://mediaservice-fe.volccdn.com/obj/vcloud-fe/livesaas-client/player-mobile/js/index.2.1.59.js"></script>
资源引入后, ByteLiveWebSDK 挂载在 window 下。您可以通过以下方式,将观播 SDK 集成到您的 Web 应用中,从而在观看页展示直播间或点播播放器。有关代码中的参数配置,详见配置参数。有关监听与触发事件,详见事件。有关方法调用,详见属性及方法。
如果您使用 WebSDK Loader 接入,需要先等待 Loader 完成版本决策、资源加载和异常兜底后,再初始化 ByteLiveWebSDK。初始化代码如下所示:
window.LiveSaaSWebSDKLoader.ready() .then(function () { var webSDK = new window.ByteLiveWebSDK({ activityId: 169410856822****, token: 'JC****', service: "Demo", mode: 1, modules: [ { id: "player", // 接入方页面内的元素 ID, 视频模块会嵌入到此元素内 mode: "player", }, { id: "content", // 接入方页面内的元素 ID, 菜单栏模块会嵌入到此元素内 mode: "menu", }, ], options: { mobileBackgroundTransparent: true, saveUserInfo: true, }, }); webSDK.on("error", console.log); }) .catch(function (error) { console.error("LiveSaaSWebSDKLoader ready failed", error); });
手动指定版本接入的示例代码如下所示:
直播间 SDK 初始化代码示例如下所示:
var webSDK = new window.ByteLiveWebSDK({ activityId: 169410856822****, token: 'JC****', service: 'Demo', mode: 1, modules: [ { id: "player", mode: "player", }, { id: "menu", mode: "menu", menu: ["comment"], } ], options: {} }) webSDK.emit('player.pause'); // 触发事件 webSDK.on('player.pause', () => {}); // 监听事件
SDK 元素的 class 属性值不可更改。您可以通过变更 class 属性的样式属性及其属性值,覆盖对应元素的样式,实现样式自定义。
您可以选择以下任一方法验证接入效果。
在本地 localhost:8080 端口进行调试,但此种调试方法无法播放预告和回放。有关本地调试方法,详见 Demo 体验集成示例。
建议在 PC 上使用 SDK demo playground 进行线上效果调试。通过 SDK demo playground 配置不同版本的 SDK 以及不同直播间,修改模板代码后可实时预览效果。详见企业直播 Web SDK demo playground。
https://lf-cdn-tos.bytescm.com/obj/static 变更为企业直播专属域名 https://mediaservice-fe.volccdn.com/obj/vcloud-fe。原域名 https://lf-cdn-tos.bytescm.com/obj/static 后续可能不再支持使用,建议您在集成 2.1.0 及以上版本时,使用新域名 https://mediaservice-fe.volccdn.com/obj/vcloud-fe。