移动端WebRTC:Android与iOS集成实战
说实话,移动端WebRTC开发是我个人觉得最"坑"也最有意思的部分。为什么?因为桌面端跑得好好的代码,一上手机就各种翻车。我最早做移动端WebRTC时,光是把Demo跑起来就折腾了两天——嗯,后来才发现是权限没配全。
这一章,我把Android和iOS的集成要点、性能优化技巧、还有那些年我踩过的坑,一次性讲清楚。
Android WebRTC集成:从零开始
Android集成WebRTC,说白了就三步:引入库、配权限、写代码。但每一步都有讲究。
1. 引入WebRTC库
我个人习惯用Google官方的Maven仓库,版本号跟着Chrome走就行。
// build.gradle (app级别)
dependencies {
implementation 'org.webrtc:google-webrtc:1.0.32006'
}
2. 权限配置
Android 6.0以上需要动态申请权限。这里有个坑:CAMERA和RECORD_AUDIO是必须的,但很多人忘了INTERNET权限。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
3. 核心代码骨架
初始化PeerConnectionFactory是第一步。你想想看,没有工厂,哪来的连接对象?
// 初始化PeerConnectionFactory
PeerConnectionFactory.InitializationOptions initOptions =
PeerConnectionFactory.InitializationOptions.builder(context)
.setFieldTrials("")
.createInitializationOptions();
PeerConnectionFactory.initialize(initOptions);
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
PeerConnectionFactory factory = PeerConnectionFactory.builder()
.setOptions(options)
.createPeerConnectionFactory();
iOS WebRTC集成:Swift与OC的抉择
iOS端集成WebRTC,我个人推荐用CocoaPods。为什么?省心。手动编译WebRTC的iOS版本,那编译时间够你喝三杯咖啡。
1. Podfile配置
platform :ios, '12.0'
target 'YourApp' do
pod 'GoogleWebRTC'
end
这里要注意:iOS 12.0是最低要求。我试过在iOS 11上跑,结果某些API直接崩溃——说白了,苹果对旧版本的支持越来越少了。
2. 权限与后台模式
Info.plist里需要加两样东西:摄像头权限描述、麦克风权限描述。还有,如果你要做后台通话,记得开启Audio, AirPlay, and Picture in Picture后台模式。
<key>NSCameraUsageDescription</key>
<string>需要访问摄像头进行视频通话</string>
<key>NSMicrophoneUsageDescription</key>
<string>需要访问麦克风进行语音通话</string>
3. Swift集成示例
import GoogleWebRTC
class VideoCallManager {
private var factory: RTCPeerConnectionFactory?
private var peerConnection: RTCPeerConnection?
func setup() {
// 初始化SSL(必须!)
RTCInitializeSSL()
// 创建工厂
let encoderFactory = RTCDefaultVideoEncoderFactory()
let decoderFactory = RTCDefaultVideoDecoderFactory()
factory = RTCPeerConnectionFactory(
encoderFactory: encoderFactory,
decoderFactory: decoderFactory
)
}
}
移动端性能优化:别让手机变暖手宝
移动端性能优化,核心就三个字:省、稳、快。省电、稳定、快速。我总结了一张优化清单,直接拿去用。
| 优化项 | 具体做法 | 效果 |
|---|---|---|
| 分辨率自适应 | 根据网络带宽动态调整分辨率 | 减少卡顿,降低CPU负载 |
| 硬件编码优先 | 优先使用H.264硬件编码 | 降低功耗,提升帧率 |
| 帧率控制 | 非通话场景降低到15fps | 省电效果明显 |
| 音频降噪 | 开启内置降噪算法 | 提升通话质量 |
| 内存管理 | 及时释放PeerConnection | 防止OOM |
分辨率自适应实现
说白了,就是根据网络状况动态调整。我习惯用WebRTC自带的带宽估计器,再结合自己的策略。
// 设置视频发送参数
RTCVideoEncoderSettings *settings = [[RTCVideoEncoderSettings alloc] init];
settings.name = @"H264";
settings.width = 640;
settings.height = 480;
settings.startBitrate = 500; // 初始500kbps
settings.maxBitrate = 1500;
settings.minBitrate = 100;
settings.maxFramerate = 30;
// 监听网络变化,动态调整
- (void)onNetworkChanged:(NSInteger)bitrate {
if (bitrate < 300) {
// 网络差,降低分辨率
settings.width = 320;
settings.height = 240;
} else if (bitrate > 1000) {
// 网络好,提升分辨率
settings.width = 1280;
settings.height = 720;
}
}
移动端常见问题:那些年我踩过的坑
问题1:Android端摄像头黑屏
我曾经遇到过这个问题,排查了半天,最后发现是摄像头被其他应用占用了。比如你开了微信视频,再打开自己的App,摄像头就黑了。
解决方案: 在打开摄像头前检查可用性,捕获异常后提示用户关闭其他应用。
问题2:iOS端音频突然消失
这个坑我印象特别深。有一次用户反馈说通话到一半,突然听不到声音了。后来发现是音频会话被系统中断了——比如来了个电话,或者闹钟响了。
解决方案: 监听AVAudioSession的 interruption 通知,中断结束后自动恢复音频。
// 监听音频中断
NotificationCenter.default.addObserver(
self,
selector: #selector(handleInterruption),
name: AVAudioSession.interruptionNotification,
object: nil
)
@objc func handleInterruption(_ notification: Notification) {
guard let info = notification.userInfo,
let type = info[AVAudioSessionInterruptionTypeKey] as? UInt else { return }
if type == AVAudioSession.InterruptionType.ended.rawValue {
// 恢复音频会话
try? AVAudioSession.sharedInstance().setActive(true)
}
}
问题3:内存泄漏
移动端WebRTC最容易出现的问题就是内存泄漏。PeerConnection、MediaStream、VideoTrack这些对象,如果不及时释放,内存会一直涨。
解决方案: 遵循"谁创建,谁释放"的原则。离开房间时,一定要调用close()和dispose()。
// 正确释放资源
peerConnection?.close()
peerConnection = nil
factory = nil