实例化与参数配置
var engine = new P2PEngineShaka(player, {p2pConfig: [opts]}, videojs = window.videojs);
创建一个新的 P2PEngineShaka 实例,其中 player 是 Shaka Player 的实例。
如果指定了 opts ,那么对应的默认值将会被覆盖。
字段 | 类型 | 默认值 | 描述 |
---|---|---|---|
logLevel | string|boolean | 'error' | log的等级,分为warn、error、none,设为true等于warn,设为false等于none。 |
token | string | undefined | token用于控制台多域名数据汇总展示,另外如果自定义channelId也需要设置token。 |
trackerZone | string | 'eu' | tracker服务器地址的国家代号,分为'cn'、'eu'、'hk'、'us'。 |
memoryCacheLimit | Object | {"pc": 400 * 1024 * 1024, "mobile": 100 * 1024 * 1024} | p2p缓存的最大数据量,分为PC和mobile。 |
p2pEnabled | boolean | true | 是否开启P2P。 |
webRTCConfig | Object | {} | 用于配置stun和datachannel的字典。 |
useHttpRange | boolean | true | 在可能的情况下使用Http Range请求来补足p2p下载超时的剩余部分数据。 |
httpLoadTime | number | 3.0 | P2P下载超时后留给HTTP下载的时间。 |
sharePlaylist | boolean | false | 是否允许m3u8文件的P2P传输。 |
useDiskCache | boolean | true | 点播模式用 IndexedDB 存储数据。 |
diskCacheLimit | Object | {"pc": 1500 * 1024 * 1024, "mobile": 1000 * 1024 * 1024} | 磁盘缓存的最大数据量,分为PC和mobile。 |
prefetchOnly | boolean | false | HLS模式下只采用预加载的方式进行P2P下载。 |
P2PEngineShaka API
P2PEngineShaka.version (static)
获取 P2PEngineShaka 的版本号。
P2PEngineShaka.protocolVersion (static)
获取 P2P 协议的版本号。
P2PEngineShaka.isSupported() (static method)
判断当前浏览器是否支持WebRTC datachannel。
engine.enableP2P()
在p2p暂停或未启动情况下启动p2p。
engine.disableP2P()
停止p2p并释放内存。
engine.destroy()
停止p2p、销毁engine并释放内存。
P2PEngineShaka 事件
engine.on('peerId', function (peerId) {})
当从服务端获取到peerId时回调该事件。
engine.on('peers', function (peers) {})
当与新的节点成功建立p2p连接时回调该事件。
engine.on('stats', function (stats) {})
该回调函数可以获取p2p信息,包括:
stats.totalHTTPDownloaded: 从HTTP(CDN)下载的数据量(单位KB)
stats.totalP2PDownloaded: 从P2P下载的数据量(单位KB)
stats.totalP2PUploaded: P2P上传的数据量(单位KB)
stats.p2pDownloadSpeed: P2P下载速度(单位KB/s)
engine.on('serverConnected', function (connected) {})
当连接/断开websocket时回调该事件。
engine.on('exception', function (e) {})
该回调函数可以获取SDK的异常信息,包括:
e.code: 异常标识(TRACKER_EXPT SIGNAL_EXPT)
e.message: 异常信息
e.stack: 异常堆栈信息
通过p2pConfig获取p2p信息
p2pConfig: {
getStats: function (totalP2PDownloaded, totalP2PUploaded, totalHTTPDownloaded, p2pDownloadSpeed) {
// 获取p2p下载信息
},
getPeerId: function (peerId) {
// 获取本节点的Id
},
getPeersInfo: function (peers) {
// 获取成功连接的节点的信息
},
onHttpDownloaded: function (traffic) {
// 监听http下载流量
},
onP2pDownloaded: function (traffic, speed) {
// 监听p2p下载流量和速度
},
onP2pUploaded: function (traffic) {
// 监听p2p上传流量
},
}
WARNING
下载和上传数据量的单位是KB,下载速度的单位是KB/s。
高级用法
解决动态 m3u8/mpd 路径问题
某些流媒体提供商的 m3u8/mpd 是动态生成的,不同节点的mpd地址不一样,例如example.com/clientId1/streamId.mpd和example.com/clientId2/streamId.mpd, 而本插件默认使用m3u8/mpd作为channelId。这时候就要构造一个共同的chanelId,使实际观看同一直播/视频的节点处在相同频道中。
// 必须先在 p2pConfig 设置 token ,才能自定义 channelId !
p2pConfig: {
token: YOUR_TOKEN,
channelId: function (mpdUrl) {
const videoId = extractVideoIdFromUrl(mpdUrl); // 忽略差异部分,构造一个一致的channelId,其中 extractVideoIdFromUrl 需要自己定义,可以抽取url中的视频ID作为结果返回
return videoId;
}
// channelId: VIDEO_ID // for fixed channel id
}
解决动态切片路径问题
类似动态mpd路径问题,相同切片文件的路径也可能有差异,这时候需要忽略切片路径差异的部分。插件默认用切片的绝地路径(url)来标识每个切片文件,所以需要通过钩子函数重新构造标识符。可以按如下设置:
p2pConfig: {
/*
segmentUrl: The url of segment
range: The byte range of segment
*/
segmentId: function (segmentUrl, range) {
const segId = extractSegmentIdFromUrl(segmentUrl, range);
return segId;
}
}
p2pConfig: {
/*
streamId: The id of stream
sn: The serial number of segment
segmentUrl: The url of segment
range: The byte range of segment
*/
segmentId: function (streamId, sn, segmentUrl, range) {
const tsId = extractSegmentIdFromUrl(segmentUrl);
return tsId;
}
}
自行配置 STUN 和 TURN 服务器地址
STUN用于p2p连接过程中获取公网IP地址,TURN则可以在p2p连接不通时用于中转数据。本SDK已内置公开的STUN服务,开发者可以通过P2pConfig来更换STUN地址。TURN服务器则需要开发者自行搭建,可以参考coturn。
p2pConfig: {
webRTCConfig: {
iceServers: [
{ urls: YOUR_STUN_OR_TURN_SERVER }
]
}
}
允许Http Range请求
当对等端上行带宽不够时,可能导致p2p传输超时而转向http下载,原本p2p下载的数据无法复用。Http Range请求用于补足p2p下载超时的剩余部分数据,要开启Http Range,首先需要源服务器支持,然后增加以下配置:
p2pConfig: {
useHttpRange: true,
}
切片合法性校验
有时候我们需要校验从节点下载的切片的合法性(类似bittorrent的哈希校验)。 CDNBye提供了一个钩子函数,可以回调下载的切片供开发者进行校验。用于校验的 哈希表建议直接从服务器下载,开发者可以通过程序计算每个ts文件的哈希并存储于 特定的文件中或者直接嵌入到m3u8文件中。如果校验失败,直接在回调函数中 返回false即可。
p2pConfig: {
validateSegment: function (segId, buffer) {
var hash = hashFile.getHash(segId);
return hash === md5(buffer);
}
}