Skip to content

Commit 3381d3f

Browse files
authored
FCE-3096 - document simulcast (#243)
## Description Adds simulcast documentation.
1 parent 1fcda5a commit 3381d3f

9 files changed

Lines changed: 390 additions & 20 deletions

File tree

api/fishjam-server

api/room-manager

docs/examples/react-native.mdx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ _Runnable reference apps demonstrating common Fishjam use cases in React Native_
1010
Each example is a standalone Expo application you can run locally and use as a starting point for your own project.
1111
All examples use `@fishjam-cloud/react-native-client` and require a Fishjam ID from the [Fishjam Dashboard](https://fishjam.io/app).
1212

13-
| Example | What it demonstrates |
14-
| ----------------------------------------- | ------------------------------------------------------------------ |
15-
| [Minimal Video Room](#minimal-video-room) | Simplest possible video call — the baseline for all other examples |
16-
| [Fishjam Chat](#fishjam-chat) | Full-featured video conferencing and livestreaming app |
17-
| [Background Blur](#background-blur) | Applying real-time video effects via camera track middleware |
18-
| [Text Chat](#text-chat) | Peer-to-peer text messaging with WebRTC data channels |
19-
| [Video Player](#video-player) | Livestream broadcaster and viewer with separate UI modes |
13+
| Example | What it demonstrates |
14+
| ----------------------------------------- | --------------------------------------------------------------------- |
15+
| [Minimal Video Room](#minimal-video-room) | Simplest possible video call — the baseline for all other examples |
16+
| [Fishjam Chat](#fishjam-chat) | Full-featured video conferencing and livestreaming app with simulcast |
17+
| [Background Blur](#background-blur) | Applying real-time video effects via camera track middleware |
18+
| [Text Chat](#text-chat) | Peer-to-peer text messaging with WebRTC data channels |
19+
| [Video Player](#video-player) | Livestream broadcaster and viewer with separate UI modes |
2020

2121
---
2222

@@ -61,6 +61,7 @@ A full-featured application covering two distinct room types: a video conferenci
6161
- Environment switching between staging and production
6262
- Screen sharing from a livestream broadcaster
6363
- Permission handling with a reusable `useMediaPermissions` hook
64+
- Selecting received video quality with simulcast (`setReceivedQuality`)
6465

6566
### Running the example
6667

docs/examples/react.mdx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ _Runnable reference apps demonstrating common Fishjam use cases in React_
1010
Each example is a standalone React application you can run locally and use as a starting point for your own project.
1111
All examples use `@fishjam-cloud/react-client` and require a Fishjam ID from the [Fishjam Dashboard](https://fishjam.io/app).
1212

13-
| Example | What it demonstrates |
14-
| ----------------------------------- | ---------------------------------------------------------------------- |
15-
| [Minimal React](#minimal-react) | Simplest video call — join a room, camera, mic, screen share |
16-
| [Audio Only](#audio-only) | Voice chat with no video and microphone device selection |
17-
| [Text Chat](#text-chat) | Peer-to-peer messaging over WebRTC data channels |
18-
| [Livestreaming](#livestreaming) | One broadcaster, many viewers with separate streamer/viewer UIs |
19-
| [Minimal Smelter](#minimal-smelter) | Custom video overlays using the Smelter rendering engine |
20-
| [Fishjam Chat](#fishjam-chat) | Full-featured conferencing app with background blur and screen sharing |
13+
| Example | What it demonstrates |
14+
| ----------------------------------- | ----------------------------------------------------------------------- |
15+
| [Minimal React](#minimal-react) | Simplest video call — join a room, camera, mic, screen share, simulcast |
16+
| [Audio Only](#audio-only) | Voice chat with no video and microphone device selection |
17+
| [Text Chat](#text-chat) | Peer-to-peer messaging over WebRTC data channels |
18+
| [Livestreaming](#livestreaming) | One broadcaster, many viewers with separate streamer/viewer UIs |
19+
| [Minimal Smelter](#minimal-smelter) | Custom video overlays using the Smelter rendering engine |
20+
| [Fishjam Chat](#fishjam-chat) | Full-featured conferencing app with background blur and screen sharing |
2121

2222
---
2323

@@ -33,6 +33,7 @@ The simplest way to get a video call working in the browser — joining a room,
3333
- Enabling camera and microphone with `useCamera` and `useMicrophone`
3434
- Starting screen sharing with `useScreenShare`
3535
- Rendering streams with `VideoPlayer` and `AudioPlayer` components
36+
- Selecting received video quality with simulcast (`setReceivedQuality`)
3637

3738
### Running the example
3839

docs/explanation/simulcast.mdx

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
type: explanation
3+
sidebar_position: 8
4+
description: How simulcast enables adaptive video quality by sending multiple resolution variants simultaneously.
5+
---
6+
7+
# Simulcast
8+
9+
_Multi-quality video streaming for adaptive bandwidth and layout-aware rendering_
10+
11+
Simulcast allows a video sender to encode and transmit the same video at multiple quality levels (variants) simultaneously. Each receiver independently chooses which variant to receive, enabling adaptive quality based on network conditions, UI layout, or user preference.
12+
13+
## Why Simulcast?
14+
15+
Without simulcast, every receiver gets the same video quality. This creates a trade-off: receive high quality (wastes bandwidth for small thumbnails) or receive low quality (degrades the experience for full-screen viewers).
16+
17+
Simulcast solves this on the receiver side -- a sender publishes multiple variants, and each receiver requests only the quality it needs. The trade-off is increased upload bandwidth on the sender, since it encodes and transmits multiple variants simultaneously. If this overhead is not acceptable, the sender can [choose which variants to publish](#sender-configuration) or disable simulcast entirely.
18+
19+
- A **thumbnail grid** can request low quality for all participants
20+
- A **spotlight view** can request high quality for the active speaker and low for everyone else
21+
- A participant on a **slow connection** can request medium quality regardless of UI layout
22+
23+
## Quality Variants
24+
25+
Three predefined quality tiers are available via the `Variant` enum:
26+
27+
| Variant | Meaning |
28+
| ------------------------ | --------------------------- |
29+
| `Variant.VARIANT_LOW` | Low quality / resolution |
30+
| `Variant.VARIANT_MEDIUM` | Medium quality / resolution |
31+
| `Variant.VARIANT_HIGH` | High quality / resolution |
32+
33+
## How It Works
34+
35+
```mermaid
36+
sequenceDiagram
37+
participant Sender
38+
participant Server as Fishjam Server
39+
participant ReceiverA as Receiver A (thumbnail)
40+
participant ReceiverB as Receiver B (full-screen)
41+
42+
Sender->>Server: Video (LOW + MEDIUM + HIGH)
43+
ReceiverA->>Server: setReceivedQuality(LOW)
44+
Server->>ReceiverA: Forwards LOW variant
45+
ReceiverB->>Server: setReceivedQuality(HIGH)
46+
Server->>ReceiverB: Forwards HIGH variant
47+
```
48+
49+
1. The **sender** encodes the camera feed into up to three variants and sends all of them to the Fishjam server.
50+
2. The **server** receives all variants but only forwards the one each receiver has requested.
51+
3. Each **receiver** calls `setReceivedQuality` on a remote track to tell the server which variant it wants. The receiver can change this at any time.
52+
53+
## Sender Configuration
54+
55+
The sender controls which variants to publish via the `sentQualities` option in `FishjamProvider`'s `videoConfig`:
56+
57+
- **All variants** (default): Omit `sentQualities` or pass `[Variant.VARIANT_LOW, Variant.VARIANT_MEDIUM, Variant.VARIANT_HIGH]`
58+
- **Subset**: Pass only the variants you need, e.g. `[Variant.VARIANT_LOW, Variant.VARIANT_HIGH]`
59+
- **Disabled**: Pass `false` to send a single quality stream (no simulcast)
60+
61+
## Receiver Quality Selection
62+
63+
Remote tracks expose a `setReceivedQuality` method. This is only available on **remote** peer tracks. Your own local tracks don't have it, since you don't "receive" your own video.
64+
65+
The `RemoteTrack` type (exported from both `@fishjam-cloud/react-client` and `@fishjam-cloud/react-native-client`) extends the base `Track` type with a `setReceivedQuality(quality: Variant)` method.
66+
67+
When you call `setReceivedQuality`, the server switches which variant it forwards for that track. The change takes effect almost immediately.
68+
69+
## When to Use Simulcast
70+
71+
Simulcast is most valuable when:
72+
73+
- Your app has **multiple layout modes** (grid, spotlight, picture-in-picture)
74+
- Participants have **varying network conditions**
75+
- You want to **reduce bandwidth** for participants viewing many small thumbnails
76+
- You're building **adaptive quality** that responds to UI state
77+
78+
For simple 1:1 calls where both sides always show full-screen video, simulcast adds encoding overhead without much benefit. Consider disabling it with `sentQualities: false`.
79+
80+
## See also
81+
82+
- [Simulcast how-to guide](../how-to/features/simulcast): step-by-step implementation
83+
- [Architecture](./architecture): how Fishjam routes media

0 commit comments

Comments
 (0)