
做rtc开发这些年,我遇到过太多次”明明网络看起来没问题,但通话就是卡顿”的尴尬情况。甲方一个电话打过来,用户投诉画面糊成马赛克,声音断断续续像在发电报的那种。后来我发现,通话质量优化这件事,真的不是调一个参数就能解决的,它是一个系统工程。
这篇文章我想把声网RTC的通话质量优化思路好好梳理一下,把那些踩过的坑、积累的经验都分享出来。我们不搞那些玄之又玄的理论,就从实际出发,说说怎么一步步把通话质量做上去。
很多人嘴上说”要最好的通话质量”,但你问他什么算好质量,他又说不清楚。在我看来,通话质量得看四个核心指标,它们像四个相互制约的兄弟,你想让某一个做到极致,往往就得牺牲另外一个。
首先是延迟,这个最好理解,就是从你说话到对方听到的时间差。正常情况下,200毫秒以内双方通话基本无感,300到500毫秒会有轻微滞后,超过500毫秒对话就会开始变得别扭,超过800毫秒那基本上就是各说各的了。
然后是清晰度,这个取决于你用的编码分辨率和码率。720P肯定比480P清楚,1080P更没问题,但清晰度高了数据量就大,网络稍微有点波动就容易出问题。
第三是流畅度,也就是帧率。30fps基本够用,60fps当然更顺滑,但高帧率意味着每秒钟要传输更多数据帧,网络带宽压力大的时候宁可降帧率也不能让画面卡住不动。
最后一个是稳定性,这个最容易被忽视但也最重要。忽好忽坏的体验比一直将就更让人难受,用户刚觉得通话还行,突然一下卡住半秒钟,这种落差感最伤口碑。

| 质量指标 | 优秀标准 | 可接受标准 | 用户开始抱怨 |
| 延迟 | < 200ms | 200-400ms | > 500ms |
| 视频分辨率 | 1080P | 720P | 480P及以下 |
| 帧率 | 30fps+ | 24fps | < 15fps |
| 丢包率 | < 1% | 1-3% | > 5% |
搞明白这四个指标的关系之后,你会发现所谓的优化,其实就是在它们之间找平衡。比如网络不好的时候,你首先要保证的是低延迟和稳定,清晰度和帧率可以适当让步。等网络好了,再把参数调回去。这才是成熟的优化思路,不是跟网络死磕,而是学会跟网络妥协。
我见过不少团队,一上来就问我要怎么调参数,结果一问才发现,他们连自己用户大概有多少带宽都没仔细评估过。这就像装修房子不问户型就开始买家具,很容易买错。
声网的SDK其实内置了带宽探测的功能,但我建议最好在正式通话开始之前,先做个简单的网络质量探测。探测的目的不是测个数字出来,而是要搞清楚当前网络的上行和下行能力大概是什么样的。

探测的时候有几点要注意。首先别在网络高峰期测,你要是晚上八点测用户家的网速,那数据肯定偏悲观的。其次多测几次取个平均值,一次探测的结果可能有偶然性。还有就是探测的时候尽量模拟真实使用场景,比如如果你的应用主要在手机4G环境下用,那就用手机网络去测,别用办公室WiFi测出来的数据指导移动端参数。
码率自适应这个功能,我建议只要网络条件不是特别好的用户,都应该打开。它的工作原理其实挺简单:网络好了就提高码率让画面更清楚,网络差了就降低码率保证流畅,别让数据堵在路上。
但这里有个误区很多人会踩。有些人以为开了自适应就万事大吉了,自己不用管了。其实自适应只是帮你做动态调整,它的调整范围是有边界的。如果你把最小码率设得太高,网络差的时候它也降不下去,照样会卡顿。反过来如果最大码率设得太低,网络好的时候它也提不起来,画面永远不够清楚。
我的经验是,先用固定码率跑一段时间,看看在你的主要用户群体中,网络分布大概是什么样的,然后再去设置自适应的上下限。这样既能让网络好的用户享受到高质量,又能让网络差的用户保证基本流畅。
移动端用户有个特点,就是网络会经常切换。WiFi切4G,4G切WiFi,甚至有时候信号不好会从4G掉到3G。这种场景对RTC的考验特别大,因为网络状态突变的时候,原来的码率设置可能突然就不合适了。
比较好的做法是在检测到网络类型变化的时候,主动做一次码率重估。比如从WiFi切到4G,这时候4G的上行带宽通常比WiFi紧张,你得主动把码率降一降,给网络留点余量。等网络稳定了,再慢慢往上调。
另外就是移动网络特有的NAT和防火墙问题。有些运营商的网络会有比较严格的NAT策略,导致UDP包被限制得很厉害。这种情况下声网的算法会自动切换到TCP模式,虽然延迟会高一点,但至少能保证通话不断。
分辨率和帧率这两个参数怎么设,是问我最多的问题。我的回答永远是:看场景。
如果你是做视频会议这种场景,大家主要是看文档、看PPT,那分辨率比帧率重要。1080P的文档字迹清晰度肯定比720P好,但30帧和60帧在PPT翻页这种场景下差别不大。这时候我建议优先保证分辨率,帧率24到30就够了。
如果是做直播或者互动娱乐,用户主要看人脸和动作,那帧率就比分辨率重要了。60帧的脸部微表情明显比30帧自然,但60帧的码率开销也比30帧大很多。这时候可以考虑适当降低分辨率来换帧率,比如720P 60帧比1080P 30帧在很多场景下体验更好。
还有一种情况是屏幕共享。共享屏幕的时候,静态内容多,动态内容少。这时候完全可以把帧率降到10到15帧,然后省下来的带宽全部给分辨率,让文字和图形显示得更清晰。
编码参数这块,我分享几个我自己验证过的经验值,仅供参考,具体肯定还要根据自己的场景调。
视频编码这块,H.264编码器在大多数场景下兼容性是最好的。除非你有特殊需求,否则默认用H.264就行。码率控制模式我建议用CRF或者VBR,固定码率(CBR)在网络波动的时候容易出问题。关键帧间隔(GOP)建议设在2到4秒之间,太短了会增加码率开销,太长了会让延迟增加而且切换画面的时候会有明显卡顿。
音频编码相对简单一些,通常Opus编码器可以覆盖大多数场景。采样率建议用48kHz,这个采样率在质量和带宽之间平衡得比较好。如果你的用户网络条件普遍不太好,可以降到32kHz,但再低我就不建议了,音质损失太明显。
下面这张表是我整理的一个码率参考框架,基于主流的网络条件。但重申一下,这是参考值,具体一定要根据自己的用户反馈来调。
| 网络条件 | 视频码率建议 | 音频码率建议 | 分辨率 |
| 优质WiFi/有线 | 1.5-2.5Mbps | 64-128kbps | 1080P |
| 普通WiFi/4G良好 | 800K-1.5Mbps | 48-64kbps | 720P |
| 一般4G/较差WiFi | 400-800Kbps | 32-48kbps | 480P |
| 弱网环境 | 150-400Kbps | 24-32kbps | 360P及以下 |
这个表里有一个原则我要解释一下:音频码率不要压得太狠。很多人在网络差的时候喜欢把音频也压得很低来省带宽,但这其实得不偿失。声音是通话场景中用户最敏感的部分,宁可视频差点也要保证音频清楚。我的经验是,音频至少要保留24kbps以上,再低的话人声就会开始失真了。
丢包不可怕,可怕的是你不知道包是怎么丢的。在RTC系统中,丢包可能发生在三个环节:上行丢包、下行丢包,还有中间网络传输过程中的丢包。
上行丢包一般是你这边的网络上行带宽不够,数据发不出去导致的。这种情况你本地网络肯定有问题,看一下有没有人在下载东西,或者用无线的话是不是信号不太好。下行丢包是对方那边的问题,你这边网络正常但收到的包不完整。中间传输丢包就是网络链路的问题了,可能是跨运营商,可能是有网络波动,这种你控制不了。
声网的SDK会帮你统计这些数据,你看质量报告的时候要注意区分是上行丢包多还是下行丢包多,这对定位问题很有帮助。如果是上行丢包多,那得优化你本地的网络条件;如果是下行丢包多,可能是对方的问题,或者你们之间的链路有问题。
抗丢包主要有两种技术手段:前向纠错(FEC)和重传(ARQ)。它们各有优缺点,用哪个要看你的场景。
FEC的原理是在发送数据的时候多发一些冗余包,这样即使丢了一些包,接收方也能把丢失的数据恢复出来。它的好处是延迟低,丢包了不需要等待重传就能恢复。但它的问题是冗余包本身也要占用带宽,如果丢包率很高,FEC的效率反而会下降,因为发再多冗余包也可能被一起丢掉。
ARQ就是传统的丢包重传机制,收到丢包通知之后再补发。它的好处是不浪费带宽,只有丢了才重传。但缺点是延迟高,因为要等一轮往返时间才能知道丢了,然后还要再等一轮才能收到重传的包。
我的建议是,在丢包率比较低的时候(5%以内),优先用FEC,因为延迟体验更好。在丢包率比较高的时候(超过10%),可以FEC和ARQ结合着用,用FEC扛一部分,ARQ补一部分。声网的SDK里这两个功能都有,可以分别配置开关和强度。
网络抖动是比丢包更烦人的问题。丢包至少知道哪个包没了,抖动是包到了但顺序乱了或者 timing 不对。想象一下,你说话的声音传到对方那里有时候快有时候慢,这种体验比偶尔卡顿一下更难受。
抖动缓冲(Jitter Buffer)是解决这个问题的核心机制。它的原理是接收方收到包之后不马上播放,而是先缓存一小段时间,把顺序排好,把快慢不一的包整理成均匀的节奏再推送给播放器。
这里有个关键的权衡:缓冲区设得越大,抗抖动能力越强,但延迟也越高;缓冲区设得小,延迟低,但稍微有点抖动就会卡顿。通常我建议动态调整这个缓冲区的大小,网络稳定的时候缩小缓冲区降低延迟,网络抖动的时候放大缓冲区保证流畅。
声网的抖动自适应算法做得还不错,默认情况下会自动根据网络状况调整这个buffer的大小。如果你的场景对延迟特别敏感(比如乐器合奏、远程操控),可以手动把buffer设小一点,但要做好心理准备,网络波动的时候可能会出现卡顿。
现在大多数设备都有硬件编码器,用硬件编码比软件编码效率高,发热低,电池耐用。但硬件编码器有个问题:它的参数配置不如软件编码器灵活,有些参数你想调但调不了。
我遇到过一种情况:某个型号的手机,硬件编码器支持的码率上限比较低,当你想要高质量编码的时候,它死活达不到你设定的码率,画面就变得一团糟。后来发现是硬件编码器的能力限制,换成软件编码器就解决了。
所以我建议在发布之前,多测几种主流设备。如果某些设备用硬件编码器表现不好,可以考虑在那些设备上回退到软件编码器。虽然软件编码器费电一点,但总比画面质量差要好。
别以为网络没问题就万事大吉了,我见过很多案例,通话质量差是因为设备本身性能跟不上。手机发热严重的时候,CPU会降频,编码速度变慢,导致帧率上不去。内存紧张的时候,系统可能会杀掉后台进程,影响音视频处理。
一个简单的排查方法是:通话质量差的时候,看一下设备的CPU使用率和温度。如果CPU占用率长期在80%以上,或者温度超过45度,那很可能是性能瓶颈导致的降级表现。
这种情况下的优化策略主要是两个方向。一是降低音视频处理的复杂度,比如减少滤镜和特效,降低分辨率,减轻设备负担。二是引导用户在使用RTC通话的时候关闭其他耗电耗资源的应用。
安卓系统有个很坑的地方:不同厂商对音频系统的实现差异很大。有的厂商为了省电,会把后台应用的音频优先级降得很低,导致通话声音断断续续。还有的厂商有各种音频加速引擎,有时候会和rtc sdk产生冲突。
如果你的用户反馈在某些特定品牌的手机上通话有问题,可以重点排查一下系统音频设置。比如有的手机需要在应用设置里打开”后台弹出界面”的权限,有的需要关闭”省电模式”下的应用限制。这些问题光靠代码优化解决不了,得在产品层面做好用户引导。
最后我想分享几个排查通话质量问题时的实用思路,这些思路帮我定位过很多看起来很奇怪的问题。
当用户投诉通话质量差的时候,首先要做的是获取完整的质量报告。声网的SDK会生成详细的通话质量数据,包括每分钟的丢包率、延迟、码率变化等信息。拿到这些数据后,先看丢包发生在上行还是下行,这能帮你快速锁定问题方向。
然后要关注时间点。很多质量问题不是一直存在的,而是某个时间点突然出现的。比如用户说”昨天通话好好的,今天就卡了”,那很可能跟网络环境变化有关。看看质量报告里从什么时候开始指标恶化的,对应那时候有没有网络切换或者其他操作。
还有就是对比测试。如果某个用户反馈有问题,可以让用户用另一台设备或者另一个网络环境再试试。如果换了设备就好了,那是设备问题;如果换了网络就好了,那是网络问题;如果换了什么都一样,那可能是应用本身的问题。这种排除法虽然笨,但很有效。
哦对了,还有一个常见但容易被忽视的问题:用户侧的物理环境。比如用户用的蓝牙耳机质量不好,或者麦克风被挡住了,或者用户那边有很强的电磁干扰。这些问题靠看日志是看不出来的,只能靠用户反馈和引导去排查。
通话质量优化这件事,说到底没有一劳永逸的解决方案。网络环境在变,用户设备在变,你的应用也在迭代,质量优化的工作就得一直做下去。我的建议是保持对用户反馈的敏感,建立一个持续监测的机制,有了问题及时响应,长期积累下来,你对自己的用户群体有足够的了解,优化起来就会越来越得心应手。
希望这篇文章对你有帮助。如果有具体的问题想要讨论,欢迎在评论区交流。
