实时音视频 rtc 的媒体协商流程及原理

实时音视频rtc的媒体协商流程及原理

说起实时音视频通话,可能很多人第一反应就是"打开APP,点个按钮,对方接起来就能聊了"。但实际上,从你点击"通话"按钮到双方真正能看见彼此、听见彼此,中间经历了一场相当复杂的"握手"过程。这个过程,就是我们今天要聊的媒体协商。

你可能觉得这玩意儿太技术了,跟自己没什么关系。但了解一下,你会发现这里面的门道其实挺有意思的,而且理解之后,你就能明白为什么有些通话质量好、有些通话总是卡顿,甚至还能明白为什么有些APP在某些环境下就是打不通电话。

从一个真实的场景说起

想象一下这个画面:你和远在北京的朋友约好了视频聊天。你打开APP,点击"视频通话",这时候会发生什么?

你以为信号像变魔术一样"嗖"一下就飞过去了?实际情况是,你的手机先得和对方的手机"认识一下",互相确认一下"我能发什么格式的视频"、"你能收什么格式的视频"、"咱们用哪个端口通讯"、"走哪条网络线路"……这一系列确认和协调的过程,就是媒体协商。

这个过程之所以存在,是因为互联网太大了,每个人的设备不一样,网络环境不一样,支持的音视频格式也不一样。就像两个人聊天,一个说中文一个说英语,肯定得先商量好用哪种语言,不然你说你的、我听我的,根本没法交流。

媒体协商到底在协商什么

媒体协商要解决的核心问题,其实就是三个:说什么(音视频格式)、怎么说(传输方式)、在哪说(网络路径)。

先说说什么的问题。音视频的格式可不仅仅是分辨率和帧率这么简单,里面涉及到编码器(也就是用什么算法压缩数据)、采样率、声道数、码率控制方式等等一系列参数。你的手机可能支持几十种编码格式,对方手机支持的可能是另一套。这时候就需要坐下来商量,找一个两边都能支持的"最大公约数"。

举个例子,假设你的手机支持H.264、H.265和AV1三种视频编码,而对方只支持H.264和VP8。那最优方案就是选择H.264作为视频编码。音频也是一样的道理,Opus、AAC、G.711这些编解码器各有优缺点,需要协商出一个两边都能处理的结果。

然后是怎么说的问题。这里涉及到传输协议的选型,是用UDP还是TCP?RTP还是SRTP?要不要开启冗余包来抗丢包?这一系列传输层面的参数也需要双方达成一致。

最后是在哪说的问题,这才是最复杂的。你的手机可能在小区WiFi上,对方可能在办公室的局域网里,你们之间隔着路由器、防火墙、NAT设备……怎么找到一条能通的路,这就是ICE协议要干的事情。

SDP:媒婆手里的那份"相亲资料"

提到媒体协商,就不得不说说SDP这个协议。SDP的全称是Session Description Protocol,翻译过来就是会话描述协议。你可以把它理解成一张"相亲资料卡",上面写着你的各项条件和诉求。

一份典型的SDP文件大概长这个样子:里面会告诉你我的IP地址和端口是什么、我支持哪些媒体类型(是音视频都有还是只有音频)、每种媒体用的是什么编码格式、编码参数是多少……把这些信息打包成一段文本,发给对方,对方再回一份自己的SDP过来,双方一对照,协商就完成了。

这个过程有个专门的名称,叫做Offer/Answer模型。发起方先扔出一份Offer,里面写着自己的"条件";接收方看完之后,给出一份Answer,表示"我同意这些条件"或者"咱們改一改";来来回回几轮之后,最终达成一致,媒体协商就完成了。

这个模型设计得挺巧妙的,它允许在Offer和Answer之间进行修改。比如接收方发现自己不支持某个编码格式,就可以把那段删掉,换成自己支持的。这样一来一回,最终总能找到两边都能接受的方案。

NAT和ICE:打通网络的那条路

前面说到网络路径的问题,这里得好好展开讲讲,因为这是实际部署中最让人头疼的部分。

我们现在用的互联网协议主要是IPv4,但公网IP地址是有限的。家里的WiFi、公司的局域网,用的都是内网IP地址,从外面是访问不到的。这就需要NAT(网络地址转换)来帮忙。NAT的作用就是给内网设备分配一个公网端口映射,让外网的请求能找到你。

但问题来了,NAT的类型有很多种。有的是锥形NAT,有的是对称形NAT,每种的打通难度都不一样。有些NAT很"开放",只要你往外发过包,外面就能随便进来;有些NAT很"封闭",只有你主动联系的对方才能反过来联系你。

这就很让人头疼了。假设你在公司的对称形NAT后面,你想给家里的朋友打视频电话,你的手机发出的数据包能出去,但对方想回复你的时候,NAT一看来源地址不是之前那个,就会把包扔掉。电话就打不通。

为了解决这个问题,业界搞出了一套叫做ICE的框架,全称是Interactive Connectivity Establishment,交互式连接建立。ICE的思路很简单:既然我不知道哪条路能通,那我就多准备几条路,一条一条试。

具体怎么做呢?ICE会收集候选地址。候选地址分好几种:一种是主机地址,就是你本机的IP和端口;一种是服务器反射地址,就是你到STUN服务器那边挂号的公网地址;还有中继地址,就是通过TURN服务器转发数据的地址。这些地址排好顺序,先试直连,不行就转发,总有一条能通。

这个过程叫做"候选对连通性检查"。把本地的候选地址和对方的候选地址配成对,然后试着发探测包,看能不能正常往返。能通的候选对就会被选为最终的传输路径。

整个过程是有时间限制的,ICE会设置一个总的超时时间,在这个时间内尽量多地尝试。如果超时之前找到了能用的路径,那就皆大欢喜;如果超时了还没找到,那这次通话就只能放弃了。

实际流程是怎样的

现在我们把整个流程串起来讲一遍,看看到底是怎么一步步走下来的。

第一步,初始化。当你点击"通话"按钮的时候,SDK会先看看本地有什么媒体设备可用,摄像头有几个、麦克风在不在工作……这些信息会被收集起来,作为后续协商的基础材料。

第二步,生成Offer。SDK会根据本地支持的能力,生成一份SDP Offer,里面包含本地的媒体能力、网络候选地址等信息。这份Offer会通过信令通道发到对方那里。信令通道可能是WebSocket,也可能是HTTP长连接,反正就是能可靠地把消息送到对方手里。

第三步,处理Offer。对方收到Offer之后,会解析里面的内容,看看对方支持什么格式、自己能不能配合。如果发现有些格式自己不支持,就会把那些从SDP里删掉或者替换掉。然后生成Answer,再通过信令通道发回去。

第四步,ICE候选交换。在Offer和Answer之外,还有一件事在同步进行,就是ICE候选的交换。双方都会把自己的候选地址通过信令通道一条一条发过去,对方收到之后就记下来,准备做连通性检查。

第五步,连通性检查。双方都在候选池里取出一些候选对,组成探测任务,然后开始互相发探测包。这个过程是并行进行的,每隔一段时间ICE框架就会检查一下有没有新的候选对可用,有没有已经超时失效的。

第六步,媒体通道就绪。当ICE选出了最终可用的候选对,双方就都知道了该往哪个地址发数据。从这一刻起,音视频数据就可以开始传输了。

第七步,媒体流控制。协商完成之后,双方还会持续交换rtcP包,里面包含网络质量、丢包率、延迟等信息。如果发现网络变差了,可能会主动降级编码参数,比如把1080P降到720P,甚至降到480P,以保证通话不断。

这个流程看起来步骤挺多的,但在实际部署中,整个过程往往只需要几百毫秒就能完成。除非网络环境特别差,候选地址特别多,否则大多数情况下你点击通话按钮之后,很快就能看到画面了。

影响协商成功率的关键因素

了解了原理之后,我们来看看哪些因素会影响媒体协商的成功率。

首先是NAT类型。如果双方都在对称形NAT后面,那直连基本上是不可能的,只能靠TURN中继。这就会增加延迟和成本。所以有些应用会在进入通话之前先检测双方的NAT类型,如果都是对称形NAT,就提前准备好TURN资源。

其次是防火墙设置。有些公司的网络安全策略非常严格,只开放特定的端口。这时候ICE收集的候选地址可能根本没法用,通话就建立不起来。很多企业级应用会采用部署中继服务器的方式来解决这个问题。

再次是候选地址的数量。如果候选地址收集得不够全面,可能会漏掉一些能通的路径;如果收集得太多,ICE的探测时间就会变长,影响通话建立的速度。这需要在全面性和时效性之间做一个权衡。

还有就是网络环境的变化。比如你正在打着电话,从WiFi切换到了4G,这时候IP地址就变了,原来的传输路径可能就失效了。有些实现会在这种情况下触发重新协商,切换到新的路径上;有些则可能直接断线。

为什么不同的APP体验差异很大

回到开头的问题,为什么有些APP通话很顺畅,有些APP总是打不通或者容易卡顿?这里面的差异主要体现在几个方面。

第一是候选地址收集的全面性。有些SDK只会收集本地网卡的地址,有些则会探测更多的候选地址,包括通过不同网络接口的地址、通过STUN拿到的反射地址、甚至主动配置的中继地址。候选地址越全面,通话建立的成功率就越高。

第二是ICE策略的优化。有些实现会用比较激进的策略,优先尝试直连,如果直连不通再试中继;有些则会比较保守,先保证能用再说。这两种策略各有利弊,需要根据场景来选择。

第三是编码器的适配能力。不同的设备、不同的操作系统版本,对音视频编码器的支持程度是不一样的。一套好的SDK应该能自动检测设备能力,挑选出最优的编码组合。有些低端设备可能不支持H.264 High Profile,这时候就得退回到Baseline Profile,画质会有明显差距。

第四是弱网对抗能力。当网络出现丢包或者抖动的时候,不同的处理方式会导致完全不同的体验。有些实现会牺牲帧率来保证清晰度,有些则会降低分辨率来保证流畅度。这需要在产品层面做很多调优工作。

写在最后

聊了这么多关于媒体协商的东西,你会发现这个看似简单的"点个按钮就能打视频"背后,实际上涉及到网络协议、编解码技术、系统架构等多个领域的知识。每一次顺畅的通话体验,都是这些技术协同工作的结果。

作为开发者来说,理解这些原理是非常有必要的。它能帮助你在遇到通话问题时快速定位原因,也能帮助你在选型和技术决策时做出更好的判断。毕竟,实时音视频是一个对体验要求非常高的场景,任何一个环节的疏漏都可能影响用户的通话质量。

如果你正在开发一个需要实时音视频功能的APP,建议在产品设计阶段就把这些因素考虑进去。比如,要不要提前检测网络环境?要不要准备备用方案?弱网情况下如何降级?这些决策都会直接影响最终的用户体验。

技术的东西说再多,最终还是要落到实际应用中。希望这篇文章能给你一些启发,也希望你在开发自己的应用时,能少走一些弯路。毕竟,让用户能够顺畅地和朋友家人视频通话,本身就是一件很有价值的事情。

上一篇实时音视频服务的扩容流程及自动化实现
下一篇 rtc 的信令协议性能测试方法及指标

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱:

工作时间:周一至周五,9:00-17:30,节假日休息
关注微信
微信扫一扫关注我们

微信扫一扫关注我们

手机访问
手机扫一扫打开网站

手机扫一扫打开网站

返回顶部