TL;DR
Whatrtc-js users most often confuse are actually two different things:
- Capture resolution: decides how large the raw video captured by the camera is
- Publishing simulcast: decides whether the same video is encoded into multiple layers and sent together
- To capture sharper video, change the capture parameters
- To control “send one layer or two”, change
simulcastsin the publish parameters - To “send only the low stream”, you don’t “enable low-stream mode”; you send a single low-resolution stream
SDK default behavior
The Web SDK’s built-in camera presets behave as follows by default:CameraPresets['720p']: publishescamera_big + camera_smallby defaultCameraPresets['1080p']: publishescamera_big + camera_smallby defaultCameraPresets['360p']/CameraPresets['180p']: no default simulcast configuration
This means that if you write it like this:
- one
camera_big - one
camera_small
The concepts, separated
1. Capture resolution
Capture resolution is determined by the preset passed tocreateLocalCameraTrack(...), or by the parameters passed to startCapture(...):
2. Publishing simulcast
Publishing simulcast is determined byVideoPublishOptions.simulcasts when calling publishLocalTrack(...):
Key point:
Changing only the capture resolution doesn’t turn off the low stream automatically;
changing only simulcasts doesn’t change the camera’s actual capture resolution either.
Scenario 1: change the high-stream resolution but keep simulcast
This is the most common need. To do it:- First set the camera capture resolution to the target value
- Then keep
simulcasts
Scenario 2: send only the high stream, no low stream
Don’t just changewidth / height here; explicitly empty simulcasts.
- The channel is small and doesn’t need layer switching
- Your app only consumes one main video
- You want to reduce uplink encoding and bandwidth cost
Note:CameraPresets['720p']/['1080p']include the low stream by default. If your goal is “send only the high stream”, you must explicitly passsimulcasts: []to override the default.
Scenario 3: send only a single low-resolution stream
When people say “send only the low stream”, from an encoding standpoint what they usually want is:- Don’t send
camera_big - Send only a single low-resolution stream
- There’s only one video track
- That track’s spec is low resolution
- Whether it’s called
camera_smallis just naming for your app’s semantics; underneath, it isn’t “the secondary layer of the high stream turned on by itself”
Scenario 4: customize simulcast parameters
If the default320 × 180 / 250 Kbps doesn’t fit your app, customize it directly:
- Decide the main layer’s resolution based on what your UI actually needs; don’t chase 1080p blindly
- The secondary layer mainly serves thumbnails, small windows, and grids, so its resolution and bitrate should be clearly lower than the main layer’s
- If the channel often has poor networks or multiple videos on screen at once, keeping the low stream is usually more stable than sending only the high stream
Not recommended
Don’t create two camera tracks manually to simulate simulcast
For example, this approach isn’t recommended:- It becomes two independent app-level tracks rather than multiple encoding layers of the same video
- Remote users have to handle two streams separately, which muddles the semantics
- Local capture, encoding, and bandwidth costs are also higher
- When you need simulcast, use one camera track +
simulcasts - When you only need a single low-resolution stream, send just one low-resolution stream directly
How remote users see simulcast
In theTrackInfo seen by remote users, two fields matter:
fallback_ids: which lower layers the main layer can fall back tovariant: whether this is a simulcast secondary layer
- Subscribe to the main layer track first
- Don’t display a secondary layer with
variant === trueas a separate new video
fallback_ids.