先说结论
rtc-js 里用户最容易混淆的,其实是两件不同的事:
- 采集分辨率:决定摄像头采上来的原始画面有多大
- 发布大小流:决定是否把同一份画面编码成多层一起发出去
- 想把画面采得更清楚,改的是采集参数
- 想控制“发一层还是发两层”,改的是发布参数里的
simulcasts - 想“只发小流”,本质上不是“开启小流模式”,而是只发一条低分辨率单流
SDK 默认行为
Web SDK 内置摄像头预设里,默认行为如下:CameraPresets['720p']:默认发布camera_big + camera_smallCameraPresets['1080p']:默认发布camera_big + camera_smallCameraPresets['360p']/CameraPresets['180p']:不带默认 simulcast 配置
| 流层 | desc | 分辨率 | 帧率 | 码率 |
|---|---|---|---|---|
| 大流 | camera_big | 跟随主预设 | 跟随主预设 | 跟随主预设 |
| 小流 | camera_small | 320 × 180 | 15 fps | 250 Kbps |
- 一路
camera_big - 一路
camera_small
概念拆开看
1. 采集分辨率
采集分辨率由createLocalCameraTrack(...) 的预设,或 startCapture(...) 传入的参数决定:
2. 发布大小流
发布大小流由publishLocalTrack(...) 时的 VideoPublishOptions.simulcasts 决定:
关键点:
只改采集分辨率,不会自动关闭小流;
只改 simulcasts,也不会改变摄像头实际采集分辨率。
场景一:想改大流分辨率,但仍然保留大小流
这是最常见需求。做法是:- 先把摄像头采集分辨率调到目标值
- 再保留
simulcasts
场景二:只发大流,不发小流
这时不要只改width / height,而是要把 simulcasts 显式清空。
- 频道规模很小,不需要多层切换
- 业务只消费一路主画面
- 想减少上行编码和带宽开销
注意:CameraPresets['720p']/['1080p']默认带小流。 如果你的目标是“只发大流”,就必须显式传simulcasts: []覆盖默认值。
场景三:只发一条低清流
很多人说的“只发小流”,如果从编码原理上说,真正想要的通常是:- 不发
camera_big - 只发一条低分辨率单流
- 只有一条视频轨
- 这条轨的规格就是低清
- 它叫不叫
camera_small只是业务语义命名,底层并不是“大流里的副层被单独打开”
场景四:自定义大小流参数
如果默认的320 × 180 / 250 Kbps 不适合你的业务,可以直接自定义:
- 主层分辨率先按实际业务 UI 需要决定,不要盲目追求 1080p
- 小层优先服务于缩略图、小窗、宫格,因此分辨率和码率都应明显低于主层
- 如果频道里经常出现弱网或多路视频同屏,保留小流通常比只发大流更稳
不建议的用法
不要手动创建两条摄像头轨道来模拟大小流
例如下面这种思路不建议:- 它会变成两条独立业务轨道,而不是同一条视频的多编码层
- 远端需要分别处理两条流,语义更乱
- 本地采集、编码、带宽开销也更高
- 需要大小流时,用一条摄像头轨道 +
simulcasts - 只需要低清单流时,直接发一条低清主流
远端如何理解大小流
远端看到的TrackInfo 里,关键字段有两个:
fallback_ids:主层可降级到哪些更低层variant:是否为 simulcast 副层
- 优先订阅主层轨道
- 不要把
variant === true的副层当成一条普通新视频单独展示
fallback_ids 处理。
选择建议
| 需求 | 推荐做法 |
|---|---|
| 想把主画面从 720p 改成 1080p | 改摄像头预设或 startCapture 参数 |
| 想继续保留大小流 | 保留 simulcasts,或直接用 CameraPresets['720p'] / ['1080p'] |
| 想只发大流 | publishLocalTrack(..., { simulcasts: [] }) |
| 想只发一条低清流 | 直接创建低分辨率单流,不要走双层编码 |
| 想单独调整小流规格 | 自定义 simulcasts 数组 |