Mp4是目前使用很广泛的一种视频格式。
随着客户的增加,mp4文件播放的弊端也日益凸显,主要集中在两个方面当视频时长比较长的时候,mp4的关键帧元素往往很大,需要加载很长时间才能开始播放,网速不好的情况缓冲加载就要20多秒的时间,客户早已急不可耐。当用户打开一个视频播放的时候,浏览器会持续请求下载mp4文件直到下载完成,就算是用户暂停视频播放浏览器也会持续这种下载状态,如果这个视频文件是500M则会请求服务器下载500M文件,是1G则会不停下载1G,给服务器硬盘和宽带造成很大浪费和压力。而HLS这种方式就可以避免这两个问题。
HLS(HTTP Live Streaming)是苹果公司针对iPhone、iPod、iTouch和iPad等移动设备而开发的基于HTTP协议的流媒体解决方案。在 HLS 技术中 Web 服务器向客户端提供接近实时的音视频流。
但在使用的过程中是使用的标准的 HTTP 协议,所以这时,只要使用 HLS 的技术,就能在普通的 HTTP 的应用上直接提供点播和直播。
该技术基本原理是将视频文件或视频流切分成小片(ts)并建立索引文件(m3u8)。支持的视频流编码为H.264,音频流编码为AAC。
在App Store中的视频相关的应用,基本都是应用的此种技术。
HLS优点
无需专门软件,普通的网络服务器即可,大大降低了 CDN 边缘服务器的配置要求,可以使用任何现成的 CDN。分发使用的协议是最常见 HTTP,代理服务器对这个协议的缓存优化相当成熟,而很少有代理服务器对 RTSP 的进行缓存优
对于非实时视频,同样的好处也是存在的:如果你要在一段长达一小时的视频中跳转,如果使用单个 MP4 格式的视频文件,并且也是用 HTTP 协议,那么需要代理服务器支持 HTTP range request ,以获取大文件中的一部分。不是所有的代理服务器都对此有良好的支持。而 HTTP Live Streaming 则只需要根据列表文件中的时间轴找出对应的 TS 片段下载即可,不需要 range request,对代理服务器的要求小很多。所有代理服务器都支持小文件的高效缓存。
此外,HTTP Live Streaming 还有一个巨大优势:自适应码率流播(adaptive streaming)。效果就是客户端会根据网络状况自动选择不同码率的视频流,条件允许的情况下使用高码率,网络繁忙的时候使用低码率,并且自动在二者间随意切换。这对移动设备网络状况不稳定的情况下保障流畅播放非常有帮助。实现方法是服务器端提供多码率视频流,并且在列表文件中注明,播放器根据播放进度和下载速度自动调整。
根据网络带宽,客户端会选择一个适合自己码率的文件进行播放,保证视频流的流畅。
至于为什么要用 TS 而不是 MP4,这是因为两个 TS 片段可以无缝拼接,播放器能连续播放,而 MP4 文件由于编码方式的原因,两段 MP4 不能无缝拼接,播放器连续播放两个 MP4 文件会出现破音和画面间断,影响用户体验。
,与实时传输协议(RTP)不同,HLS可以穿过任何允许HTTP数据通过的防火墙或者代理服务器。它也很容易使用内容分发网络来传输媒体流
M3U8文件介绍
我们比较详细的来介绍m3u8文件
譬如:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:13
#EXT-X-MEDIA-SEQUENCE:430
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:11.800
news-430.ts
#EXTINF:10.120
news-431.ts
#EXT-X-DISCONTINUITY
#EXTINF:11.952
news-430.ts
#EXTINF:12.640
news-431.ts
#EXTINF:11.160
news-432.ts
#EXT-X-DISCONTINUITY
#EXTINF:11.751
news-430.ts
#EXTINF:2.040
news-431.ts
#EXT-X-ENDLIST
EXTM3U
首先要说明的是
m3u8 文件必须以 utf-8
m3u8 文件的每一行要么是一个 URI,要么是空行,要么就是以 # 开头的字符串。不能出现空白字符,除了显示声明的元素。
m3u8 文件中以 # 开头的字符串要么是注释,要么就是标签。标签以 #EXT 开头,大小写敏感。
第二行 EXT-X-VERSION:表示 HLS 的协议版本号,该标签与流媒体的兼容性相关。该标签为全局作用域,使能整个 m3u8 文件;每个 m3u8 文件内最多只能出现一个该标签定义。如果 m3u8 文件不包含该标签,则默认为协议的第一个版本。
第三行 #EXT-X-ALLOW-CACHE:YES
忘文生意,表示允许缓存
第四行
EXT-X-TARGETDURATION:TARGETDURATION 英文直译就是目标持续时间 表示每个视频分段最大的时长(单位秒)。该标签为必选标签。下面的ts列表中,任何一个 ts播放的时间长度都不能超过这里指定的时间长度
上面我们介绍的是HLS里面,媒体索引文件--m3u8文件的常用格式,以及标签。它的详细的标签说明,我们可以去搜索相应的文档。
第五行
#EXT-X-PLAYLIST-TYPE:VOD
▷ EXT-X-PLAYLIST-TYPE:表明流媒体类型。全局生效。该标签为可选标签。
其格式为:#EXT-X-PLAYLIST-TYPE:<type-enum>,其中,type-enum可选值如下:
☛ VOD 即 Video on Demand,表示该视屏流为点播源,因此服务器不能更改该 m3u8 文件;
☛ EVENT 表示该视频流为直播源,因此服务器不能更改或删除该文件任意部分内容(但是可以在文件末尾添加新内容)(注:VOD 文件通常带有 EXT-X-ENDLIST 标签,因为其为点播源,不会改变;而 EVEVT 文件初始化时一般不会有 EXT-X-ENDLIST 标签,暗示有新的文件会添加到播放列表末尾,因此也需要客户端定时获取该 m3u8 文件,以获取新的媒体片段资源,直到访问到 EXT-X-ENDLIST 标签才停止)。
第六行
EXTINF:表示其后 URL 指定的媒体片段时长(单位为秒)。每个 URL 媒体片段之前必须指定该标签。该标签的使用格式为:#EXTINF:<duration>,[<title>],其中,参数duration可以为十进制的整型或者浮点型,其值必须小于或等于 EXT-X-
EXT-X-ENDLIST:表明 m3u8 文件的结束。该标签可出现在 m3u8 文件任意位置,一般是结尾。
接下来,我们来了解下如何切换同一视频的不同码流
我们介绍过,m3u8的一个优点就是可以根据网络状况,切换不通清晰度的码流。那么要实现码流切换,应该怎么做呢?
首先,我们要生成同一视频的不同码率的ts文件及其索引文件,及m3u8文件。然后,再生成一个m3u8文件,来包含这几个不同
码率的m3u8文件。这个m3u8文件如下
多码率适配流,
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000
http://example.com/low.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000
http://example.com/mid.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000
http://example.com/hi.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=65000,CODECS="mp4a.40.5"
http://example.com/audio-only.m3u8
我们看,这个m3u8文件里包括关键字BANDWIDTH也就是带宽,每一行下面跟着的,就是这个带宽要读取的m3u8文件。对应的m3u8文件里,才是真正的ts文件。
服务器搭建
服务器在逻辑上其实是分两块,一是http服务器,这相对比较简单,我们在此用apache做例子。另一部分是视频的切割,就是将一个大的mp4文件切割成多个ts文件,这个需要安装安装FFMPEG,但是先要安装比较多的第三方库。。
搭建好后,使用ffmpege命令,例如ffmpeg -i /root/1.mp4 4 -c:v libx264 -c:a aac -strict -2 -f hls -hls_time 15 -hls_list_size 0 test.m3u8 就能将 \root\1.mp4 这个文件切割。并且生成m3u8文件 名字是 test.m3u8
五、客户端
我们可以利用第三方一些库,支持h5的,在html文件中指定这个m3u8文件,就可以播放了。
总体思路是比较清晰的,但是具体实施起来,还是有很多细节,一篇文章难以写完。具体的可在“CSDN学院”里面搜 "视频点播平台的开发搭建",那里有详细的实现步骤。