浏览器三大API
WebRTC 在浏览器里的全部能力就是三套 API。把这三个学透,剩下都是工程化封装。
阅读顺序
| 顺序 | 文件 | 解决的问题 |
|---|---|---|
| 1 | MediaStream与采集.md | getUserMedia、getDisplayMedia、MediaStreamTrack 全套 |
| 2 | RTCPeerConnection.md | 生命周期、Transceiver、addTrack vs addTransceiver |
| 3 | RTCDataChannel.md | 可靠/不可靠语义、背压、典型用法 |
| 4 | 编解码与协商.md | VP8/VP9/H.264/AV1/Opus、setCodecPreferences |
三件套的职责切分
MediaStream / MediaStreamTrack
└── 采集层:从硬件拿数据 → 输出 Track
RTCPeerConnection
└── 连接层:建链、协商、收发 Track、控制带宽和码率
RTCDataChannel
└── 数据层:任意二进制/字符串 P2P 通道
必须用 Unified Plan
WebRTC 历史上有两种 SDP 表示方式:
- Plan B(Chrome 旧):所有视频 Track 共享一条 m-line。已废弃。
- Unified Plan(标准,Chrome 72+ / Firefox / Safari):一条 Track 一条 m-line,标准化 Transceiver 模型。
new RTCPeerConnection() 在所有现代浏览器都默认 Unified Plan。禁止通过 sdpSemantics: 'plan-b' 切回去——只会带来兼容问题。
addTrack vs addTransceiver
| 选择 | 何时用 | 关键差异 |
|---|---|---|
pc.addTrack(track, stream) | 简单场景,先有 Track 再加 | 自动创建 sendrecv transceiver |
pc.addTransceiver(kind, options) | 先建好通道、Track 后续设置 | 可指定 direction、sendEncodings、streams |
服务端订阅模型(先建 transceiver 等服务端推流)必须用 addTransceiver。Simulcast 配置也只能在 addTransceiver({sendEncodings}) 时指定。
关键事件速查
| 事件 | 时机 | 通常处理 |
|---|---|---|
negotiationneeded | 需要重新协商 | 触发 createOffer 流程 |
icecandidate | 收到本地新候选 | 通过信令发给对端 |
track | 收到对端媒体 | 挂到 <video>.srcObject |
datachannel | 对端创建 DataChannel | 监听消息 |
connectionstatechange | 整体连接状态变化 | 监控 connected/failed |
iceconnectionstatechange | ICE 状态变化 | 触发 ICE Restart |
signalingstatechange | SDP 协商状态变化 | 调试用 |
反模式总览
| 反模式 | 后果 | 修复 |
|---|---|---|
getUserMedia 后立刻 track.stop() 想"预热" | 直接释放设备,下次还得等用户授权 | 用 MediaStreamTrack.enabled = false 静音 |
用 <video>.srcObject = null 想停止采集 | 只断开展示,硬件还在采 | 必须 track.stop() |
给同一个 RTCPeerConnection 反复 addTrack 然后 removeTrack | 协商风暴 | 用 transceiver.sender.replaceTrack(newTrack) 切换 |
DataChannel 不监听 bufferedamountlow | 大文件发送时浏览器 OOM | 用 bufferedAmount 做背压 |
不监听 negotiationneeded 自己手动触发 | 漏掉补充协商 | 让浏览器告诉你什么时候需要 |