WebRTC + 直播技术学习路线
目标:理解 WebRTC 原理 + 跑通 Android 推拉流 Demo + 了解移动端直播架构
节奏:工作日 30-45 分钟(看理论),周末集中写代码
整理时间:2026-06
一、背景知识:WebRTC vs 传统直播
1.1 WebRTC 不只针对 Web
WebRTC 有完整的 Android / iOS 原生库,移动端支持非常成熟:
- Android:
org.webrtc:google-webrtc或io.getstream:stream-webrtc-android - iOS:内置 WebRTC.framework
- Web:浏览器原生支持
1.2 三种运行模式
| 模式 | 架构 | 适用场景 | 延迟 |
|---|---|---|---|
| P2P | 端到端直连 | 1v1 通话 | 最低 |
| SFU | 服务器转发,不解码 | 多人会议、连麦 | 低 |
| MCU | 服务器解码+混流 | 大会议、弱网端 | 较高 |
腾讯会议、Zoom 均采用 SFU + MCU 混合模式,根据参与人数和网络状况动态切换。
1.3 传统直播 vs WebRTC 详细对比
架构对比
1 | # 传统直播 |
延迟对比
| 协议 | 延迟 | 原因 |
|---|---|---|
| HLS | 5-30秒 | 切片缓冲,每片2-10秒 |
| HTTP-FLV | 1-3秒 | 流式传输,有缓冲区 |
| RTMP | 1-3秒 | TCP,有重传队列 |
| WebRTC | 50-500ms | UDP,丢包直接丢弃不等重传 |
WebRTC 延迟低的根本原因:宁可丢帧,不等重传。
弱网表现
WebRTC 内置三重弱网保障:
- NACK:发现丢包主动请求重传
- FEC(前向纠错):提前发冗余包,丢了也能还原
- GCC(Google Congestion Control):实时估算带宽,自动降码率保流畅
成本对比
| 传统直播 | WebRTC | |
|---|---|---|
| 分发成本 | 低(CDN按流量) | 高(SFU服务器) |
| 开源生态 | FFmpeg/ijkplayer/SRS | WebRTC原生/Mediasoup/Livekit |
| 延迟 | 秒级 | 毫秒级 |
1.4 移动端直播架构全貌
1 | 主播手机 |
二、Week 1-2:理论打底
工作日 30-45 分钟,通勤/睡前均可。不写代码,先把原理搞透。
Week 1:WebRTC 核心原理
必须理解的 5 个核心概念:
① 信令(Signaling)
- WebRTC 本身不定义信令协议,需要自己实现
- 本质:交换 SDP 和 ICE Candidate 的通道
- 常见实现:WebSocket / HTTP 长轮询 / 任意方式均可
② SDP(Session Description Protocol)
- 描述「我能用什么编解码器、什么格式通信」
- 使用 Offer/Answer 模型:A 发 Offer,B 回 Answer
③ ICE / STUN / TURN
1 | STUN Server:告诉你「你的公网 IP 是 x.x.x.x:port」 |
④ DTLS + SRTP
- 所有 WebRTC 媒体流强制加密,无法关闭
- DTLS:基于 UDP 的 TLS,握手交换密钥
- SRTP:加密后的 RTP,传输音视频数据
⑤ 拥塞控制(GCC)
- 实时估算当前可用带宽
- 带宽充足 → 提升码率/分辨率;带宽不足 → 降低码率
推荐阅读:WebRTC for the Curious(必读,免费电子书)
Week 2:音视频基础
视频编解码器对比
| 编解码器 | 特点 | WebRTC 中的角色 |
|---|---|---|
| H.264 | 硬件支持最广,兼容性最好 | Android 默认首选 |
| H.265/HEVC | 压缩率更高,但专利费问题 | 部分场景使用 |
| VP8 | Google 开源,无专利 | WebRTC 早期默认 |
| VP9 | VP8 升级版,压缩率好 | Chrome 常用 |
| AV1 | 新一代,压缩率最高 | 逐步普及中 |
关键参数关系
1 | 码率 = 分辨率 × 帧率 × 压缩率(近似) |
帧类型
- I帧(关键帧):完整图像,可独立解码,体积大
- P帧(预测帧):相对前一帧的差异,体积小
- B帧(双向预测帧):WebRTC 通常不用(增加延迟)
推荐阅读:Digital Video Introduction
三、Week 3-4:Android WebRTC 第一个 Demo
Week 3:Loopback Demo
添加依赖:
1 | // app/build.gradle |
核心 API 学习顺序:
1 | PeerConnectionFactory(全局初始化) |
Loopback Demo 核心逻辑:
1 | // 本机两个 PeerConnection 互连,不需要服务器 |
验收标准: 本机摄像头画面出现在两个 SurfaceViewRenderer 里。
Week 4:信令服务器 + 1v1 通话
最简信令服务器(Node.js):
1 | const WebSocket = require('ws') |
两台手机通话时序:
1 | 设备A 信令服务器 设备B |
验收标准: 两台手机互相看到对方摄像头,听到对方声音。
四、Week 5-6:SFU + 多人推拉流
Week 5:接入 Livekit
搭建服务器:
1 | docker run --rm \ |
Android 接入核心代码:
1 | implementation 'io.livekit:livekit-android:2.5.0' |
验收标准: 3台手机进同一房间,互相能看到听到。
Week 6:传统推拉流(RTMP + HLS)
搭建 SRS 服务器:
1 | docker run -p 1935:1935 -p 8080:8080 ossrs/srs:5 |
Android RTMP 推流(腾讯 LiteAV SDK):
1 | val pusher = V2TXLivePusher(this, V2TXLiveMode.TXLiveMode_RTMP) |
Android HLS 拉流(ExoPlayer):
1 | val player = ExoPlayer.Builder(this).build() |
验收标准: 一台手机推 RTMP,另一台 ExoPlayer 拉 HLS 播放。
五、Week 7-8:融会贯通
Week 7:自测问题
- 为什么 WebRTC 的延迟比 HLS 低 10-100 倍?
- ICE 协商失败会怎样?TURN 服务器的作用是什么?
- GCC 是怎么估算带宽的?丢包和延迟增大各触发什么策略?
- SFU 和 MCU 的 CPU 消耗为什么差这么多?
- 1000 人观看的直播,WebRTC 和 HLS 的服务器成本差多少?
Week 8:Wireshark 抓包
1 | brew install wireshark |
重点观察:
- STUN Binding Request/Response:ICE 发现公网地址
- DTLS ClientHello/ServerHello:加密握手过程
- RTCP REMB 包:带宽估算反馈信号
六、配套资源
| 资源 | 类型 | 链接 |
|---|---|---|
| WebRTC for the Curious | 必读电子书 | https://webrtcforthecurious.com/ |
| Digital Video Introduction | 音视频基础 | https://github.com/leandromoreira/digital_video_introduction |
| stream-webrtc-android | Android WebRTC 库 | https://github.com/GetStream/webrtc-android |
| Livekit Android SDK | SFU 接入 | https://github.com/livekit/client-sdk-android |
| SRS 流媒体服务器 | 传统直播服务器 | https://github.com/ossrs/srs |
| AppRTCMobile | Google 官方示例 | https://chromium.googlesource.com/external/webrtc/ |
七、每周验收 Checklist
Week 1
- 能解释 SDP Offer/Answer 交换过程
- 能画出 ICE 连接建立的流程图
- 理解 STUN 和 TURN 的区别
Week 2
- 理解 I/P/B 帧区别,知道 WebRTC 为什么不用 B 帧
- 能解释码率/帧率/分辨率三者关系
Week 3
- Loopback Demo 跑通
- 理解 SDP 协商在代码里如何触发
Week 4
- 信令服务器搭起来
- 两台手机 1v1 通话成功
Week 5
- Livekit 3人房间跑通
- 理解 SFU 模式下每个客户端的上下行
Week 6
- RTMP 推流 + HLS 拉流跑通
- 能描述「直播+连麦」混合架构
Week 7
- 能回答全部 5 个自测问题
Week 8
- 抓到 DTLS 握手包并能解释
- 找到 RTCP REMB 包,理解其作用
附录一:服务端用 Docker,客户端跑真机
为什么推荐 Docker 跑服务端
跑 Demo 时服务端有三个组件:信令服务器、Livekit SFU、SRS 流媒体服务器。这三个用 Docker 有明显优势:
- 一行命令启动,不污染本机环境
- 随时销毁重建,环境始终干净
- 官方镜像开箱即用,无需手动编译配置
1 | # 信令服务器(自己写的 Node.js) |
不适合用 Docker 的部分
- Android App:必须跑在真机或 Android 模拟器上,Docker 里没有摄像头/麦克风
- Wireshark 抓包:Docker 有网络 NAT 层,抓包会变复杂,建议直接在宿主机抓
推荐组合
1 | 服务端(Docker) 客户端(真机) |
局域网内手机和 Mac 互通,your-server 填 Mac 的局域网 IP 即可。
附录二:常见问题排查
ICE 连接失败
- 检查 STUN 服务器是否可达
- 检查防火墙是否放行 UDP
- 检查 ICE candidate 是否正确交换
- 添加 TURN 服务器作为兜底
画面卡顿/花屏
- 查看丢包率(>5% 明显影响质量)
- 确认硬件编码已启用
- 检查码率是否超过实际带宽
Android 音频回声
- 确认 AEC(回声消除)已启用
- 检查 AudioManager 模式是否为 MODE_IN_COMMUNICATION
最后更新:2026-06