Simulcast
Simulcast is a feature of WebRTC that allows a publisher to send multiple video streams of the same media at different qualities. For example, this is useful for scenarios where you want to send a high quality stream for desktop users and a lower quality stream for mobile users.
graph LR A[Publisher] -->|Low quality| B[Cloudflare Realtime SFU] A -->|Medium quality| B A -->|High quality| B B -->|Low quality| C@{ shape: procs, label: "Subscribers"} B -->|Medium quality| D@{ shape: procs, label: "Subscribers"} B -->|High quality| E@{ shape: procs, label: "Subscribers"}
Simulcast in WebRTC allows a single video source, like a camera or screen share, to be encoded at multiple quality levels and sent simultaneously, which is beneficial for subscribers with varying network conditions and device capabilities. The video source is encoded into multiple streams, each identified by RIDs (RTP Stream Identifiers) for different quality levels, such as low, medium, and high. These simulcast streams are described in the SDP you send to Cloudflare Realtime SFU. It's the responsibility of the Cloudflare Realtime SFU to ensure that the appropriate quality stream is delivered to each subscriber based on their network conditions and device capabilities.
Cloudflare Realtime SFU will automatically handle the simulcast configuration based on the SDP you send to it from the publisher. The SFU will then automatically switch between the different quality levels based on the subscriber's network conditions, or the qaulity level can be controlled manually via the API. You can control the quality switching behavior using the simulcast
configuration object when you send an API call to start pulling a remote track.
The simulcast
configuration object in the API call when you start pulling a remote track allows you to specify:
-
preferredRid
: The preferred quality level for the video stream (RID for the simulcast stream. RIDs can be specified by the publisher. ↗) -
priorityOrdering
: Controls how the SFU handles bandwidth constraints.none
: Keep sending the preferred layer, set via the preferredRid, even if there's not enough bandwidth.asciibetical
: Use alphabetical ordering (a-z) to determine priority, where 'a' is most desirable and 'z' is least desirable.
-
ridNotAvailable
: Controls what happens when the preferred RID is no longer available, for example when the publisher stops sending it.none
: Do nothing.asciibetical
: Switch to the next available RID based on the priority ordering, where 'a' is most desirable and 'z' is least desirable.
You will likely want to order the asciibetical RIDs based on your desired metric, such as higest resoltion to lowest or highest bandwidth to lowest.
Cloudflare Realtime treats all media tracks equally at the transport level. For example, if you have multiple video tracks (cameras, screen shares, etc.), they all have equal priority for bandwidth allocation. This means:
- Each track's simulcast configuration is handled independently
- The SFU performs automatic bandwidth estimation and layer switching based on network conditions independently for each track
When a layer switch is requested (through updating preferredRid
) with the /tracks/update
API:
- The SFU will automatically generate a Full Intraframe Request (FIR)
- PLI generation is debounced to prevent excessive requests
For publishers (local tracks), you only need to include the simulcast attributes in your SDP. The SFU will automatically handle the simulcast configuration based on the SDP. For example, the SDP should contain a section like this:
a=simulcast:send f;h;qa=rid:f senda=rid:h senda=rid:q send
If the publisher endpoint is a browser you can include these by specifying sendEncodings
when creating the transceiver like this:
const transceiver = peerConnection.addTransceiver(track, { direction: "sendonly", sendEncodings: [ { scaleResolutionDownBy: 1, rid: "f" }, { scaleResolutionDownBy: 2, rid: "h" }, { scaleResolutionDownBy: 4, rid: "q" } ]});
Here's an example of how to use simulcast with Cloudflare Realtime:
- Create a new local track with simulcast configuration. There should be a section in the SDP with
a=simulcast:send
. - Use the Cloudflare Realtime API to push this local track, by calling the /tracks/new endpoint.
- Use the Cloudflare Realtime API to start pulling a remote track (from another browser or device), by calling the /tracks/new endpoint and specifying the
simulcast
configuration object along with the remote track ID you get from step 2.
For more examples, check out the Realtime Examples GitHub repository ↗.
Was this helpful?
- Resources
- API
- New to Cloudflare?
- Products
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark