一、直播场景和技术分析
好吧,既然你们非要搞什么直播,我就开始写写直播吧,怪不得WebRTC是下一代关键技术,直播的一些业务页必须要用WebRTC来实现
1. 电商直播系统源码场景分析
秀场直播
这个不用说,在各个直播平台都存在的形式
游戏直播
像斗鱼、虎牙、战旗等直播平台都是比较典型的游戏直播平台,游戏直播对码率要求比较高,观看人数也多,所以它也是流量贡献最大的直播形式。
移动直播
移动直播是最近一两年比较火的直播形式,比较明显的特点就是推流和播放比较容易, 通过手机APP就可以进行直播,所以手机直播一般也是推流数最多的直播形式。
活动赛事直播
这类直播一般对交互要求不高,所以一般都是HLS播放形式,延迟相对其他都会多一些。
答题直播
新型直播形式,每场直播的时间不长,突发流量比较高。
2.电商直播系统源码 常见传输形式
HTTP-FLV 延时3~5s
RTMP 延时3~5s
HLS 延时10s+
3. 对于低延时的直播需求
3~5秒延时对于多数常见的直播形式一般问题不大, 基本上满足之前遇到的直播形式,但在某些场景下,直播的体验非常差,例如我们最常见的连麦,如果延时超过了1s,基本上整段垮掉
对于这种场景,现在一般的直播平台采取的方案一般是借助第三方的连麦服务,然后再推给CDN厂商来加速视频传输的速度
在答题直播场景下, 一般都要求在一段时间内用户提交答案,如果有各别用户延迟比较大,这样对用户是不公平的。虽然直播平台仍然使用FLV的传输形式完成答题直播,但是基本都会采用SEI插帧等方法来解决时间同步问题, 需要平台的端和直播CDN做一些配合来完成。
除了连麦、答题场景之外,像在线课堂、在线拍卖等场景因为涉及到实时性的互动,对延时的要求也比较高。
从对业务的支持层面来看, 仅仅有RTMP、FLV这种3~5秒延时以上的直播形式已经不够了, 需要对更低延迟的直播业务进行支持。从技术的角度来看,国内常用的FLV、RTMP这种直播手段,本身是Adobe自己的标准, 而且很快会停止对Flash的维护, 另一方面WebRTC技术的兴起,Chrome、Safari等浏览器也都进行了支持,因此也需要对新的技术有一些调研和准备。
4. 短延时直播VS实时音视频通信
使用WebRTC主要用于解决实时音视频通话的需求,必然对延迟要求非常严格, 一个会议室中参与的多方可以进行视频通话, 每个参与者可以看到其他参与者,也能听到其他参与者说话。每个参与者既有推流,又有播放,数据是双向的。所以参与人数不会太多,一般不能超过20个。
短延时直播仍然是直播业务类型, 只是延时比较低, 短延时直播的业务模型相对简单, 数据单向传输,一个主播推流,参与的播放者人数没有限制,上百万都可以。
5. 关于技术选型
关于技术的选型,我们需要兼顾各种各样的场景
关于之前的业务的兼容
CDN实现直播的秒开,WebRTC在移动端拥塞控制和重传方面有一些处理,所以我们需要使用WebRTC解决卡顿的问题
关于WebRTC,这个技术有点复杂,采用一部分功能
6. 为什么不选择TCP
已有的业务,无论是图片、大小文件、点播、直播,这些都是在TCP通信基础上实现的,所以短延时直播在开展的时候我们就思考了TCP的可能性。
我们对于短延时的目标定义为从端到端800毫秒以内,一场直播的延迟来自于推流端延迟、CDN产生的延迟、播放端延迟这三个方面,
从经验角度来看,播放端的延迟会比较严重,主要是两方面,一方面是开播时候卡前一个关键帧所带来的延迟,另一方面如果CDN服务器到播放端有抖动,累积的延迟会越来越多。
我们来看一下TCP,当网络抖动出现丢包的时候,TCP是ACK确认机制的,也就是发送方发送一包之后,一定要等过对方回应,才会继续发。如果说网络一旦出现丢包,就会在一个RTO之后重传,RTO的值和RTT有关,并且RTO的最小值是200ms。如果想保证流畅性,你的播放端一定要至少能容忍200ms以上的抖动,但播放端的jitbuffer太多又无法满足低延时的要求。
电商直播系统源码里对一下比WebRTC中RTP传输使用的NACK机制,NACK的丢包反馈更加及时,如果网络是偶然性抖动居多的时候, NACK机制效果更加好。这里我们也做了一个统计,全网平均RTT小于15ms,如果CDN节点覆盖足够好的情况下,延迟理论上会很低。以1.5Mbps码率的音视频流举例,每秒钟100个包,包和包之间就是10ms的间隔。如果当第二个丢包出现的时候,第三个包对方接收到了,就可以马上知道第二个包是丢掉了,就可以立刻返回一个NACK,进行重传。在这种极限情况下,重传间隔就是25ms,相比之前TCP的200ms是一个质的提升,想满足绝大部分播放延迟在800ms以内才有可能。
另外,使用TCP的话,无效传输没法避免,。TCP是采用socket buffer进行通信,数据也是从应用层先进入socket buffer再分发。对于RTMP或FLV的分发来说,假如某一帧的数据的一部分已经进入了socket缓冲区, 那么也必须将这一帧剩余的数据发送出去, 如果剩余的数据不发出去的话, 播放端会出现解析错误, 断开连接, 这个体验会很差。
二、关于电商直播系统源码直播中问题和分析
直播常见的问题包括
主播在不稳定的网络环境下如何稳定推流?
偏远地区的观众如何高清流畅观看直播?
直播卡顿时如何智能切换线路?
如何精确度量直播质量指标并实时调整?
移动设备上不同的芯片平台如何高性能编码和渲染视频?
美颜等滤镜特效处理怎么做?
如何实现播放秒开?
如何保障直播持续播放流畅不卡顿?
1. 秒开问题
对于国内大部分平台都是使用的H.264和AAC,我们在这个基础上进行秒开的优化
对于RTMP流播放时出现黑屏问题,我们一般的认识都是因为网络慢、手机性能差,那么就真的是这样的吗,下面我们一起来看看视频播放的时候发生了什么。
第一点:视频是如何播放的
对于H.264编码来说,我们会有三个不同的帧,所谓帧是什么呢?就是你看到的每一个图像。
我们看到动态的视频,大家知道电影最开始用胶片拍的时候,每秒是25帧,是每秒25个图片在切换。
对于H.264来讲,我们常见的有I帧,P帧,和B帧。
I帧
I-Frame也有人会叫Inter Frame,那么它的意义是什么?
它是一个自描述帧,你可以理解为它就类似一个jpg图片,它里头所有的数据,你解出来之后,它就是一整张图片。
无其他帧引用,它不需要去做前置和后置的引用。
它压缩比是最小的,因为它要包括整个图片所有的数据在里头。
P帧
P-Frame也就是说预测帧,它的预测帧是怎么回事呢?P帧就是保留变的部分,不变的部分你去上一个或者几个帧里面找就行。
P帧的好处是什么呢?因为它只存一些变化信息,所以它大概的压缩比是I帧的50%。
B帧
B-Frame,前后双向引用预测。
B帧比较特别,它要引用前面P帧某一部分的图像数据同时B帧后面的数据也会引用,这个是B帧的特点,它要引用前面的数据,也要引用后面的数据。那么它的优势就是压缩比比P帧还大,大概是I帧的25%,也就是我们B帧用的特别多的话,它会把视频的大小降的比较低,因为它的压缩比更大一些。
I帧,B帧,P帧它是怎么组成一个视频流呢?我们管这个东西叫Group Of Picture,简称叫GoP。
视频解码器,看到GoP它是怎么放呢?那很简单,编码器会有一个缓冲,然后它会保留从I帧开始,当然现在说是I帧,其实这个I帧还有个特殊的类型。从I帧开始,他会把数据缓存到解码器的Buffer里,当他遇到下一个P帧,或者再下一个B帧的时候,它会从它Buffer里找到它之前引用的那个帧,然后把这个数据解出来,最终播放到显示器上。
IDR帧
IDR帧是I帧,但I帧并不一定是IDR帧,所谓IDR帧是什么?它就是拿到这个帧之后,播放器可以直接从这个帧开始往后播放,它保证后面的P帧和B帧的引用不会跨越这个IDR帧,那么看到IDR帧,编码器就可以把当前的Buffer清空,从当前这IDR帧开始解码往Buffer里边放,后续帧就可以从Buffer里的数据引用,然后解码,也就是说编码器可以从任何一个IDR帧开始解码。大家可以联想到,当我播放一个视频文件的时候,我可以拖动,但是我拖动的任何一个点,它肯定是一个IDR帧,当然它也是I帧,但是并不一定说每一个I帧我都能让它作为一个拖动的点。
IDR帧有时也有它不太学术的叫法:关键帧。
IDR 图像之后的图像永远不会使用 IDR 之前的图像的数据来解码。
我们可能会看到FFmpeg的数据结构里会标着PTS和DTS,那么PTS和DTS是什么呢?
PTS和DTS是什么?
PTS,Presentation Time Stamp也就说这个帧什么时候会放在显示器上;
DTS就是Decode Time Stamp,就是说这个帧什么时候被放在编码器去解。
那么如果全是I帧和P帧,PTS和DTS都是单调递增的,那么如果我们有B帧,会出现什么情况?因为大家都知道,对于B帧来讲,它会引用前面的帧和后面的帧。
为什么直播会等待
对于电商直播系统源码来讲,它是一个流,它不像点播,大家都从0秒开始,任何一个视频文件,0秒第一个帧肯定都是关键帧。那么对于直播来讲,我是一个随机的时间点接到这个视频流进行播放,那么我接入的这个时间点的帧有可能拿到的第一个帧的数据是I帧,也有可能是B帧,也有可能是P帧。这是一个随机的。在这种情况下,我们大概率会出现一个黑屏的状态。因为我拿到的是个P帧,对于P帧来讲,解码器面那个Buffer是空的,它不知道这个P帧如何进行解码,所以它只能丢弃这个帧。
对于直播来讲,我一秒钟的帧数是固定的,只能等到我下一个关键帧到来的时候,我才能开始去播放。当然正好赶巧了的话,接入那瞬间得到的数据正好是个I帧。就可以达到秒开的效果。
关键帧缓冲如何工作
其实是在cache服务器上,它会去预先解一下这个帧,然后去看它到底是个I帧,还是个B帧,还是个P帧,当它发现是I帧的时候,它会放在它的程序的内存里头,当你每一次打开这个视频流的时候,cache服务器会把内存中的I帧发送给客户端比如当前播放到了P帧,那我把P帧前面的I帧和P帧全波放到cache的内存里,然后当客户端接入之后先把内存里的数据发送给客户端解码器,然后再从这个B帧往后给。对于这个解码器来讲,它很舒服,它接到第一个数据流的第一个包肯定是I帧,那么它就可以直接播放了。
2. 平滑发送机制
我们可采用混合拥塞算法,基于丢包率和基于延迟进行码率控制。标准的做法是,当播放卡顿时,会让发送端降码率。WebRTC已经帮我们做了这一部分的工作
3. 播放端的优化
一阶段是开播阶段,获得GOP数据的时候,如果端不做处理的话,一定会有一个延迟。所以在这个阶段,播放端一定进行快进的操作,缩短延迟。第二阶段是当网络出现抖动的时候,会慢慢放大buffer的长度,来一定程度上适应抖动,提高流畅度。第三阶段,当网络恢复的时候,我们可以适当快进,减小buffer,把进度赶回来。也就是说这个buffer大小是动态变化的。
4. FEC冗余传输
FEC是靠冗余传输,来提高容错率。关键帧10%冗余率, 非关键帧5%,根据丢包判断出网络状况,动态调整冗余度。
5. 探活策略
除了对于正常关闭进行主动通知之外, 还需要对超时情况进行处理。即便是TCP传输的时候也有类似的问题,推流端发送了FIN结束报文,但是服务器未必收到,所以一定要有超时的机制来进行管理。我们采用数据及时反馈的机制,在下行播放端要求周期性的返回心跳,上行要求推流端在8或10秒内一定要有一些真实数据传输,否则我们就会断开。
本文转载自网络,感谢(ddssingsong)的分享,转载仅为分享干货知识,如有侵权欢迎联系云豹科技进行删除处理