26、移动端适配:Android WebRTC、iOS WebRTC、移动端性能调优
移动端做WebRTC,说白了就是一场与硬件和系统的博弈。
我最早在Android上跑通第一个视频通话时,心里还挺美。结果一上真机,发热、卡顿、掉帧全来了。嗯,那时候我才意识到——桌面端的代码,搬到手机上,根本跑不动。
这一章,我就把Android和iOS上WebRTC的适配要点,以及性能调优的实战经验,一次性讲清楚。
Android WebRTC:碎片化是最大的敌人
Android的碎片化问题,做过的都懂。芯片、摄像头、编码器、系统版本,排列组合下来几百种。WebRTC在Android上,最头疼的就是硬编硬解的兼容性。
核心原则:不要依赖默认的编解码器选择逻辑。一定要自己做降级策略。
我个人习惯的做法是:
- 先尝试H264硬编,因为兼容性最好
- 如果硬编失败,降级到H264软编
- 再不行,才考虑VP8
代码上,初始化PeerConnectionFactory时,要显式指定编码器优先级:
// 推荐:显式设置编码器优先级
PeerConnectionFactory.InitializationOptions initOptions =
PeerConnectionFactory.InitializationOptions.builder(context)
.setFieldTrials("WebRTC-H264HighProfile/Enabled/")
.createInitializationOptions();
PeerConnectionFactory.initialize(initOptions);
// 创建工厂时指定编码器
VideoEncoderFactory encoderFactory = new DefaultVideoEncoderFactory(
rootEglBase.getEglBaseContext(),
true, // enableIntelVp8Encoder
true // enableH264HighProfile
);
避坑指南:我曾经在小米某款机型上,硬编H264一直崩溃。后来发现是MediaCodec的异步模式没处理好。建议统一使用同步模式,配合超时机制。
iOS WebRTC:注意后台和权限
iOS这边,WebRTC的集成相对顺滑一些。但有两个坑,我每次都要提醒团队注意。
第一个坑:后台音频。App切到后台,WebRTC的音频流会断。解决方案是启用Audio Session的后台模式:
// 启用后台音频
RTCAudioSession *session = [RTCAudioSession sharedInstance];
[session lockForConfiguration];
NSError *error = nil;
[session setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionMixWithOthers |
AVAudioSessionCategoryOptionAllowBluetooth |
AVAudioSessionCategoryOptionDefaultToSpeaker
error:&error];
[session setActive:YES error:&error];
[session unlockForConfiguration];
第二个坑:摄像头权限。iOS 14之后,权限弹窗的时机变了。一定要在调用摄像头之前,先检查权限状态。否则直接黑屏。
注意:iOS上WebRTC的硬编解码,对A系列芯片优化得很好。但如果你用VP9,发热会非常明显。我个人建议iOS端只用H264。
移动端性能调优:三板斧
性能调优,我总结了三个方向。你想想看,移动端资源就那么点,CPU、内存、网络,哪个都不能爆。
1. 分辨率与帧率的动态调整
不要固定720P 30帧。要根据网络和CPU负载,动态降级。我常用的策略是:
- 网络抖动时,先降分辨率(从720P降到480P)
- CPU超过80%时,降帧率(从30帧降到15帧)
- 两者都差时,同时降
WebRTC自带的Simulcast可以帮我们做这件事,但要注意移动端不要开太多流。我一般只开两层:高清层和低清层。
2. 硬编硬解的正确使用姿势
硬编硬解省电,但坑也多。我遇到过的问题包括:
- 编码器输出延迟(尤其是低端芯片)
- 解码器花屏(切换分辨率时)
- 内存泄漏(MediaCodec没及时释放)
我的解决方案是:每次切换分辨率时,重建编码器/解码器。不要复用旧的实例。
// 切换分辨率时,重建编码器
private fun recreateEncoder(width: Int, height: Int) {
videoEncoder?.release()
videoEncoder = VideoCodec.createEncoder(
VideoCodecType.H264,
width, height,
30, // fps
2000 // bitrate kbps
)
}
3. 网络抗丢包与带宽估计
移动网络丢包率经常到5%以上。WebRTC默认的NACK+FEC组合,在弱网下效果还行。但我建议做两件事:
- 开启Transport-CC(传输层拥塞控制),比GCC更准
- 设置合理的FEC比例,不要超过20%,否则带宽浪费太大
我的经验:在4G网络下,丢包率3%以内,WebRTC默认配置就能扛住。超过5%,建议开启SVC(可伸缩视频编码),让接收端自己决定收多少数据。
移动端适配知识体系
下面这张图,是我自己整理的移动端WebRTC适配核心逻辑。你看一眼,基本就全了。
最后说几句
移动端WebRTC适配,没有银弹。每个机型、每个系统版本,都可能出幺蛾子。我的建议是:
- 建立自己的兼容性测试矩阵
- 线上加日志,出了问题能快速定位
- 不要追求极致画质,流畅度优先
嗯,这一章就到这里。移动端的水很深,但掌握了这些核心思路,你至少不会翻船。
公众号:蓝海资料掘金营,微信deep3321