API文档
# P2P配置
用建造者模式实例化 P2pConfig,以下的参数是默认值:
P2pConfig config = new P2pConfig.Builder()
.logEnabled(false) // 是否打印日志
.logLevel(LogLevel.WARN) // 打印日志的级别
.announce("https://tracker.cdnbye.com/v1") // tracker服务器地址
.AnnounceLocation(AnnounceLocation.Europe) // tracker服务器地址所在国家的枚举,分为Europe、HongKong、USA
.downloadTimeout(30_000, TimeUnit.MILLISECONDS) // HTTP下载ts文件超时时间
.localPortHls(0) // HLS本地代理服务器的端口号(默认随机端口,设置-1关闭Hls代理)
.localPortMp4(0) // MP4本地代理服务器的端口号(默认随机端口,设置-1关闭Mp4代理)
.localPortDash(0) // DASH本地代理服务器的端口号(默认随机端口,设置-1关闭Dash代理)
.diskCacheLimit(1500*1024*1024) // 点播模式下P2P在磁盘缓存的最大数据量(设为0可以禁用磁盘缓存)
.memoryCacheCountLimit(30) // P2P在内存缓存的最大数据量,用ts文件个数表示
.p2pEnabled(true) // 开启或关闭p2p engine
.withTag(null) // 用户自定义的标签,可以在控制台查看分布图
.webRTCConfig(null) // 通过webRTCConfig来修改WebRTC默认配置
.maxPeerConnections(20) // 最大连接节点数量
.useHttpRange(true) // 在可能的情况下使用Http Range请求来补足p2p下载超时的剩余部分数据
.httpHeadersForHls(null) // 设置请求ts和m3u8时的HTTP请求头
.httpHeadersForMp4(null) // 设置请求mp4时的HTTP请求头
.httpHeadersForDash(null) // 设置请求dash描述文件和媒体文件时的HTTP请求头
.httpHeadersForFile(null) // 设置文件下载请求时的HTTP请求头
.isSetTopBox(false) // 如果运行于机顶盒请设置成true
.fileCacheDirectory(null) // 文件下载的文件保存路径,如果挂载了SD卡默认是"/Android/data/[app_package_name]/cache/p2p-engine",
.pieceLengthForMp4(1024*1024) // MP4的切片大小,HTTP下载和P2P传输的基本单位
.pieceLengthForFile(1024*1024) // 文件下载的切片大小,HTTP下载和P2P传输的基本单位
.waitForPeer(false) // 优先尝试从对等端下载前几片数据,可以提高P2P比例,但可能会增加起播延时
.waitForPeerTimeout(4500) // waitForPeer的超时时间,超时后恢复从http下载
.httpLoadTime(2_000) // P2P下载超时后留给HTTP下载的时间
.sharePlaylist(false) // 是否允许m3u8文件的P2P传输
.logPersistent(false) // 是否将日志持久化到外部存储(Environment.getExternalStorageDirectory()路径下的logger文件夹)
.geoIpPreflight(true) // 直播模式下向在线IP数据库请求ASN等信息,从而获得更准确的调度
.build();
P2pEngine.init(getApplicationContext(), token, config);
# P2pEngine
实例化P2pEngine,获得一个全局单例:
P2pEngine engine = P2pEngine.init(Context context, String token, P2pConfig config);
参数说明:
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
context | Context | 是 | 建议使用Application 的 Context 对象。 |
token | String | 是 | CDNBye分配的token。 |
config | P2pConfig | 否 | 自定义配置。 |
# 切换源
当播放器切换到新的播放地址时,只需要将新的播放地址传给 P2pEngine,从而获取新的本地播放地址:
String newParsedURL = P2pEngine.getInstance().parseStreamUrl(url);
# P2pEngine API
# P2pEngine.Version
当前插件的版本号。
# P2pEngine.protocolVersion
获取 P2P 协议的版本号,与其他平台互通的前提是 P2P 协议版本号相同。
# P2pEngine.getInstance()
获取 P2pEngine 的单例。
# engine.parseStreamUrl(String url)
将原始播放地址(m3u8或者mp4)转换成本地代理服务器的地址。
# engine.parseStreamUrl(String url, String videoId)
将原始播放地址(m3u8或者mp4)转换成本地代理服务器的地址,同时传入videoId用以构造channelId。
# engine.parseStreamUrl(String url, String videoId, MimeType mimeType)
除了原始播放地址(m3u8/mpd)以及videoId,同时传入mimeType(目前支持MimeType.APPLICATION_M3U8和MimeType.APPLICATION_MPD),用于无".m3u8"或".mpd"后缀的url。
# engine.isConnected()
是否已与CDNBye后台建立连接。
# engine.stopP2p()
立即停止P2P加速并释放资源,一般只需要在退出APP的时候调用即可。SDK采用"懒释放"的策略,只有在重启p2p的时候才释放资源。对于性能较差的设备起播耗时可能比较明显,建议在视频播放之前提前调用 engine.stopP2p() 。
# engine.restartP2p()
重启P2P加速服务,一般不需要调用。
# engine.getPeerId()
获取对等连接的id。
# engine.setHttpHeadersForHls(Map<String, String> headers)
动态设置请求ts和m3u8时的HTTP请求头。
# engine.setHttpHeadersForMp4(Map<String, String> headers)
动态设置请求mp4文件时的HTTP请求头。
# engine.setHttpHeadersForFile(Map<String, String> headers)
动态设置文件下载时的HTTP请求头。
# engine.disableP2p()
运行时动态关闭P2P,在播放下一个媒体文件时才生效。
# engine.enableP2p()
运行时动态开启P2P,在播放下一个媒体文件时才生效。
# engine.shutdown()
停止P2P并关闭代理服务器。
# engine.downloadFile(String url)
开始下载url对应的文件。
返回 DownloadInfo 对象,包含了下载信息,包括:
long getFileSize() 获取文件总大小
String getUrl() 获取文件url
String getFileName() 获取文件名
String getMimeType() 获取http响应头的 MimeType
File getCacheFile() 获取文件保存路径
boolean isCached() 文件是否已经缓存了,如果是的话直接可以使用,不需要下载
boolean isInProgress() 文件是否正在下载
# engine.downloadFile(String url, String fileName)
开始下载url对应的文件,其中 fileName 是保存在本地的文件名。
# engine.downloadFile(String url, String fileName, File cacheDir)
开始下载url对应的文件,其中 fileName 是保存在本地的文件名, cacheDir 是文件保存路径。
# engine.downloadFile(String url, String fileName,String channelId)
开始下载url对应的文件,其中 fileName 是保存在本地的文件名,channelId 用于标识p2p频道。
# engine.downloadFileNormally(String url)
普通文件下载,不使用P2P。
# engine.stopFileDownload()
停止文件下载,关闭P2P并释放占用的記憶體。
# engine.pauseFileDownload()
暂停文件下载,此时P2P文件交换正常进行。
# engine.deleteDownloadedFile(File file)
删除正在下载或已下载的文件file。
# P2P统计
通过 P2pStatisticsListener 来监听P2P下载信息:
engine.addP2pStatisticsListener(new P2pStatisticsListener() {
@Override
public void onHttpDownloaded(long value) {
}
@Override
public void onP2pDownloaded(long value, int speed) {
}
@Override
public void onP2pUploaded(long value, int speed) {
}
@Override
public void onPeers(List<String> peers) {
}
@Override
public void onServerConnected(boolean connected) {
}
});
下载和上传数据量的单位是KB,下载速度的单位是KB/s。
# 监听文件下载情况
engine.registerFileDownloadListener(new FileDownloadListener() {
@Override
public void onDownloadFailed(Throwable e) {
// fallback
}
@Override
public void onDownloadFinished(File cacheFile, String url) {
// get downloaded file here
}
@Override
public void onCacheAvailable(File cacheFile, String url, int percentsAvailable) {
// show progress to user
}
});
# 移除文件下载监听
engine.unregisterFileDownloadListener(FileDownloadListener listener)
# 高级用法
# 回调播放器信息
在直播或者MP4播放模式下,为了增强P2P效果并提高播放流畅度,建议通过 setPlayerInteractor ,将从当前播放时间到缓冲前沿的时间间隔回调给p2p engine。
import com.cdnbye.core.p2p.PlayerInteractor;
P2pEngine.getInstance().setPlayerInteractor(new PlayerInteractor() {
public long onBufferedDuration() {
// Exoplayer 单位:毫秒
return player.getBufferedPosition() - player.getCurrentPosition();
}
});
在点播模式下,一个视频的时长可能比较大,如果能在节点匹配的时候优先匹配播放时间接近的节点则有助于P2P效果的提升,要实现这个功能需要在SDK层面获取播放器的当前播放时间:
import com.cdnbye.core.p2p.PlayerInteractor;
P2pEngine.getInstance().setPlayerInteractor(new PlayerInteractor() {
public long onCurrentPosition() {
// Exoplayer 单位:毫秒
return player.getCurrentPosition();
}
});
# 解决动态url路径问题
某些CDN提供商提供的url是动态生成的,不同节点的地址不一样,例如example.com/clientId1/streamId.m3u8和example.com/clientId2/streamId.m3u8, 而本插件默认使用url(去掉查询参数)作为channelId。这时候就要构造一个共同的chanelId,使实际观看同一直播/视频(下载同一文件)的节点处在相同频道中。构造channelId方法如下:
- HLS & DASH & MP4
String videoId = extractVideoIdFromUrl(urlString); // extractVideoIdFromUrl 需要自己定义,可以抽取url中的视频ID作为结果返回
String parsedUrl = P2pEngine.getInstance().parseStreamUrl(urlString, videoId);
- 文件下载
String fileId = extractFileIdFromUrl(urlString); // extractFileIdFromUrl 需要自己定义,可以抽取url中的文件ID作为结果返回
P2pEngine.getInstance().downloadFile(url, url, fileId);
如果要与其他平台互通,则必须确保两者拥有相同的 token 和 channelId 。
# 解决动态ts路径问题
类似动态m3u8/mpd路径问题,相同ts文件的路径也可能有差异,这时候需要忽略ts路径差异的部分。插件默认用ts的绝地路径(url)来标识每个ts文件,所以需要通过钩子函数重新构造标识符。可以按如下设置:
/*
streamId: The id of stream
sn: The serial number of segment
segmentUrl: The url of segment
range: Byte range of segment
*/
// For HLS
P2pEngine.getInstance().setHlsSegmentIdGenerator(new HlsSegmentIdGenerator() {
@Override
public String onSegmentId(String streamId, long sn, String segmentUrl, String range) {
return extractIdFromSegment(segmentUrl, range);
}
});
// For DASH
P2pEngine.getInstance().setDashSegmentIdGenerator(new DashSegmentIdGenerator() {
@Override
public String onSegmentId(String streamId, String segmentUrl, String range) {
return extractIdFromSegment(segmentUrl, range);
}
});
# 设置HTTP请求头
出于防盗链或者统计的需求,有些HTTP请求需要加上 User-Agent 等头信息,可以通过 setHttpHeaders 进行设置:
Map headers = new HashMap();
headers.put("User-Agent", "XXX");
engine.setHttpHeadersForHls(headers); // For hls playback
// engine.setHttpHeadersForDash(headers); // For dash playback
// engine.setHttpHeadersForMp4(headers); // For mp4 playback
// engine.setHttpHeadersForFile(headers); // For file download
# 传入自定义 OkHttpClient
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new YourInterceptor())
.build();
P2pConfig config = new P2pConfig.Builder()
.okHttpClient(httpClient)
.build();
# 扩展支持的HLS媒体文件
默认只支持".ts"等为后缀的常见文件类型,如果需要支持类似".image"的文件类型,需要做以下配置:
P2pConfig config = new P2pConfig.Builder()
.hlsMediaFiles(new ArrayList<String>(){{
add("mp4");
add("ts");
add("m4s");
add("m4v");
add("image");
}})
.build();
一般HLS媒体文件以".xx"结尾,但也有例外情况,比如其他任意字符结尾,为了让本地代理能识别出这些扩展,需要做以下配置:
// 假如媒体文件url是 http://example.com/pathxxx
P2pConfig config = new P2pConfig.Builder()
.hlsMediaFileExtensions(new ArrayList<String>(){{
add("xxx");
}})
.build();
# P2P优先策略
由于建立P2P连接需要时间,默认情况下前几片用HTTP下载。可以通过配置参数,等待P2P建立连接后优先用P2P下载,从而提升P2P效果,但可能会带来延时,建议在热度比较大的频道开启。
P2pConfig config = new P2pConfig.Builder()
.waitForPeer(true)
.waitForPeerTimeout(4500) // 可以根据具体场景设置超时时间
.build();
暂不支持MPEG-DASH和多码率HLS。
# 拦截m3u8文件
由于 SDK 需要解析m3u8的内容,如果您用了加密的m3u8,则需要使用拦截器拦截并返回标准的m3u8文件:
P2pEngine.getInstance().setHlsInterceptor(new HlsInterceptor() {
@Override
public byte[] interceptPlaylist(byte[] text, String url) {
return handlePlaylist(text, url);
}
});
# 自行配置 STUN 和 TURN 服务器地址
STUN用于p2p连接过程中获取公网IP地址,TURN则可以在p2p连接不通时用于中转数据。本SDK已内置公开的STUN服务,开发者可以通过P2pConfig来更换STUN地址。TURN服务器则需要开发者自行搭建,可以参考coturn (opens new window)。
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();
# 监听SDK异常信息
由于网络、服务器和算法bug等原因,SDK可能会出现异常,可以通过 registerExceptionListener 方法来监听异常:
P2pEngine.getInstance().registerExceptionListener(new EngineExceptionListener() {
@Override
public void onTrackerException(EngineException e) {
// Tracker Exception
}
@Override
public void onSignalException(EngineException e) {
// Signal Server Exception
}
@Override
public void onSchedulerException(EngineException e) {
// Scheduler Exception
}
@Override
public void onOtherException(EngineException e) {
// Other Exception
}
});