sequenceDiagram
accTitle: MoQ session setup and first subscription delivery
accDescr: After transport establishment, client and relay each send SETUP on their own control stream. The client opens a bidirectional request stream for SUBSCRIBE, the relay answers SUBSCRIBE_OK there, and sends objects on separate subgroup streams.
participant C as Client
participant R as Relay
Note over C,R: Transport established with compatible MoQ version
C->>R: Client control stream: SETUP
R->>C: Relay control stream: SETUP
C->>R: New request stream: SUBSCRIBE track
R->>C: Same request stream: SUBSCRIBE_OK
R->>C: Separate subgroup stream: objects
R->>C: Another subgroup stream: more objects
Chapter 04
Publishing and Subscribing
On this page
A subscription asks another endpoint to send objects from a named track. Alice wants to hear the lecture, so her player subscribes to its audio track.
We’ll follow Alice as she connects, finds the lecture, asks for audio, and joins the video partway through. Then we’ll see how she ends a subscription when she leaves.
Establishing a session
Alice’s player and the relay first agree on a MoQ session. The session holds the settings and request state they need to exchange content over their transport connection.
In MOQT draft-21, version selection happens during transport establishment. Native QUIC uses ALPN, a handshake field identifying the application protocol; WebTransport uses its protocol negotiation header. The identifier for this edition’s draft is moqt-21. The network can be reachable while session setup fails because the endpoints have no protocol version in common. See §6.2.
Each endpoint opens a control stream and starts it with SETUP, exchanging session options and supported extensions. Each control stream is unidirectional: only the endpoint that opened it sends on it. A request such as SUBSCRIBE uses a separate bidirectional stream, so the other endpoint can answer on that same stream. Objects travel separately from these request messages.
The implementation can overlap some of this work. Requests and data may be sent while initialization is still underway. The draft recommends buffering early arrivals until setup completes, but permits an endpoint to reset early request streams if it cannot support or does not want to buffer them. The endpoint need not wait for a reply at each step before starting the next. See §6.3.
From a connection to the first object
This sequence follows a direct-QUIC session after its transport handshake. The browser path first establishes a WebTransport session. Stream labels describe their jobs, not numeric QUIC stream IDs.
This client already knows the track name, so it can subscribe without discovery. The diagram shows setup first to make it easier to follow; requests and data can also arrive during setup, as described above. The SUBSCRIBE_OK reply accepts the subscription, and the objects travel on separate data streams. See draft-21 §6.4.
Finding the lecture
Before asking for media, the application must turn Alice’s choice into track names. The lecture page might already contain a publication name, or it might use namespace discovery to find available publishers. The application can use discovery results to build a room list or public directory.
Once it finds the publication, the player reads its media description. This tells it which tracks contain audio and which contain video renditions: alternative encodings, such as low-resolution and high-resolution video. Alice’s player can start by choosing audio and a low-resolution rendition. We will examine that media description in the browser chapter.
Discovery and delivery can have different access rules. A private lecture might be hidden from the room list as well as unavailable for playback. Knowing its name does not grant permission to receive it. MOQT provides namespace discovery mechanisms; the service supplies the access policy.
Asking for audio
Alice’s player sends SUBSCRIBE, naming the lecture’s audio track and specifying its delivery choices. The relay answers with SUBSCRIBE_OK if it accepts, or REQUEST_ERROR if it rejects the request. Acceptance establishes the subscription. Audio objects arrive separately from the request and response messages.
What if the relay isn’t receiving the lecture yet? It needs to find the publisher and make its own subscription. The relay can learn where the publisher is from registration, configuration, or discovery. In the example below, the relay already knows where the publisher is, and both subscriptions ask for compatible delivery settings.
sequenceDiagram
accTitle: A viewer subscribes through a relay
accDescr: Alice subscribes to audio at the relay. The relay obtains an upstream subscription from the publisher, accepts Alice's request, and forwards audio objects.
participant A as Alice
participant R as Relay
participant P as Publisher
A->>R: SUBSCRIBE audio
R->>P: SUBSCRIBE audio
P-->>R: SUBSCRIBE_OK
R-->>A: SUBSCRIBE_OK
P->>R: Audio objects
R->>A: Audio objects
There are now two subscriptions: Alice’s request to the relay, and the relay’s request to the publisher. The relay receives the audio on one connection and forwards it on the other. If it was already receiving the lecture, it could reuse that content instead of asking the publisher again.
Now Bob opens the same lecture and asks for the same audio. The relay can reuse its upstream content while maintaining a separate downstream subscription for Bob. If Alice leaves, Bob still needs that content. If both leave, and no recorder or other consumer remains, the relay can cancel its upstream request. This is how a relay combines demand without making every viewer share one connection. See §7.
The publisher can initiate a subscription too, by offering a track with PUBLISH. The receiver accepts with REQUEST_OK—called PUBLISH_OK when accepting a publication in this draft—or rejects with REQUEST_ERROR. A relay must already know the client is interested in and authorized for that content. Either direction of initiation establishes the same kind of subscription. See §3.1.
Joining video in the middle
Audio is arriving, and Alice’s player also requests video. The publisher is halfway through group 42. In our example, the group’s first object contains a keyframe and the later frames depend on earlier pictures. Receiving only the next new frame may therefore leave Alice with bytes she cannot decode.
The player can retrieve the beginning of group 42 while following new objects, or wait for the next independent group. The first choice can start playback sooner if the missing content is available and quick to deliver. The second avoids catching up through the current group, but waits for a new decoding starting point.
A fetch asks for a bounded portion of a track. In draft-21, the publisher answers a standalone FETCH with FETCH_OK or REQUEST_ERROR. If it accepts, it sends the objects on a separate data stream and ends that stream when delivery is complete. See §3.2.1.
For Alice’s first choice, draft-21 also allows FILL_PARAMETERS on the subscription. These request a bounded fill range on a fetch stream alongside ongoing subscription delivery. The ranges can overlap, so the player must handle duplicate objects; pairing a fill through the largest known object with a subscription starting at the next object avoids that overlap. For the second choice, a location filter can start delivery at the next group. A location is a group ID and object ID: a position in the track, rather than a clock reading. See fill ranges (§3.4) and location filters (§3.3.1).
flowchart TD
accTitle: Two ways to join a video track
accDescr: Alice joins during group 42. She can retrieve its earlier objects and follow new ones, or wait for the independently decodable group 43. Either route needs codec configuration before decoding.
J["Alice joins during group 42"] --> C["Retrieve earlier objects in group 42"]
J --> W["Wait for group 43"]
C --> F["Combine with ongoing delivery"]
W --> K["Receive group 43 from its keyframe"]
F --> D["Decode with the codec configuration"]
K --> D
Alice has a wait either way: time to download the start of group 42, or time for the publisher to produce group 43’s keyframe.
Both choices depend on the media format identifying usable starting points. Switching from low-resolution to high-resolution video raises the same question: where can the decoder begin using the new rendition?
Fetching also depends on retention. The relay may have discarded the beginning of group 42, or never received it. To offer a “rewind 30 seconds” button, the service must retain enough content and map playback time to track locations. The player can then translate the requested time into a fetch range.
Ending a subscription
When Alice disables video, her player should cancel the video subscription while leaving audio active. Otherwise, the relay continues doing work she no longer needs.
In draft-21, cancellation abruptly closes the request stream’s open directions. STOP_SENDING asks the peer to stop its sending direction; RESET_STREAM abandons the cancelling endpoint’s own sending direction. A plain FIN only means that no more bytes will be sent in one direction. A subscriber can finish sending request messages while still expecting content, so FIN alone does not cancel the request. See §6.4.2.2–3.
When the publisher ends an established subscription, it closes the associated data streams, sends PUBLISH_DONE, and closes its request-stream direction. The data streams and request stream can arrive in different orders. Alice may therefore receive PUBLISH_DONE while some final object data is still on its way. See §3.1.1 and §9.9.
Subscription lifetime also matters to authorization. If Alice’s permission expires during the lecture, the service needs a policy for the subscription she already holds, as well as for any new request. Publication permission is separate: allowing Alice to watch must not allow her to replace the lecturer’s content.
What happens after a disconnect?
If Alice loses the session, opening a new connection is only the first recovery step. Her player needs to establish a new session, make its requests again, and choose a usable place to resume. If the relay still has the missing objects, the player may recover them; if they are gone or too old for live playback, it needs a newer decoding starting point.
A planned shutdown gives the endpoints more time. Draft-21 defines GOAWAY so an endpoint can announce that its session will close; a server can also suggest a new session URI. The client still has to establish the replacement session. See graceful session migration (§6.6.1).