参考地址 基于本地代理的边下边播技术分析
1.边下边播技术介绍
2.边下边播技术演进
这就是演进到播放器 <----> 本地代理服务器 <----> 视频源服务器,我们本文所讲的 边下边播的技术就是 基于本地代理服务展开的。
3.Socket监听
边下边播是基于本地代理,本地代理的建立依赖于Socket监听,那么什么是Socket?
Socket就是一组API,对TCP/IP协议进行封装的API,可以将Socket理解为处于传输层和应用层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。
Socket通讯流程简化如下:
服务端这边首先创建一个Socket(Socket()),然后绑定IP地址和端口号(Bind()),之后注册监听(Listen()),这样服务端就可以监听指定的Socket地址了; 客户端这边也创建一个Socket(Socket())并打开,然后根据服务器IP地址和端口号向服务器Socket发送连接请求(Connect()); 服务器Socket监听到客户端Socket发来的连接请求之后,被动打开,并调用Accept()函数接收请求,这样客户端和服务器之间的连接就建立好了; 成功建立连接之后就可以你侬我侬了,客户端和服务器进行数据交互(Receive()、Send()); 在腻歪完之后,各自关闭连接(Close()),交互结束;
4.边下边播技术点解析
4.1 视频类型
视频类型,我们知道有非分片视频和分片视频区分;像 mp4 mov mkv avi rmvb 这些封装格式都是非分片视频,一般情况下,播放器可以一次请求,后续处理,这些视频最终会存储到一个文件中;像现在mp4的封装格式应用的最广泛,有一个很优秀的开源库:https://github.com/danikula/AndroidVideoCache,主要是针对非分片视频的边下边播来的;
分片视频,就是一个整视频被分为若干个小分片视频,请求的时候不能一次性地请求所有的视频文件;会有一个视频索引文件,至于各个分片要依次请求,这种叫做分片视频。之前我们详细分析过M3U8视频的格式:多媒体文件格式剖析:M3U8篇,还有其中的TS视频格式:多媒体文件格式剖析:TS篇
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXTINF:9.009,
http://media.example.com/first.ts
#EXTINF:9.009,
http://media.example.com/second.ts
#EXTINF:3.003,
http://media.example.com/third.ts
#EXT-X-ENDLIST
这个HLS文件中有3个分片ts视频,我们请求的时候,需要一个一个请求,整视频请求数据是一次就可以的,后续使用206分段下载;
实现mp4 等非分片视频的边下边播是可以的,那么HLS分片视频如何实现边下边播呢?
4.2 分片视频如何处理
HLS视频----> HTTP Live Streaming,就是熟知的M3U8视频;
https://tv.youkutv.cc/2019/10/28/6MSVuLec4zbpYFlj/playlist.m3u8
什么样算是HLS类型的视频?
简单的判断,url解析出的path后缀名是 .m3u8的就是M3U8类型
通过视频的mimetype来判断:如果发现是下面四种类型,就是M3U8类型的视频,我们就可以按照M3U8解析的规则来解析这个视频url
public static String MIME_TYPE_M3U8_1 = "application/vnd.apple.mpegurl";
public static String MIME_TYPE_M3U8_2 = "application/x-mpegurl";
public static String MIME_TYPE_M3U8_3 = "vnd.apple.mpegurl";
public static String MIME_TYPE_M3U8_4 = "applicationnd.apple.mpegurl";
private boolean isM3U8Mimetype(String mimeType) {
return mimeType.contains(MIME_TYPE_M3U8_1)
|| mimeType.contains(MIME_TYPE_M3U8_2)
|| mimeType.contains(MIME_TYPE_M3U8_3)
|| mimeType.contains(MIME_TYPE_M3U8_4);
}
http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.main.m3u8
这个m3u8文件存储信息是:
#EXTM3U#EXT-X-VERSION:3#EXT-X-MEDIA-SEQUENCE:0#EXT-X-TARGETDURATION:11.0#EXTINF:10.12,http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.f10_0_10.ts#EXTINF:9.88,http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.f10_10_20.ts#EXTINF:10.08,http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.f10_20_30.ts#EXTINF:10.28,http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.f10_30_40.ts#EXTINF:9.68,http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.f10_40_50.ts#EXTINF:10.12,http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.f10_50_60.ts#EXTINF:3.04,http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.f10_60_63.ts#EXT-X-ENDLIST
转化成一个本地代理的文件:
#EXTM3U#EXT-X-VERSION:3#EXT-X-MEDIA-SEQUENCE:0#EXT-X-TARGETDURATION:11.0#EXTINF:10.12,http://127.0.0.1:3888/http%3A%2F%2Fvideoconverter.vivo.com.cn%2F201706%2F655_1498479540118.mp4.f10_0_10.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_0.ts#EXTINF:9.88,http://127.0.0.1:3888/http%3A%2F%2Fvideoconverter.vivo.com.cn%2F201706%2F655_1498479540118.mp4.f10_10_20.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_1.ts#EXTINF:10.08,http://127.0.0.1:3888/http%3A%2F%2Fvideoconverter.vivo.com.cn%2F201706%2F655_1498479540118.mp4.f10_20_30.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_2.ts#EXTINF:10.28,http://127.0.0.1:3888/http%3A%2F%2Fvideoconverter.vivo.com.cn%2F201706%2F655_1498479540118.mp4.f10_30_40.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_3.ts#EXTINF:9.68,http://127.0.0.1:3888/http%3A%2F%2Fvideoconverter.vivo.com.cn%2F201706%2F655_1498479540118.mp4.f10_40_50.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_4.ts#EXTINF:10.12,http://127.0.0.1:3888/http%3A%2F%2Fvideoconverter.vivo.com.cn%2F201706%2F655_1498479540118.mp4.f10_50_60.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_5.ts#EXTINF:3.04,http://127.0.0.1:3888/http%3A%2F%2Fvideoconverter.vivo.com.cn%2F201706%2F655_1498479540118.mp4.f10_60_63.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_6.ts#EXT-X-ENDLIST
请求一个
http://127.0.0.1:3888/http%3A%2F%2Fvideoconverter.vivo.com.cn%2F201706%2F655_1498479540118.mp4.f10_0_10.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_0.ts
这个http://127.0.0.1:3888的url会被拦截,直接解析出后续的参数:
http%3A%2F%2Fvideoconverter.vivo.com.cn%2F201706%2F655_1498479540118.mp4.f10_0_10.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_0.ts
对这个url decode 一下:
http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.f10_0_10.ts&jeffmony&/3bfd0b2eec722da9ed67509a9388dbe2/seg_0.ts
http://videoconverter.vivo.com.cn/201706/655_1498479540118.mp4.f10_0_10.ts
/3bfd0b2eec722da9ed67509a9388dbe2/seg_0.ts
PD1710:/sdcard/Android/data/com.android.media/cache/.local/3bfd0b2eec722da9ed67509a9388dbe2 $ lsproxy.m3u8 remote.m3u8 seg_0.ts seg_1.ts seg_2.ts seg_3.ts seg_4.ts seg_5.ts seg_6.ts video.info
4.3 非分片视频分段如何处理
视频播放不是孤立的行为,用户有可能会拖动进度条的,拖动进度条,如何拖动到当前没有下载到的位置,那就必须要从拖动到位置向后重新下载,这个分段缓存片段的管理也是比较重要的;
用户随意拖动进度条,可能会产生若干个分段的缓存块,这些缓存块是不连续的,但是一旦用户拖动进度条到之前的某个位置,下载资源的时候会将各个分段的缓存块连起来,连接起来之后就是一个完整的视频;
不过维护缓存块的逻辑是比较重要的,这儿主要讲解一下思想,具体看下项目代码吧,是按照上面阐述的思想来的。
4.4 边下边播架构图