API文档
# P2P配置
用建造者模式实例化 P2pConfig,以下的参数是默认值:
P2pConfig config = new P2pConfig.Builder()
.logEnabled(false) // 是否打印日志
.logLevel(LogLevel.WARN) // 打印日志的级别
.announce("https://tracker.cdnbye.com/v1") // tracker服务器地址
.wsSignalerAddr("wss://signal.cdnbye.com") // 信令服务器地址
.downloadTimeout(15_000, TimeUnit.MILLISECONDS) // HTTP下载ts文件超时时间
.dcDownloadTimeout(6_000, TimeUnit.MILLISECONDS) // datachannel下载二进制数据的最大超时时间
.localPort(0) // 本地代理服务器的端口号(默认随机端口)
.diskCacheLimit(1024*1024*1024) // 点播模式下P2P在磁盘缓存的最大数据量(设为0可以禁用磁盘缓存)
.memoryCacheCountLimit(30) // P2P在内存缓存的最大数据量,用ts文件个数表示
.p2pEnabled(true) // 开启或关闭p2p engine
.wifiOnly(false) // 是否只在wifi和有线网络模式上传数据(建议在云端设置)
.withTag("unknown") // 用户自定义的标签,可以在控制台查看分布图
.webRTCConfig(null) // 通过webRTCConfig来修改WebRTC默认配置
.maxPeerConnections(15) // 最大连接节点数量
.useHttpRange(true) // 在可能的情况下使用Http Range请求来补足p2p下载超时的剩余部分数据
.httpHeaders(null) // 设置请求ts和m3u8时的HTTP请求头
.channelIdPrefix(null) // 如果使用自定义的channelId,则此字段必须设置,且长度必须在5到15个字符之间,建议设置成你所在组织的唯一标识
.isSetTopBox(false) // 如果运行于机顶盒请设置成true
.fastStartup(true) // 前几个ts直接向服务器请求,不走代理服务器,提高起播速度
.playlistMaxRetries(2) // 本地代理请求m3u8或者mpd失败时的最大重试次数
.build();
P2pEngine.initEngine(getApplicationContext(), token, config);
# P2pEngine
实例化P2pEngine,获得一个全局单例:
P2pEngine engine = P2pEngine.initEngine(Context context, String token, P2pConfig config);
参数说明:
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
context | Context | 是 | 建议使用Application 的 Context 对象。 |
token | String | 是 | CDNBye分配的token。 |
config | P2pConfig | 否 | 自定义配置。 |
# 切换源
当播放器切换到新的播放地址时,只需要将新的播放地址(m3u8)传给 P2pEngine,从而获取新的本地播放地址:
String newParsedURL = P2pEngine.getInstance().parseStreamUrl(url);
# P2pEngine API
# P2pEngine.Version
当前插件的版本号。
# P2pEngine.protocolVersion
获取 P2P 协议的版本号,与其他平台互通的前提是 P2P 协议版本号相同。
# P2pEngine.getInstance()
获取 P2pEngine 的单例。
# engine.parseStreamUrl(String url)
将原始播放地址(m3u8)转换成本地代理服务器的地址。
# engine.parseStreamUrl(String url, String videoId)
将原始播放地址(m3u8)转换成本地代理服务器的地址,同时传入videoId用以构造channelId。
# engine.isConnected()
是否已与CDNBye后台建立连接。
# engine.stopP2p()
停止P2P加速并释放资源,一般不需要调用。SDK采用"懒释放"的策略,只有在重启p2p的时候才释放资源。对于性能较差的设备起播耗时可能比较明显,建议在视频播放之前提前调用 engine.stopP2p() 。
# engine.restartP2p()
重启P2P加速服务,一般不需要调用。
# engine.getPeerId()
获取对等连接的id。
# engine.setHttpHeaders(Map<String, String> headers)
动态设置请求ts和m3u8时的HTTP请求头。
# engine.shutdown()
停止P2P并关闭代理服务器。
# P2P统计
通过 P2pStatisticsListener 来监听P2P下载信息:
engine.addP2pStatisticsListener(new P2pStatisticsListener() {
@Override
public void onHttpDownloaded(long value) {
}
@Override
public void onP2pDownloaded(long value) {
}
@Override
public void onP2pUploaded(long value) {
}
@Override
public void onPeers(List<String> peers) {
}
@Override
public void onServerConnected(boolean connected) {
}
});
下载和上传数据量的单位是KB。
# 高级用法
# 直播流P2P优化
在直播模式下,为了增强P2P效果,建议通过 setPlayStats ,将从当前播放时间到缓冲前沿的时间间隔回调给p2p engine。
import com.cdnbye.sdk.PlayerStatsCallback;
P2pEngine.getInstance().setPlayStats(new PlayerStatsCallback() {
@Override
public long onBufferedDuration() {
// Exoplayer 单位:毫秒
return player.getBufferedPosition() - player.getCurrentPosition();
}
});
# 解决动态m3u8路径问题
某些流媒体提供商的m3u8是动态生成的,不同节点的m3u8地址不一样,例如example.com/clientId1/streamId.m3u8和example.com/clientId2/streamId.m3u8, 而本插件默认使用m3u8地址(去掉查询参数)作为channelId。这时候就要构造一个共同的chanelId,使实际观看同一直播/视频的节点处在相同频道中。构造channelId方法如下:
- SDK 版本 >= 1.10
// 必须先在 p2pConfig 设置 channelIdPrefix ,才能自定义 channelId ! 与其他平台互通需要构造相同的 channelIdPrefix 。
P2pConfig config = new P2pConfig.Builder()
.channelIdPrefix(YOUR_UNIQUE_ID)
.build();
P2pEngine.initEngine(getApplicationContext(), token, config);
// 如果m3u8里的ts是相对地址需要设置segmentId
P2pEngine.getInstance().setSegmentId(new SegmentIdCallback() {
@Override
public String onSegmentId(int level, long sn, String segmentUrl) {
return String.format("%d-%d", level, sn);
}
});
String videoId = extractVideoIdFromUrl(urlString); // extractVideoIdFromUrl 需要自己定义,可以抽取url中的视频ID作为结果返回
String parsedUrl = P2pEngine.getInstance().parseStreamUrl(urlString, videoId);
- SDK 版本 < 1.10
import com.cdnbye.sdk.ChannelIdCallback;
// 必须先在 p2pConfig 设置 channelIdPrefix ,才能自定义 channelId ! 与其他平台互通需要构造相同的 channelIdPrefix 。
P2pConfig config = new P2pConfig.Builder()
.channelIdPrefix(YOUR_UNIQUE_ID)
.build();
P2pEngine.initEngine(getApplicationContext(), token, config);
// 如果m3u8里的ts是相对地址需要设置segmentId
P2pEngine.getInstance().setSegmentId(new SegmentIdCallback() {
@Override
public String onSegmentId(int level, long sn, String segmentUrl) {
return String.format("%d-%d", level, sn);
}
});
P2pEngine.getInstance().setChannelId(new ChannelIdCallback() {
@Override
public String onChannelId(String urlString) {
return extractVideoIdFromUrl(urlString); // extractVideoIdFromUrl 需要自己定义,可以抽取url中的视频ID作为结果返回
}
});
如果要与其他平台互通,则必须确保两者拥有相同的 channelIdPrefix 和 channelId 。
# 解决动态ts路径问题
类似动态m3u8路径问题,相同ts文件的路径也可能有差异,这时候需要忽略ts路径差异的部分。插件默认用ts的绝地路径(url)来标识每个ts文件,所以需要通过钩子函数重新构造标识符。可以按如下设置:
/*
level: The quality level
sn: The serial number of segment
segmentUrl: The url of segment
*/
engine.setSegmentId(new SegmentIdCallback() {
@Override
public String onSegmentId(int level, long sn, String segmentUrl) {
return format(segmentUrl);
}
});
# 设置HTTP请求头
出于防盗链或者统计的需求,有些HTTP请求需要加上 referer 或者 User-Agent 等头信息,可以通过 setHttpHeaders 进行设置:
Map headers = new HashMap();
headers.put("referer", "XXX");
headers.put("User-Agent", "XXX");
engine.setHttpHeaders(headers);
# 切换信令
某些场景下需要动态修改信令地址,防止单个信令负载过大,例如根据播放地址的哈希值选择信令。可以通过调用 engine.setConfig(config) 运行时动态调整配置,示例如下:
P2pConfig config = new P2pConfig.Builder()
.wsSignalerAddr("wss://yoursignal2.com")
.build();
P2pEngine.getInstance().setConfig(config);
需要注意的是这个方法会重置 P2pEngine 的所有config,因此之前已经修改的字段需要再设置一次以保持一致。
# 自行配置 STUN 和 TURN 服务器地址
STUN用于p2p连接过程中获取公网IP地址,TURN则可以在p2p连接不通时用于中转数据。本SDK已内置公开的STUN服务,开发者可以通过P2pConfig来更换STUN地址。TURN服务器则需要开发者自行搭建,可以参考coturn。
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnection.RTCConfiguration;
List<PeerConnection.IceServer> iceServers = new ArrayList<>();
iceServers.add(PeerConnection.IceServer.builder(YOUR_STUN_OR_TURN_SERVER).createIceServer());
RTCConfiguration rtcConfig = new RTCConfiguration(iceServers);
P2pConfig config = new P2pConfig.Builder()
.webRTCConfig(rtcConfig)
.build();