|
| 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