Skip to content

Commit e2ef9f0

Browse files
authored
Copy MoQ over to 0.27.0 (#261)
1 parent 229dcda commit e2ef9f0

4 files changed

Lines changed: 537 additions & 3 deletions

File tree

docs/explanation/moq-streaming.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
type: explanation
33
sidebar_position: 6
4-
title: MoQ Streaming
4+
title: MoQ Streaming with Fishjam
55
description: Understand how Media over QUIC (MoQ) works in Fishjam — the relay model, publish/subscribe architecture, paths, and token-based access control.
66
---
77

docs/tutorials/moq.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
---
22
type: tutorial
33
sidebar_position: 5
4-
title: MoQ Streaming
4+
title: How to stream Media over QUIC
55
description: Stream live video and audio over Media over QUIC (MoQ) with Fishjam, from sandbox prototyping to production deployment.
66
---
77

88
import Tabs from "@theme/Tabs";
99
import TabItem from "@theme/TabItem";
1010

11-
# MoQ Streaming
11+
# How to stream Media over QUIC
1212

1313
This section explains how to publish and subscribe to live streams using [Media over QUIC (MoQ)](https://datatracker.ietf.org/wg/moq/about/) with Fishjam.
1414
MoQ uses QUIC as its transport layer (with a WebSocket fallback), delivering ultra-low latency at scale — making it ideal for interactive broadcasts, live events, and large-audience streams.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
---
2+
type: explanation
3+
sidebar_position: 6
4+
title: MoQ Streaming with Fishjam
5+
description: Understand how Media over QUIC (MoQ) works in Fishjam — the relay model, publish/subscribe architecture, paths, and token-based access control.
6+
---
7+
8+
# MoQ Streaming with Fishjam
9+
10+
_How Media over QUIC (MoQ) works in Fishjam_
11+
12+
## What is MoQ?
13+
14+
[Media over QUIC (MoQ)](https://datatracker.ietf.org/wg/moq/about/) is a new internet standard for live media delivery, designed from the ground up for **scalable, low-latency streaming to large audiences**.
15+
16+
Unlike WebRTC — which was primarily built for interactive, peer-to-peer conferencing — MoQ is optimized for the one-to-many broadcast model: one publisher, potentially thousands of simultaneous subscribers, all receiving the stream with minimal delay.
17+
18+
A few properties make MoQ stand out:
19+
20+
- **Built on QUIC.** QUIC is a modern transport protocol that eliminates head-of-line blocking, recovers from packet loss more gracefully than TCP, and establishes connections faster. For live video, this means more resilient delivery at low latency.
21+
- **Standardized negotiation.** Because MoQ defines a common signaling and subscription protocol, any MoQ-compliant client can connect to any MoQ-compliant relay — you are not locked into a proprietary stack.
22+
- **Relay-based architecture.** The relay is a first-class part of the MoQ protocol, not an add-on. Because relaying is built into the protocol's design, scaling delivery to large audiences is a native capability.
23+
24+
:::info
25+
Fishjam also supports WebRTC-based livestreaming (WHIP/WHEP). See [Livestreams](./livestreams) for that approach.
26+
:::
27+
28+
## How MoQ Works in Fishjam
29+
30+
Fishjam provides a **MoQ relay** that publishers push media to and subscribers pull media from.
31+
32+
```
33+
Publisher → Fishjam MoQ Relay → Subscriber(s)
34+
```
35+
36+
The relay is responsible for distributing the stream: it receives media from the publisher once and fans it out to every subscriber.
37+
38+
### The publish/subscribe model
39+
40+
MoQ uses a **publish/subscribe** model:
41+
42+
- A **publisher** connects to the relay, announces a stream under a specific path, and starts sending media.
43+
- **Subscribers** connect to the relay, discover announced paths, and receive the media.
44+
45+
The relay manages the flow between them. Neither side needs a direct connection to the other.
46+
47+
### Paths
48+
49+
Every stream is identified by a **path** — a slash-separated string like `my-room/alice-camera`. Paths are used in two distinct ways:
50+
51+
1. **Addressing** — a subscriber consumes an exact path to receive that specific stream (e.g. `my-room/alice-camera`).
52+
2. **Discovery** — a subscriber watches a prefix (e.g. `my-room`) to learn which streams are currently live under it. This returns a live feed of announced paths — each of which must then be consumed individually. This is how you can display all participants in a room without knowing their paths in advance.
53+
54+
Note that consuming an exact path and discovering a prefix are separate operations. Consuming `my-room` directly would fail unless a publisher is broadcasting at that exact path.
55+
56+
### Path Scoping
57+
58+
Every connection goes to `relay.fishjam.io/<fishjam-id>`. Your Fishjam ID is automatically used as the token's root namespace by the Fishjam Server — you never include it in `publishPath` or `subscribePath`; it is set for you. All paths you specify are **relative to that root**.
59+
60+
Path matching is **prefix-based**: a path of `"stream-name"` permits any broadcast whose full path starts with `stream-name/`, not just the exact string `"stream-name"`.
61+
62+
#### Publisher paths
63+
64+
The `publishPath` you set determines how much freedom the broadcaster has when naming their broadcast:
65+
66+
- **Broad path** (`publishPath: "stream-name"`) — the client can publish as any sub-path under `stream-name`, such as `stream-name/alice` or `stream-name/bob-camera`. The client chooses its own identity; the relay only enforces the prefix.
67+
- **Specific path** (`publishPath: "stream-name/alice"`) — the client can **only** publish as `stream-name/alice`. If the broadcaster tries to use `stream-name/bob`, the relay rejects the announcement. This is how you enforce a broadcaster's identity from the server side.
68+
69+
Use the broad form when clients self-identify (e.g., users pick their own stream name). Use the specific form when your backend assigns identities (e.g., you issue a per-user token for a managed conference).
70+
71+
#### Subscriber paths
72+
73+
The `subscribePath` works the same way: it is a prefix that limits which broadcasts the subscriber can consume and discover.
74+
75+
- **Broad path** (`subscribePath: "stream-name"`) — the subscriber can consume any broadcast under `stream-name/` and will surface all publishers in that namespace as they come and go.
76+
- **Specific path** (`subscribePath: "stream-name/alice"`) — the subscriber can only receive from `stream-name/alice`. Broadcasts at `stream-name/bob` are invisible to this client.
77+
78+
#### Example: a multi-publisher room
79+
80+
A typical room setup uses a combination of both patterns:
81+
82+
1. The backend issues each broadcaster a **specific** publisher token — `publishPath: "my-room/<user-id>"` — so each user can only occupy their own slot.
83+
2. The backend issues viewers a **broad** subscriber token — `subscribePath: "my-room"` — so they discover and consume every broadcast in the room.
84+
3. When a new publisher joins or leaves, the viewer is informed by the relay
85+
86+
## Access Control: MoQ Tokens
87+
88+
Access to the relay is controlled by **MoQ tokens** — short-lived JWTs that are path-scoped:
89+
90+
| Token type | Grants | Typical recipient |
91+
| ---------------- | ---------------------------------- | ----------------- |
92+
| Publisher token | Write access to a specific path | Streamer |
93+
| Subscriber token | Read access to a path or namespace | Viewer |
94+
95+
A token is attached to the relay URL as a query parameter (`?jwt=<token>`). The relay validates the token and enforces its scope before allowing any media to flow.
96+
97+
Keeping publisher and subscriber tokens separate ensures that a viewer can never accidentally publish to the stream, and a publisher cannot subscribe to paths it does not own.
98+
99+
## Getting Tokens
100+
101+
There are two ways to obtain MoQ tokens, depending on where you are in the development lifecycle.
102+
103+
### Sandbox API (prototyping)
104+
105+
The **Sandbox API** is a ready-made backend provided by Fishjam for development and prototyping. It issues tokens without requiring you to build your own server, so you can start streaming immediately.
106+
107+
To get a publisher token, call:
108+
109+
```
110+
GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{PUBLISHER-PATH}/publisher
111+
```
112+
113+
To get a subscriber token, call:
114+
115+
```
116+
GET https://fishjam.io/api/v1/connect/{FISHJAM_ID}/room-manager/moq/{SUBSCRIBER-PATH}/subscriber
117+
```
118+
119+
The Sandbox API is **not intended for production** — it has no authentication and is only available in the Sandbox environment. See [What is the Sandbox API?](./sandbox-api-concept) for more context.
120+
121+
### Fishjam Server SDK (production)
122+
123+
In production, your backend generates tokens using the **Fishjam Server SDK**. This gives you full control over who can publish and who can subscribe.
124+
125+
The SDK's `createMoqToken` method accepts either a `publishPath` or a `subscribePath`:
126+
127+
- `publishPath` — issues a publisher token scoped to that path.
128+
- `subscribePath` — issues a subscriber token scoped to that path or namespace prefix.
129+
130+
Your backend then delivers each token to the appropriate client (publisher or viewer), which uses it to connect to the relay.
131+
132+
See the [MoQ Streaming tutorial](../tutorials/moq) for working code examples of both approaches.
133+
134+
## See also
135+
136+
- [MoQ Streaming tutorial](../tutorials/moq) — step-by-step guide to publishing and subscribing
137+
- [What is the Sandbox API?](./sandbox-api-concept) — when and why to use the Sandbox API
138+
- [Security & Token Model](./security-tokens) — broader overview of Fishjam's token system
139+
- [Livestreams](./livestreams) — WebRTC-based livestreaming with WHIP/WHEP

0 commit comments

Comments
 (0)