Photo by Wendy Wei from Pexels
随着直播行业的迭代更新,传统直播方案的延迟问题越发凸显。本文来自融云联合创始人、首席架构师 李淼在LiveVideoStackCon 2019深圳站中的演讲,在其中他详细介绍了如何利用WebRTC低延迟音视频传输的特点,解决传统直播方案的延迟问题。
文 / 李淼
整理 / LiveVideoStack
融云是一家全球互联网通信云平台,主要提供即时通讯、实时音视频相关业务,今天主要向大家介绍一下我们基于WebRTC的直播解决方案。
主要内容分为以下四个部分:
1. WebRTC直播的优势
为什么要选择WebRTC做直播呢?
WebRTC自身最大的优势:低延时、流量更少、性能好。
WebRTC做直播第二大优势:主播端与观众端的方案一致。
直播会涉及推流方面的问题,例如使用OBS推流或者WebRTC推流,而观众端为了适应推流平台,会涉及接入HLS或者RTMP的播放器,如果选用WebRTC就可以达成主播端和观众端方案的一致性。对于开发来讲,编码量会更少一些,因此对于后期整体的代码维护,甚至团队的人员构成都可以保证资源消耗最低。
WebRTC做直播的劣势是标准的直播解决方案少,即我们选择WebRTC开源服务会涉及到的lincode、mediasoup大部分都在解决p2p通讯或者多人音视频通讯,但是对于直播方案来讲,很少能提供相应的解决方案。
首先了解p2p通讯或者多人音视频通讯与直播通讯的差异是什么:
2. WebRTC直播的过程
WebRTC支持低延时直播,那么如何通过WebRTC来完成直播场景的构建呢?
使用WebRTC首先会涉及信令相关的交互逻辑,观众端不需要接入信令,如图便是普通直播场景完整流程的时序图。主播客户端利用业务服务器申请开通直播间,提交房间号,生成一个URL,将URL保存到业务服务器(另外一种方式是URL由业务服务器生成),当URL生成后,主播端即可向URL进行推流。观众端在打开APP或者一个场景时,通过点击链接即可获得URL,根据URL发起订阅,进行拉流。
WebRTC直播的流程是完全不一样的,WebRTC直播的中间过程没有信令的接入逻辑。
如图所示是WebRTC不使用信令的方式通过客户端进行订阅的简要整体流程。
首先是主播客户端向MediaServerA发起发布资源,其中涉及SDP信息交换,此接口是MediaServerA提供的HTTP的接口,该接口可以接收SDP信息,MediaServerA接收到SDP请求后转移到MCU混流服务器上,主播客户端通过用户ID的方式接入到MediaServerA,MediaServerA通过房间ID进行聚合,MCU完成合流之后向下推送到MediaServerB,即直播间的视频流,MediaServerA是以人的方式进行分散,MediaServerB通过房间的方式进行聚合,MediaServerB生成相应URL用于描述资源所在位置,再将该URL含有SDP的answer信息依次传递到主播客户端上,主播即可接收资源信息的描述,主播可以通过自身与业务服务器的交流接口将URL上传到业务服务器上,此时观众客户端可通过点击链接或者其他方式获取URL,最后完成最下方的订阅步骤。(整体流程图中省略了很多推流的逻辑)
关于MCU的注意事项
在海量直播的情况下,如果涉及到连麦的情景,为了降低流量就需要对服务进行合流处理,合流处理需要注意以下几点:
针对于观众端订阅的子流程,如上流程图拆分为上下两部分。
第一部分是No SDPCache,即客户端没有任何SDP缓存,可理解为客户端首次与服务器进行连接,第一次链接的正常流程是一个SDP的offer通过HTTP的接口向MediaServer发起订阅,交互后SDP会在客户端进行缓存,完成缓存后就进入WebRTC的标准通讯流程,后MediaServer再向客户端进行推流。
第二部分是为了应对客户端频繁切换房间进行的优化部分。优化的点是客户端不需要频繁的进行ICE以及DTLS证书交换,即如果有SDPCache情况下,可直接从客户端生成offer,通过已经缓存的Answer,将其中的ssrc信息进行替换,在客户端上setRemote SDP,在不需要与服务器进行数据交换的情况下即可完成整体的SDP交换,后续客户端向服务器发起HTTP请求订阅某一个房间的流时,MediaServer直接向下推流即可。
既然与服务器已有订阅交换的情况为什么还要使用本地缓存SDP的方式设置SDP呢?
后续客户端已经不再与MediaServer做ICE以及URL交换,当服务器收到SDP的offer时,就已经构建了整体的订阅关系,服务器向下发送Answer的同时有可能出现该Answer还没到达客户端但服务器就已经进行推流了。使用本地缓存SDP的方式设置SDP可以避免Answer不再依赖于订阅接口,因此只要设置完成SDP,服务器向下推流使得整体切换变得非常平滑。
我们的URL是通过二进制方式进行描述,再对二进制文件进行base64下发到客户端,客户端解析后整体的数据结构大体如图所示,其中包括房间ID(用于确定观众端订阅了哪个房间)、服务器ID(用于确定房间发布的第一道流所在的服务器的位置,即MediaServerB),这些都是为了后续构建直播网络确定数据所在位置,其次是关于视频流的SSRC信息的描述,将URL进行序列化后即可发送到客户端,客户端以及服务器通过数据进行反序列化获取相关数据以及信息。
在完成上述流程之后,对于直播场景还有一些基本诉求。
首先,房间号不变的情况下,一切都不能变。其中一种场景就是主播端由于网络原因断开连接,再重新与服务器进行建联就意味着要重新交换SDP,其中的资源信息可能全部会发生变化,但是对于观众端来讲,观众一直都在线等待。由此得出结论,房间号不变的情况下,所有URL信息都是不能发生变化的。因此就要对传输流包内的RTP、RTCP包加工,如图为真实主播房间的源流服务器整体的交互流程,MCU向源流服务器进行SDP交换,要从SDP中将所有SSRC相关的信息全部提取,保存对应关系,其中对应关系的生成规则就是通过房间ID+流属性进行哈希变换,即成为转换之后的SSRC信息,通过这种方式意味着房间ID不变的情况下,则其中的SSRC信息就不会发生变化。即使主播端频繁的加入、退出,或者有新的主播产生连麦请求,都可以保证所有的SSRC信息不变。
实际中我们在SSRC、RTP、RTCP包完成替换之后,向下分发,也不一定对于观众端不产生影响,还会涉及一些其他注意事项。例如,需要保证替换的RTP包的SeqNumber不能中断,如果不连续可能会造成客户端产生大量的NACK,向服务器要求重传包,会造成整体网络的拥塞。在SeqNumber处理完成后,需要处理Timestemp,即本身RTP中的时间戳,如果时间戳处理不好就有可能造成视频的卡顿现象,或出画音不同步的情况。
根据流程设计服务器与客户端交流接口:
3. WebRTC直播技术细节
3.1 WebRTC直播的技术难点
首先将WebRTC应用在生产环境下,要解决以下几个问题,
3.2 GOP缓存结构
为了解决以上问题,服务器端需要加入Gop Cache数据结构,构建基于Gop的缓存结构。
如图中间部分,是一个有序的KV存储,Key表示SeqNumber,即RTP包的序号,Val表示包的VideoRTP,每个包都会涉及到I帧或者P帧,在缓存时要对这些包进行简单的解析,区分出是I帧还是P帧,Gop缓存的起点是以SPS,包含很多视频解析参数。
上一层是对于视频包的解析处理。下一层是对音频包的缓存处理。音频包的处理不会涉及到I帧或者P帧等一些逻辑处理,对于音频包采用的是Timestamp,利用时间戳作为Key,在真实使用中视频包的Timestamp找出对应范围内的音频包下发,另外还涉及实现其他应用的指针。
如何使用Gop缓存呢?
为了考虑内存的使用效率对GOP缓存做基本的控制,有以下两个控制策略。
对于服务器端有两个策略,其一是单个Gop允许的最大包数是多少,其二是允许单个Gop的最长时长是多少。
对于最大包数的策略采用整体缓存数的45%作为产生PLI的阈值,利用5%来抹平时间差;另外通过最大时长控制策略是通过首帧来进行追包请求,希望追包的时间尽可能短,这样观众端和主播端进度尽可能一致。对于这两个策略,只要其中一个策略满足,即可产生PLI向发布端所求关键帧。
4. WebRTC直播服务架构
支撑海量用户服务端的架构是如何的?
单个数据端的服务架构由负载均衡、反向代理以及MediaServer组成,当单个MediaServer处理直播达到上限时就会通过扩充服务器的方式弥补不足。
完成单个数据中心的处理后要应用到实际生产环境中,还有很多额外的工作。
例如需要有音视频审核能力(要按照法律要求过滤掉不合格内容)、云端录像能力(当直播中出现点播的请求时,就要在推流的过程中进行转码录像)、视频标注能力等,在满足若干额外工作能力之后,至少可以完成一个数据中心的一个直播工作构建。
针对于全球或者区域中心分布的简单示意图
首先主播会选择就近联结数据中心,向数据中心产生合理请求再向本数据中心进行发布,其他数据中心向该数据中心级联请求拉流,每个数据中心只有一台服务器负责拉流,到单个数据中心进行分发,本客户端即可通过服务器将流拉取走,这样可以使主数据中心的资源消耗最低,对于单数据中心的流量和网络压力也可以降到最低。
解决链路优化,就要考虑到就近接入的问题,最常用的方式就是通过SmartDNS,通过计算客户端IP的方式给观众端反馈就近节点,但由于SmartDNS本就有导致DNS分配节点不准确的问题,因此会通过使用HTTP DNS解决相关问题。当SmartDNS和HTTP DNS都不准确的情况下,优化过程中又引入了BGP Anycast链路,BGP Anycast链路已经超越了基于IP分配的方式,因为Anycast IP对于很多客户端在全网看到的是同一个IP,但是这个IP服务器地址是可以按照运营商的方式就近进行选择。即在通过SmartDNS分配的服务器质量不够满意的情况下会转入BGP Anycast链路使之节点分配更准确。
对于物理链路的优化,由于服务器与服务器之间会涉及到很多接口调用,对于接口调用会使用很多Qos进行保障,这些接口调用一般选择跨国专线的方式,使接口调用的质量得到保证。
视频流如若通过跨国专线,成本会大大增加,因此选择二级级联的方式,使音频流和视频流通过二次转发的方式提高数据传输质量。
LiveVideoStackCon 2020
上海/北京/旧金山 讲师招募
2020年LiveVideoStackCon将持续迭代,LiveVideoStackCon将分别在上海(6月13-14日),北京(9月11-12日)和旧金山(11月)举行。欢迎将你的技术实践、踩坑与填坑经历、技术与商业创业的思考分享出来,独乐不如众乐。请将个人资料和话题信息邮件到 speaker@livevideostack.com 或点击【阅读原文】了解成为LiveVideoStackCon讲师的权益与义务,我们会在48小时内回复。
本文分享自 LiveVideoStack 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!