音视频实践日 Live|QRTC 流媒体分发演进
Posted 七牛云
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了音视频实践日 Live|QRTC 流媒体分发演进相关的知识,希望对你有一定的参考价值。
去年 7 月,七牛云 QRTC 团队升级了内部的传输协议,提升传输效率的同时,也实现了在协议层对音画质量的优化。
在「音视频实践日 Live」直播活动中,七牛云资深开发工程师于佳,为我们就「QRTC 流媒体分发演进」话题带来分享,重点介绍了 QRTC 实时媒体分发服务架构与转发协议,以及网络层 QoS/QoE 的实践经验分享。
本文内容基于于佳分享整理,为方便阅读略有删改。
大家好,我是于佳,来自七牛云开发团队,目前主要负责 RTC 媒体转发相关的开发和维护工作。接下来,我会带大家从服务端的视角分析一下,我们 QRTC 的一些特性。希望我的分享能让大家对七牛的 RTC 服务有一个更清晰完整的认识。同时,我也会带大家拆解一下 WebRTC 协议,以及该协议与其他实时流媒体协议的横向对比。
我今天的分享主要包括两个部分:第一个部分讲解 QRTC 实时媒体转发服务演进,我们从最开始的发起,到现在的几轮迭代,整个演进的过程,我们解决的问题和带来的哪些性能上的增长;第二部分,结合我平时和我们团队做的一些关于流媒体相关的工程经验,主要是围绕着流媒体 QoE 做的一些经验的分享和介绍。
QRTC 媒体分发演进阶段
我们整个 RTC 的服务大概分成了三个阶段,最早从 libwebrtc 刚刚开源的时候,我们就已经开始关注 WebRTC 相关的一些社区的动态。我们也是在第一时间孵化出了面向 WebRTC 协议的转发的服务。最开始的时候,我们去做 WebRTC 媒体转发是单点转发的模式,这个大家可能在很多开源的社区都能看到,很多开源的 SFU 都是实现了一个单点转发。不同语言实现的开源项目,比如说 Golang 实现的 Pion,Rust 实现的 webrtc-rs,都是完成 WebRTC 协议栈之后再去实现一个简单的 SFU。我们在很早以前就实现了 WebRTC 单点转发的能力。
第二阶段是静态分发,去做一个分发的概念,也就是全球加速网络下分发。
第三个阶段结合我们大量的数据,与 QoE 相关的调试经验去实现一个自动化动态分发。在这之前,我带大家通俗讲一下 WebRTC 协议,因为 WebRTC 协议栈实际上比较高,不像其他协议一句话就可以讲得清楚。比如说 RTMP 这个协议,它就是在媒体的数据封装一个 FLV 的头部,在拆分成适合网络传输的 chunk,然后把这个数据放在可靠传输的 TCP 协议上,一句话就可以把 RTMP 这个协议讲清楚。
再比如说我们视频点播用的 HLS 协议,它把媒体数据加一个头部,封装成 PES,然后在打包成固定长度的 TS,然后放在 HTTP 协议上分发。但是 WebRTC 协议为了达到实时性的目的,就不得以不能在可靠的传输协议上传输,只能基于 UDP 去传输。但是 UDP 的协议传输就有很多弱点,比如拥塞、丢包、乱序、抖动,这些都是 WebRTC 里面必须要解决的问题,如果不解决的话,或者不用一些手段去处理的话,是没有办法满足实际使用需求的。所以 WebRTC 增加了很多机制,同时也增加了学习的难度,整个学习曲线稍微陡峭一点点。
但是我们如果把本质上抓住之后,你可以看一下它每个机制背后想做的是什么,或者说想解决什么问题,就容易能把这个协议理解透彻。
WebRTC 信令通道建立连接过程
我们大概来看一下,整个协议的建立,它连接建立时的信息交互是基于 SDP 的,这和传统的协议是兼容的。包括很多 VOIP 的硬件厂商都是能支持 WebRTC 协议,为什么?就是因为 WebRTC 协议的内容,虽然说信令没有具体定义,但是它协议里面的内容都是能够与传统设备做一个很好兼容的。
具体的 WebRTC 连接建立协议是由 JSEP(javascript Session Establishment Protocol)来定义的。大家可以看一下对应的 RFC 文档,所有的 WebRTC 相关的协议都能在 RFC 中找到,不像是受很强的专利保护的东西,你不好去分析和研究它,WebRTC 是一个开放的协议栈。
JSEP 大概的流程,就是围绕着 Offer/Answer 的机制,在浏览器里面,发起一方 create offer,然后 set local description,远端收到 offer 之后,set remote description,再 create answer 并 set local description,最后将 answer 返回给发起方,发起方收到 answer 后 set remote description, 整个 P2P 的连接在信令层就基本完成了。JSEP 这一层协议里面,整个系列的交互上是非常简单明了的,也是很传统的机制。如果之前理解过这个流程,或者说有过调试经验,再看 WebRTC 连接建立就非常简单。同时交互的内容是完全拓展 SDP 去实现的。虽然 SDP 里面的坑很多,很多历史的问题要去兼容,但是这也是它成功的地方,它可以去完美的兼容历史的硬件设备。
WebRTC 媒体通道建立连接过程
媒体建立在 UDP 上,首先要解决连接发现和连接初始化的问题,WebRTC 引入了传统的 STUN/TURN/ICE 协议族,解决了 P2P 连接建立的问题。
连接的安全性,通过这个 DTLS 交换密钥,交换密钥之后,通过 SRTP 加密。上图就清晰的描述了整个媒体通道在连接过程中的过程。大家看一下,应该是最好的情况需要三个 RTT 才能建连。
RTC 媒体转发服务的核心概念
RTC 媒体转发服务的本质,就是转发 RTP Stream。
在 RTP Stream 里面,WebRTC 做了很多拓展,它这个拓展其实都是为了实现实时性。在保证实时性的情况下,再去兼顾它整体的传输质量。来大概过一遍整个协议的能力集,我们第一阶段在服务端去实现 WebRTC 协议转发的时候,主要就是围绕这个能力集,我们也在 WebRTC 协议能力集做了很多技术积累。因为整个原生 WebRTC 协议是面向 P2P 的,对于转发并没有很强的定义,所以对媒体转发服务的实现带来了一些挑战。
基于 WebRTC 协议的基础能力集
首先 WebRTC 把 RTCP 和 RTP 做了一个连接的绑定,在一个端口里面传输,节省了连接资源。然后 NACK 的机制做丢包重传,这个肯定是必须的。比如说视频传输的时候,RTC 里面丢了一个包的话,肯定还是重传一下比较好一些,如果不这样的话,后面的包都没有意义了,所以 NACK 还是需要的。
WebRTC 里面的拥塞控制通过带宽估计然后反向控制编码的质量去实现。然后就是关键帧的请求,关键帧的请求也是一个非常重要的能力,有些丢包无法恢复的时候要重新请求关键帧才能去继续渲染。还有就是新用户的加入必须要有关键帧。
WebRTC 提高通话质量的常用方法是增加冗余,RED、FEC 是比较常见的机制。相对于订阅端,Simulcast 也算是另一种形式的发送端冗余。
QRTC 媒体转发服务能力集
上面讲的能力集是我们在服务端转发的时候都是完全能够支持的。当然去兼容这个 WebRTC 协议,其实只是整个工作的一部分。
在整个 WebRTC 协议的支持之后,业务上还有很多的衍生,比如需要去跟 RTMP 协议互通,这是 一个 RTMP Gate 的概念,例如基于小程序的部署的便捷性,我们需要兼容它,所以要有 RTC 协议和 RTMP 之间的一个转化。
再就是截帧、合流、录制,这都是作为一个云厂商必备的一些基本的能力。
单点转发面临的挑战
在整个工程部署的时候,我们最开始的时候,是一个单点转发的模式。很多开源项目都是基于单点转发做的。它有很多弊端。
首先,单点转发承载能力受限于单节点能力。
然后,无法满足多用户跨地域就近接入。多用户跨地域,单点式没有办法就近接入。
再其次,单点故障是没有恢复能力的,这个想解决的话,其实很简单,就是去做分布式。
全球加速网络下的 RTC 媒体转发方式
所谓分布式,就是分布式多节点协同的一个媒体转发方式。这个时候我们进行了迭代,部署了全球化加速网络,去做这种 RTC 的媒体分发,这个也是 WebRTC 协议里面没有去定义的部分。这方面,协议和社区没有办法定义,因为这是一个强资源性的东西。
这种多节点的协作,可以满足用户的就近接入的需要,同时我们内部去基于 SD-WAN 的方式实现媒体在内部网络的加速分发,可以完美的解决 first-mile 和 last-mile 接入体验的问题。
关于转发的协议,也是 WebRTC 协议里面没有定义的。而且传统的媒体转发协议是没有办法满足实时流媒体转发的需求。
静态分发模式下的网络组织模型
这个时段,整体的网络结构还是相对比较固定,因为一个机房里面会有多个节点,以机房作为单位扁平化的去做一个分布式的网络模型。然后,同机房内节点互为热备,如果跨区域分发,就通过一些固定的,或者是我们经验主义去产生的路由策略,去进行一个跨区域的分发。
静态分发模式面临的挑战
静态分发模式可以完美解决刚才提到的单点转发面临的挑战,但是随着我们整个业务量,还有用户体积的增多,整个体系复杂了之后,这套模式就比较僵硬,没有办法很灵活的去根据业务场景做调整。
首先,分发路径依赖经验参数。分发路径非常复杂,整个全球化的网络部署之后,还有它的分发,还有这种网络抖动导致的这种分发策略的变更,可能会非常的复杂。
其次,节点规模增加后管理难度提升。管理能力可想可知,这个节点的规模很多。因为我们部署了大量的边缘化的节点。
然后,没有自动化反馈控制机制。整个系统里面,没有一个自动化的反馈机制,每个节点我们都有大量的数据统计,本身 RTC 协议会有几个统计信息的机制,跟 QoE 相关的数据量,我们都没有使用上,还是去靠人工经验的方式,或者是一些监测的数据后置性的去修改整个网络的分发,这个也是有很大的难度的。
动态分发的演进
在动态分发里面,我们通过多维度的数据和科学化的统计为分发系统提供一个反馈。从而可以提供更实时的连接,管理更多元化的资源,进行更精细化的控制并且提供一套更科学的评价方式。
这种动态分发我们是怎么做的?我们有自己的鹰眼数据平台,它最主要能力是给我们提供一个实时控制的数据依据。假如我想做一个分发的路由,从 A 到 C,然后中间我要不要经过 B?这个之前我们是靠经验的,根据经验手动调。而有了这种实时数据反馈之后呢,它会自动的感知,A 到 C 之间的 RTT、 丢包率、抖动情况等参数,将 A 到 B 之间的中转节点的所有的统计数据做一个自动化的计算,省去了人工介入的成本。
这种策略之前,我们根据业务配置去手动调整,如果通过 QoE 评估系统之后,可以完全的自动化了。它会自动的去做一个场景的判断和切换,对于我们每个分发服务的运维和质量保证都是有很大的提升的。
动态分发的性能指标
再看一下动态分发的性能指标:
-
-
登录时间 < 5S
-
卡顿达标率不低于 99.5%
-
端到端延迟 < 400ms
-
我们把这三个指标做了大量的统计,大概是这样的一个数据,登录时间小于 5 秒,卡顿的达标率会不低于 99.5%,卡顿的音频 200ms 没有渲染,视频是 600ms 没有渲染,就算是卡顿。
端到端延迟是整个 RTC 协议的核心灵魂,也是它必要的组成部分。如果抛开端到端的延迟去谈 RTC 就没有太大的意义了。
实践经验分享
接下来,跟大家分享几点实践经验,首先讨论一下我们的分发协议,然后讨论一下我们怎么去做统计信息收集,最后我们再聊聊 WebRTC 协议有哪些坑。
实践经验一——分发协议设计
我们自研了一套 QRTP 的协议。这套协议也并不是特别的复杂,主要解决几个问题,1-RTT 建连、前向纠错(FEC)和拥塞控制。这几个问题解决了,基本就能解决实时分发的需求。
在这个协议里面,我们可以根据对可靠性不同程度的需求来调整协议的数据可靠性,在 TCP 和 UDP 之间,可靠性是 0 和 1 的关系,但是在我们协议里面,可靠性是一个区间的概念。
像 WebRTC 里面的建连,是需要最少 3 个 RTT,这个在服务端转发是不允许的。我们是有一个 1 RTT 建连机制。
实践经验二——统计信息
传统的 WebRTC 协议,RTCP 自带的可以统计出来的这三个信息,即 RTT(往返时延),Fraction Lost(丢包率)、Jitter(抖动),它们都是基于 P2P 的。而经过加速网络分发后,接收端能够统计到的信息只是当前连接的,并不能实时的感知到发布端的统计信息。
那对于接收端,整个链路的统计信息我们怎么统计并让接收端感知的呢?
统计数据是通过 RTCP 的 SR/RR/XR 进行计算获取的。如果经过加速网络分发之后,这个数据就不准了,这个时候我们对 RTCP 做了一些拓展,RTCP 有一个 APP 类型,APP 这个类型是可以去做拓展的,而且它非常适合做那种允许丢失但又是强统计性的信息的传递。然后分发时充分的拓展了 RTCP APP 里面的内容,去实现分发一层一层的传递,这样在接收端能够非常实时的感知到发送端的网络统计信息,即使隔着整个 RTC 分发网络之后,仍然能够清晰的感知到发送端的各种的统计信息,这个也是我们自己去做了大量的调研之后去拓展出来的。
而传统的方式,通常是将分发的统计信息上传到业务平台,我认为是不可取的,因为不能把这种媒体的统计数据放到业务里面,也就是说媒体是媒体,业务是业务,这个是关于统计信息的经验,是我们在服务端做媒体分发的一点经验。
实践经验三——WebRTC 协议的坑
WebRTC 协议的坑,我们知道每个协议都有它自己的属性,就是类似于我们玩游戏选角色的时候,好的游戏设计每个角色都会有不同的强弱特点。WebRTC 协议说到底就是为了保证实时性,是一个实时性的协议,实时性会带给它很多弱点,我大概说几点。
第一,首屏的时间。我们看一下传统的直播,首屏的时间可能已经优化到极致了,比如说它通过缓存 GOP 把首屏时间做到极致,真的做到极致,就是一点击就出来的那种。和前者相比,WebRTC 的首屏是怎么来的?首先要建联,最少 三个 RTT 建联,再请求关键帧,发送端收到请求之后,编码一个关键帧,然后接收端才能正常的渲染,这个首屏的时间,是一个很大的坑。
第二,画质无法保证。给大家举个例子,我们在看新闻的时候,新闻主持人和前方的记者联线的时候,大家有没有发现,可能会有 1 秒左右的延迟。如果使用 类似 WebRTC 这种协议,是完全可以做到让观众无感知的通话,那为什么还有 1 秒钟的延迟?其实它肯定没有采用 WebRTC 这类的协议,为什么?为了保证质量,像 RIST 协议都是有质量保证的协议,虽然实时性可能会有一点点的损失,但是它是会保证质量的。电视台对质量是很敏感的,所以说宁可牺牲 1 秒的延迟,或者说稍微长一点点的延迟,也要保证通话的质量。
第三,生态不完善。WebRTC 的生态,是一个快速迭代的过程,现在最经典的 libwebrtc,几乎每两个月迭代一个版本,它是强迭代的,有很多破坏性的更新。生态处于一个强发展的过程中,但也有不完善,各家有各家的想法。虽然 WebRTC 协议已经发布了,但是你会发现实践的工程中还是有很多小的出入和坑的,生态的不完善还包括哪方面?比如说 OBS 和 FFmpeg 目前仍然没有去完全兼容 WebRTC 协议。
第四,跨浏览器兼容问题。跨浏览器的的兼容问题,是一个非常棘手的问题,目前来说现在还好一些。每个浏览器都有自己的风格,虽然说机制是一样的,还是有不同的风格。
第五,CDN 成本。跟传统的媒体分发的方式对比,它成本是很大的,为什么?首先 RTC 的分发,像我们这个还是基于自研的分发协议,业内没有一个标准,比如说 CDN 好在哪呢?RTMP 好在哪?从底层来讲,RTMP 的分发就是一个实时文件的分发。所以它可以复用传统 CDN 的模式,只要做一些修改就可以完整的支持 RTMP 的分发。但是用到 RTC 的分发上是不可以的,需要重新做一套基础设施。所以,目前来说 RTC 的分发成本是会略高一些。
第六,SRTP/QoS/UDP 性能成本。单点的承载能力,因为整个 RTC 协议接入要有 SRTP 的加密,要有很多 QoS 机制的保证,还有 UDP 本身性能的问题,会减少单点负载的能力,这样也会导致成本的提升。
最后,转码损耗。例如我们在做 RTC 和 RTMP 这种互通的时候,RTC 不支持 AAC,还要支持 Opus 到 AAC 的转码,这个也是有一定消耗的,同时也带来成本的提升。
当然,还有其他的一些坑,有机会我们再细聊。
今天就到这里,谢谢大家。希望通过今天的分享,大家能对七牛云 QRTC 在整个服务端做了哪些有一个大概的了解,以及对 WebRTC 协议能有更进一步的认识。
以上是关于音视频实践日 Live|QRTC 流媒体分发演进的主要内容,如果未能解决你的问题,请参考以下文章
无标题音视频实践日 Live|七牛云 QRTC 媒体传输质量优化实践
无标题音视频实践日 Live|七牛云 QRTC 媒体传输质量优化实践