用 水 来举例子从而理解比特率
-
网络带宽等于水管的容量
- 粗水管,水流大相当于光纤宽带
- 细水管,水流小相当于 4G 网络
-
比特率设置等于水龙头开度
- 水龙头开的大,水流急相当于高比特率
- 水龙头开的小,水流小相当于低比特率
-
网络质量等于水压
- 水压稳定,水流顺畅相当于网络好
- 水压不稳定,水流断续相当于网络差
WebRTC 里的比特率
比特率等于单位时间内传输的数据量,单位是 kbps / Mbps。
在 WebRTC 的日常讨论中,大家常说的“码率”,可以宏观地理解为比特率,通常指音视频的媒体码率,而不是底层网络的总流量。
在 WebRTC 中,比特率有几个不同的概念:
| 类型 | 含义 | 举例 |
|---|---|---|
| 编码比特率 | 编码器产生的数据速率 | 水泵的抽水速度 |
| 发送比特率 | 实际发送的数据速率 | 水龙头出水速度 |
| 接收比特率 | 对方实际接收的数据速率 | 对方接水的速度 |
| 目标比特率 | 系统想要达到的速率 | 期望的出水速度 |
| 可用带宽 | 网络实际能承载的速率 | 水管的最大通水量 |
这些值通常是不一样的,WebRTC 的目标是让它们尽可能匹配。
WebRTC 对比特率的自动调节
WebRTC 通常使用 以 GCC(Google Congestion Control)为代表的拥塞控制算法,根据网络反馈来 持续动态调节 比特率,网络变好,提高比特率(画面更清晰);网络变差,降低比特率(保证不卡顿)。整个过程的原则是: 宁愿水流小,也不能断流。
工作流程如下:
-
开始通话
-
初始探测(较小比特率)
-
逐步增加比特率
-
检测网络反馈(丢包率、延迟、抖动)
-
判断网络状态
- 良好: 继续增加比特率
- 变差: 降低比特率
-
持续循环
如何设置比特率
通过 RTCRtpSender.setParameters
const sender = pc.getSenders().find(s => s.track.kind === 'video');
const params = sender.getParameters();
params.encodings[0].maxBitrate = 1500 * 1000; // 1.5 Mbps
params.encodings[0].minBitrate = 300 * 1000;
sender.setParameters(params);
但是需要注意:这里的设置只是设置上限和下限,最终能否达到是由 GCC 决定。
实际项目中,通常只设置 maxBitrate,让 WebRTC 在网络变差时可以自由下降,比强行限制最小码率更稳定。
常见分辨率对应的帧率和码率
下表为常见经验值,实际效果会受到编码器、内容复杂度和网络状况等影响。
| 分辨率 | 帧率 | 建议码率 |
|---|---|---|
| 360p | 15fps | 300–500 kbps |
| 480p | 30fps | 500–1000 kbps |
| 720p | 30fps | 1–2 Mbps |
| 1080p | 30fps | 3–4 Mbps |
常见误区
比特率是不是越高越好?
不是。WebRTC 的目标不是“越清晰越好”,而是,在不造成卡顿的前提下,尽可能清晰。
比特率需要与当前网络条件匹配:
-
比特率太高(水龙头开得很大、水流很急,但水管不够粗)
- 网络带宽不够用
- 结果:视频卡顿、语音断断续续
- 就像用 4G 网络看 4K 电影
-
比特率太低(水管很粗,但水龙头开得很小)
- 网络带宽够,但发送的数据太少
- 结果:画面模糊、马赛克多
- 就像用光纤网络看 240p 的视频
我已经设置了比特率,为什么实际达不到?
这是正常现象。
通过 setParameters 设置的比特率只是期望范围, WebRTC 会根据实时网络情况自动调整,最终是否能达到目标,由拥塞控制算法决定。
码率、比特率、带宽是一回事吗?
不是一回事
- 带宽:网络最多能承载多少数据(水管容量)
- 比特率 / 码率:当前实际发送的数据速率(水流大小)
弱网下,WebRTC 是先降画质还是先卡顿?
通常是 先降码率,再降画质,尽量避免卡顿。
这也是 WebRTC 拥塞控制的核心原则:宁愿清晰度下降,也要保证播放连续
是不是应该手动频繁调整比特率?
一般不建议。
WebRTC 已经内置了成熟的自动调节机制,频繁手动干预,反而可能与系统策略冲突,导致效果变差。