视频云直播中的关键帧技术探秘
现在视频直播技术很火,ArchSummit微信大讲堂有幸邀请到迅达云SpeedyCloud工程副总裁李雨来,分享下其团队在云平台上做视频直播业务其中的一个技术方面——关键帧,本文整理自微信ArchSummit交流体验群里的分享内容(文章底部有加群方式哟!)希望能够对大家有所帮助。
一.关键帧的痛点
在视频领域,电影、电视、数字视频等可视为随时间连续变换的许多张画面,而帧则指这些画面当中的每一张。如果把这些帧转换成图片文件,并原封不动的根据一个指定的格式连续摆放的话,就得到了一个视频文件。当然,这个文件有点类似电影的胶片。
不过如果按照如此的方式存储视频的话,文件势必会变得很大,而且其间有很多重复的数据。所以需要专门的算法对视频文件进行编码。对于视频的编码格式来讲,常见的就是H264。
一旦视频进行编码之后,得到的文件可以看做是连续的一组帧的集合,而这一组帧中的每一个都是有自己的类型的。帧的类型分为以下3种:
* Inter Frame(I帧)
* P-Frame(P帧)
* B-Frame(B帧)
其中只有I帧中的数据是可以自描述的,也就是说当我们获得I帧的数据之后,就可以直接解码出当前帧的图像,对于B帧和P帧来说需要找到对应的一个或者多个参考帧才能解码出来,见图一所示;
![](https://images2018.cnblogs.com/blog/1454125/201808/1454125-20180807173547147-1346848755.png)
图一
因此对于非I帧来说想要进行解码就需要多个参考帧进行计算,并得出最终的结果。由此引出了Group of Picture的概念。
对于P帧和B帧来说,他们所包含的内容可以理解为针对其参考帧的一个patch,也就是一个变化量,所以他们不用包含整个图像的信息,只要描述好与参考帧之间的变化关系即可。所以在字节大小方面,P帧和B帧要远远小于I帧的。这也是视频压缩能节省空间的一个原因所在。
二.GoP性能调优分析
Group of Picture(以下简称GoP)顾名思义就是有一组帧组成的一个序列。Wikipedia上给出的一个图简单的解释了GoP是怎么回事(见图二):
![](https://images2018.cnblogs.com/blog/1454125/201808/1454125-20180807173613232-1817578735.png)
图二
GoP由I帧开始,后面跟随者一组B帧和P帧,直到下一个I帧之前的帧为一个GoP。了解了GoP之后,就会发现播放器只有在拿到某个GoP中的I帧之后才能播放视频。对于GoP来说,编码器都是可以进行设置的,像OBS,ffmpeg等程序可以通过对应的设置和参数对视频的GoP进行设置。
那么引出了一个问题:GoP到底应该设置多大?那么GoP的大小到底有什么影响呢?
GoP设置比较大时:
好处:由于B帧和P帧的字节大小会比I帧小很多,所以GoP越长,所包含的B帧和P帧越多,相应的压缩比也会更高,或者说同样的码率下,视频会更清晰一些。
坏处:对于视频直播来说,播放器连接到服务器的时间是不固定的,当播放器在GoP中间连接服务器,并获取了中间的B帧和P帧,这时播放器是无法对这些帧进行解码的,需要进行丢弃。所以会导致客户端的首屏播放时间变长(客户端需要等待一段时间才能看到图像)。
2. 如果 GoP设置比较小时:
好处:由于GoP设置小可以降低I帧间隔时间,对于直播来说可以实现秒开的功能。
坏处:由于GoP时间比较短,会导致I帧的比例增高,压缩比降低。同样码率情况下视频的质量会有所下降。
三 .为什么我的HLS视频加载会慢?
HLS (HTTP Live Streaming),Apple的动态码率自适应技术。主要用于PC和Apple终端的音视频服务。HLS格式的视频分为两个部分的。首先,HLS会根据指定的切片时间和实际的GoP大小对视频进行切割,并生成.ts文件。其次,HLS会生成一个.m3u8文件来保存这些ts文件的索引。
HLS协议可以用来做点播,也可以用来做直播。HLS直播是对直播流实时进行格式转换,并切片出.ts文件,同时更新.m3u8文件。客户端通过间歇获取新的.m3u8文件来获取新的.ts文件的索引。HLS点播是通过预先转码好的视频进行切片,并生成一个完整的.m3u8文件,客户端通过获取.m3u8文件来得到视频的时长和各个.ts切片文件的索引。
对于HLS格式的直播来说,.m3u8文件会在生成完一个.ts文件之后才生成。所以对于HLS直播来说,刚开始推流时,到第一个.ts文件生成完毕之前是无法打开的。同理,HLS的延迟也是跟.ts文件切片时间相关的。也就是说HLS的ts文件切片时间为1秒的话,HLS直播的延迟最小为1秒。
当然对于播放端来讲,下载.m3u8文件,然后下载第一个.ts文件也是需要花费一点时间的,那么这个时间也会加在延迟中。
对于.ts文件的切割来讲,并不是告诉直播服务器指定1秒切一个.ts文件他就能保证1秒切一个.ts文件的。.ts文件的切割还是要根据直播视频的实际GoP大小来进行切割的。之前已经讲过,任何一个视频流在播放端需要能获取到完整的GoP才能播放,所以一个.ts文件所实际包含的时间是GoP的整数倍。
例如:当视频的GoP设置为1秒,.ts切片时间为2秒时,实际的.ts文件切片所包含的视频为2秒。当视频的GoP设置为5秒,.ts切片时间为2妙时,实际的.ts文件切片所包含的视频为5秒。
从上面两个例子不难发现,视频流的实际GoP对HLS切片的时间影响非常大。如果视频流的GoP大小设置不合适的话,那么HLS的切片时间就会变长,同时也会增加HLS的延迟。这个特性对于HLS直播来讲简直就是延迟杀手。如果推流上来的GoP为10秒的话,不要说切出来一个.ts文件就要10秒,同时下载一个.ts文件所花费的时间也会大大增加。
另外如果是HLS点播的话,流的GoP设置过大也会影响点播视频的(首屏)加载时间。一般的一个720P的视频,如果切片时间为2秒的话,单个.ts文件也就是在百K字节上下。对于现有的网速来讲,下载这么一个.ts文件很快。但如果源视频的GoP很大,会导致第一个.ts文件所包含的视频时常变长(比如10秒),同时导致.ts文件的大小膨胀到接近1M字节上下。想想看,如果第一个.ts文件是1M字节的话,播放器下载这个.ts文件的时间会是多久。
四.为什么我的RTMP直播首屏渲染速度很慢?
RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写。该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMPT/RTMPS/RTMPE等多种变种。RTMP是一种设计用来进行实时数据通信的网络协议,主要用来在Flash/AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信。
对于RTMP协议的直播视频来说,它并不像HLS协议需要切.ts文件,它只是把视频流实时地进行转发即可。RTMP协议本身也会抽象出一个Packet的概念来封装H264编码中的帧,也就是一个Packet会包含1到多个帧,播放器以Packet为单位来进行解码。那么RTMP的问题在于客户端连接的时间点是否合适。
例如一个RTMP直播流的GoP设置为2秒,如果客户端接入时间刚好是第4秒,那么客户端会获取一个包含I帧的Packet,由于I帧是自描述的,所以客户端可以直接解码出该帧的画面并显示出来。但是当客户端的接入之间为第5秒,那么他会获得一个包含B帧或者P帧的Packet,由于客户端拿到的数据是一个不完整的GoP,所以客户端只好抛弃当前获取的Packet中视频的数据,而且只有当获取到包含下一个GoP的I帧的Packet时才能解码出图像。因此客户端会等待1秒才能播放出画面。
由此我们可以得出一个结论:GoP的大小会影响RTMP播放端的首帧加载时间。也就是说首帧加载时间最久为一个GoP的时间。当然,如何客户端运气够好的话,可以瞬间播放。
为了优化首帧加载时间,我们可以在流媒体服务器端增加一个缓存,把上一个GoP缓存在内存中。如果客户端接入的话,我们首先放出来的是上一个GoP。这样客户端接到的数据永远是一I帧开头的数据。
不过这种方案对于延迟要求比较高的场景下就不适合。毕竟GoP的缓存会增加一个延迟,具体延迟的时间也是跟GoP大小相关的。如果要实时性,那么GoP缓存并不能很好的解决问题,只能通过减少关键帧间隔的方式来进行调优了。
五.结论
在视频直播和点播盛行的年代,对于GoP大小的取舍还是需要看具体应用场景。对于直播来讲,对延迟要求敏感的应用来说,1~2秒的GoP大小还是比较合适的,至于GoP缓存来讲,还是不用为好。如果是对延迟要求不敏感,对首屏播放时间很敏感的应用,GoP还是1~2秒最为合适,GoP缓存应该是必备的。另外直播使用HLS的话,延迟是绝对PK不过RTMP的。
对于点播的应用来说,视频加载速度是个硬指标,如果不是HLS格式的话,GoP大小适当选大一点可以降低视频文件大小,提高视频打开速度。HLS格式的话,还是推荐在2秒左右,否则很影响视频打开速度的。
其实视频直播技术的挑战很多,这次分享的只是其中一小部分,也是迅达云SpeedyCloud研发团队的经验总结,希望能够和大家多交流,一起为技术社区发展做些有益的事情。
六.Q&A
问题1:求推荐视频直播的知识资源,关于rmtp、h264编码的更多知识。大量视频文件存储服务器技术方案有哪些?
这方面的内容,可以通过翻阅wikipedia,Google来获取想要的知识。另外看一些开源项目的文档也会有所帮助。比如Nginx-RTMP-Module,Simple-rtmp-server,ffmpeg
问题2:视频直播这块有没有开源项目可以来练手的?
上面说到了Nginx-rtmp,SRS,FFMPEG
问题3:nginx 的rtmp模块,可以配置gop缓存时间吗?
nginx-rtmp是没有GoP Cache的。Simple-RTMP-Server是有的。
问题4:求现在创业公司如何快速搭建自己的直播平台,是自研还是使用第三方平台,有哪些第三方平台可以推荐?
搭建直播平台的话,涉及的东西会很多,一般都是自研一部分,外包一部分。
问题5:老师说到B侦和P侦需要参考侦才能解码,但在GoP的那张图中没有看到参考侦呀?
最前面和最后的两个橘黄色的是I帧。另外参考不一定是I帧,前后的B帧和P帧都可以做参考
问题6:ffmepg里,哪个选项是配置x264的 gop的?
-g参数可以设置gop长度,单位是帧。
问题7:就rtmpserver来说,哪些server使用者更多些?
这个看应用场景了,如果是自己用,Nginx-rtmp比较容易一些,如果是做CDN的话,simple-rtmp-server是个比较好的选择。