当你用手机或者电脑追剧的时候,有没有想过你眼前的视频是如何从服务器到你的手机上的呢?
其实随着网络技术的发展,在人们的日常生活中,互联网已经无处不在.
不管你是用手机,还是电脑,不管你浏览网页,还是使用APP
; 一个按钮的点击,一个页面的刷新,最后都是通过网络请求到服务器,然后再从服务器返回你所需要的数据.
如果你会抓包,或者在浏览器里按F12
打开控制台,就能发现信息交互的蛛丝马迹.
现在已经进入了信息化时代,每个人都应该对互联网有个基本的了解.
言归正传, 当你打开APP
或者网页,找到要追的剧,点击播放,而这些视频则是通过流的方式一点点从服务器传到你的屏幕上.
在我的记忆里,刚开始的时候,网上的视频还是flv
格式. 这种格式文件小,加载速度快,延时低.
FLV (Flash Video)
是 Adobe
公司推出的一种视频格式,是一种在网络上传输的流媒体数据存储容器格式.支持的协议有RTMP
和HTTP-FLV
.这两个协议也都是Adobe
公司推出的.
RTMP
基于 TCP
传输,可能会被防火墙拦截.
HTTP-FLV
是基于HTTP
,虽然可以避免被防火墙拦截,但是数据会在本地缓存,保密性不好.
下面就是现在最流行的一种协议了: HLS
HLS (HTTP Live Streaming)
是苹果公司基于 HTTP
的流媒体传输协议.主要应用于 iOS
设备
相对于常见的流媒体协议,
HLS
最大的不同在于它并不是一下请求完整的数据流。它会在服务器端将流媒体数据切割成连续的时长较短的ts
小文件,并通过M3U8
索引文件按序访问ts
文件。客户端只要不停的按序播放从服务器获取到的文件,从而实现播放音视频。
HLS
基于HTTP
,也不会被防火墙拦截,性能高,自带多码率适应,支持在播放过程中,可以自由选择调整码率,缺点就是延时高,小文件多.
当我们看剧的时候,想把这个下载下来怎么办呢?打开浏览器的控制台,可以发现浏览器请求了一个m3u8
地址,如下图:
这个地址就是视频资源的索引地址,而返回的ts
文件,就是被切割的很小的一个个视频文件.
如果我们可以把这些ts
文件都下载下来,然后合并,转码成mp4
,那么我们就得到了完整的视频文件.
请求m3u8
地址,得到的m3u8
文件格式如下:
没有加密:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4.166667,
5b1adcbb728000000.ts
#EXTINF:4.958333,
5b1adcbb728000001.ts
#EXTINF:2.958333,
5b1adcbb728000002.ts
......
#EXTINF:2.125000,
5b1adcbb728000204.ts
#EXT-X-ENDLIST
有加密:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="/20220415/hq0ifQwb/1000kb/hls/key.key"
#EXTINF:0.189,
/20220415/hq0ifQwb/1000kb/hls/pB625ruF.ts
#EXTINF:0.5,
/20220415/hq0ifQwb/1000kb/hls/SH2VgoEz.ts
#EXTINF:1.25,
/20220415/hq0ifQwb/1000kb/hls/Dv4M2bdG.ts
......
/20220415/hq0ifQwb/1000kb/hls/q7lZX33G.ts
#EXTINF:1,
/20220415/hq0ifQwb/1000kb/hls/9EOUyDBJ.ts
#EXT-X-ENDLIST
#EXTM3U
是文件头#EXT-X-VERSION:3
是版本#EXT-X-TARGETDURATION:2
每个分片 TS 的最大的时长#EXT-X-MEDIA-SEQUENCE:0
第一个 TS 分片的序列号#EXT-X-KEY:METHOD=AES-128,URI="/20220415/hq0ifQwb/1000kb/hls/key.key"
加密方式,秘钥地址,也要和m3u8
的地址拼起来.有的还可能有偏移量 IV
#EXTINF:0.189,
下面片段的时长/20220415/hq0ifQwb/1000kb/hls/pB625ruF.ts
ts
文件地址,要和m3u8
的网址拼到一起.比如: https://cdn1.hdzyk-video.com/20220415/hq0ifQwb/1000kb/hls/pB625ruF.ts
#EXT-X-ENDLIST
文件结束符说一下核心的代码吧,粘太多代码也不好看.
这里请求m3u8
的url
,得到index.m3u8
文件,然后解析文件.有时候可能会出现文件里还有m3u8
链接嵌套的情况,这种情况可以使用递归的方式来进行解析,因为这种情况比较少,所以没有使用递归.
解析得到ts
文件的url
,播放时长,还有序号.
播放时长是用来计算整个视频的长度的,序号是为了最后拼接的时候,文件顺序不会乱.
如果被加密,获取加密key
,加密方法,偏移向量等解密需要的信息.
使用并行的方式下载所有的ts
文件.
试过使用线程池还有Fork-Join
,这种并行的方式底层就是使用的Fork-Join
.两种下载速度差不多.
这里并发数设置为4,如果设置太大,怕服务器扛不住.还是善良一点吧.由于是并行下载,所以下载顺序是乱序的,所以最后合并的时候序号还是很重要的.
接下来就是解密了,因为不是所有的m3u8
都加密了,所以这里要先判断一下是否需要解密,不需要直接返回即可.
因为ts
片段可以无缝拼接,所以合并比较简单,使用文件流的方式写到一起就可以了.
想要用Java
转换视频格式,那就少不了这个工具: FFmpeg
FFmpeg
是一款开源软件,提供了强大的音视频编解码工具.也是音视频编解码开发套件,为开发者提供了丰富的音视频的调用接口。
FFmpeg
提供了多种媒体格式的封装和解封装,包括多种音视频编码、多种协议的流媒体、多种色彩格式转换、多种采样率转换、多种码率转换等;FFmpeg
框架提供了多种丰富的插件模块,包含封装与解封装的插件、编码与解码的插件等。
使用 FFmpeg
作为内核视频播放器:
Mplayer
,ffplay
,射手播放器,暴风影音,KMPlayer
,QQ影音...使用 FFmpeg
作为内核的 Directshow Filter
:
ffdshow
,lav filters
...使用 FFmpeg
作为内核的转码工具:
ffmpeg
,格式工厂...Mac
可以使用HomeBrew
安装:
brew install ffmpeg
到这里就完成了.
全部下载完之后,调用这个方法,就可以把ts
格式的转为mp4
.
刚开始的时候,我想过用多线程的方式,把ts
片段转为mp4
后,再进行合并,这样可以省去最后转换的时间.
后来发现,如果都转为mp4
之后,就不能使用文件流读取,然后写到一个文件的方式来进行合并了.
因为每个mp4
文件有自己的文件头,不能这样合并.
FFmpeg
的用法很多,功能很强大,感兴趣的可以看一下.
ffmpeg
的官网地址是: https://www.ffmpeg.org/
ffmpeg
的Github
项目地址是: https://github.com/FFmpeg/FFmpeg
FFmpeg
视频文件转换命令行工具,也支持经过实时电视卡抓取和编码成视频文件;
ffserver
基于HTTP
、RTSP
用于实时广播的多媒体服务器.也支持时间平移;
ffplay
用 SDL
和FFmpeg
库开发的一个简单的媒体播放器;
libavcodec
一个包含了所有FFmpeg
音视频编解码器的库。为了保证最优性能和高可复用性,大多数编解码器从头开发的;
libavformat
一个包含了所有的普通音视格式的解析器和产生器的库
好啦,就这样吧, 如需合作,请私信。
最后欢迎大家关注我的公众号,共同学习,一起进步。加油🤣