22、移动端适配:React Native集成、原生WebRTC、移动端性能优化、触控交互
说实话,做WebRTC这么久,我踩过最大的坑就是移动端适配。
PC上跑得飞起的视频会议,一到手机上就卡成PPT。屏幕小、网络差、CPU弱,这三个问题就像三座大山。今天我就把这几年的实战经验掰开揉碎,跟你聊聊怎么在移动端把WebRTC玩明白。
22.1 React Native集成:从Web到App的跨越
很多团队选React Native,说白了就是为了复用代码。但WebRTC这块,RN并没有原生支持。你需要一个桥接层。
核心思路:用react-native-webrtc这个库,把原生WebRTC能力暴露给JS层。
安装很简单:
npm install react-native-webrtc
cd ios && pod install
然后你就可以在RN里写这样的代码:
import {
mediaDevices,
RTCPeerConnection,
RTCSessionDescription,
RTCIceCandidate
} from 'react-native-webrtc';
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
// 获取本地流
const stream = await mediaDevices.getUserMedia({
audio: true,
video: { facingMode: 'user' }
});
stream.getTracks().forEach(track => {
pc.addTrack(track, stream);
});
嗯,这里要注意一点。RN的getUserMedia和浏览器版不太一样。它返回的不是MediaStream,而是MediaStream的RN封装。我刚开始没注意,直接当浏览器API用,结果调试了一整天。
我的习惯:在RN项目里,我会单独封装一个webrtcService.js,把所有原生API调用都集中管理。这样万一要切到Flutter或者纯原生,改动范围最小。
22.2 原生WebRTC:Android和iOS的差异
如果你追求极致性能,或者RN满足不了你的需求,那就得上原生WebRTC了。
Android用Google的官方库,iOS用Google的Pod库。接口基本一致,但细节差异很大。
| 平台 | 库名 | 关键类 | 注意事项 |
|---|---|---|---|
| Android | org.webrtc:google-webrtc | PeerConnectionFactory | 需手动初始化EglBase |
| iOS | GoogleWebRTC | RTCPeerConnectionFactory | 需在主线程操作UI |
Android初始化示例:
PeerConnectionFactory.InitializationOptions initOptions =
PeerConnectionFactory.InitializationOptions.builder(context)
.setFieldTrials("WebRTC-H264HighProfile/Enabled/")
.createInitializationOptions();
PeerConnectionFactory.initialize(initOptions);
EglBase eglBase = EglBase.create();
PeerConnectionFactory factory = PeerConnectionFactory.builder()
.setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
.setVideoEncoderFactory(new DefaultVideoEncoderFactory(eglBase.getEglBaseContext(), true, true))
.createPeerConnectionFactory();
iOS初始化示例:
RTCPeerConnectionFactory *factory = [[RTCPeerConnectionFactory alloc] init];
RTCVideoSource *videoSource = [factory videoSource];
RTCVideoCapturer *capturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:videoSource];
我曾经踩过的坑:Android上如果忘记初始化EglBase,渲染视频时直接黑屏。iOS上如果在后台线程操作UI,会触发断言崩溃。这两个问题我各花了两天才定位到。
22.3 移动端性能优化:帧率、分辨率、码率
移动端性能优化,说白了就是做减法。你不能像PC那样开1080p 30fps,手机扛不住。
我一般建议这样配置:
- 分辨率:默认640x480,网络好时升到1280x720
- 帧率:15fps起步,最高24fps
- 码率:500kbps-1.5Mbps,动态调整
代码实现:
const constraints = {
audio: true,
video: {
width: { ideal: 640 },
height: { ideal: 480 },
frameRate: { ideal: 15, max: 24 },
bitrate: { ideal: 800000 }
}
};
// 动态调整
function adjustBitrate(pc, newBitrate) {
const sender = pc.getSenders().find(s => s.track?.kind === 'video');
if (sender) {
const params = sender.getParameters();
params.encodings[0].maxBitrate = newBitrate;
sender.setParameters(params);
}
}
你想想看,为什么帧率要设15fps?因为人眼对视频流畅度的感知,15fps已经够用了。再高的话,CPU和电池都受不了。
核心原则:移动端优化不是追求最高质量,而是在可接受的质量下,保证稳定性和低功耗。
22.4 触控交互:手势、缩放、布局
移动端没有鼠标,所有交互都靠手指。这就带来了一些特殊问题。
手势缩放:视频画面支持双指缩放
// React Native手势处理
import { PinchGestureHandler, State } from 'react-native-gesture-handler';
function onPinchEvent(event) {
if (event.nativeEvent.state === State.ACTIVE) {
const scale = event.nativeEvent.scale;
// 调整视频渲染尺寸
videoRef.current.setNativeProps({
style: { transform: [{ scale: scale }] }
});
}
}
布局适配:不同屏幕尺寸下,视频网格要自适应
- 竖屏模式:主视频占上半屏,小窗列表在底部
- 横屏模式:视频网格铺满全屏
- 画中画:支持悬浮小窗
触控反馈:按钮点击要有视觉反馈,不然用户不知道点没点上
我个人的经验:移动端视频会议里,最常用的操作是静音和切换摄像头。这两个按钮一定要放在拇指容易够到的位置。别学某些App把静音按钮放在左上角,单手根本点不到。
22.5 知识体系总览
下面这张图,是我整理的本章节核心逻辑。你看一眼就能明白移动端适配的全貌。
这张图把四个核心模块串起来了。你从RN集成入手,搞不定就下沉到原生层,然后做性能优化,最后用触控交互收尾。每一步都有坑,但每一步也都有解法。
总结一句话:移动端WebRTC适配,本质是在有限资源下做平衡。平衡质量与功耗,平衡流畅与清晰,平衡功能与易用。