Join Flow
This document specifies how a Proctor joins a Sentinel’s video stream.
Overview
When a Proctor wants to view a Sentinel’s screen, it must:
- Request to join the stream
- Receive the initialization segment
- Receive a join fragment (IDR entry point)
- Continue receiving live fragments
See Terminology for the distinction between fragments (live delivery units) and join fragments (keyframe entry points).
Join Flow Diagram
Step-by-Step
Proctor Sends Join Request
The Proctor sends a message over WebSocket requesting to join a specific Sentinel’s stream.
Required fields:
| Field | Type | Description |
|---|---|---|
sentinelId | string | The Sentinel to subscribe to |
Optional fields:
| Field | Type | Description |
|---|---|---|
startFrom | string | "oldest" (default) or "latest" |
Server Validates and Looks Up
The Server:
- Validates the Proctor is authorized to view the Sentinel
- Checks if the Sentinel is currently streaming
- Locates the session data in memory
If the Sentinel is not streaming, the Server responds with an error.
Server Sends Initialization Segment
The Server sends the cached initialization segment for the Sentinel’s current session.
Required fields:
| Field | Type | Description |
|---|---|---|
sentinelId | string | Identifies the stream |
sessionId | string | Current session identifier |
data | bytes | Raw fMP4 initialization segment |
Server Sends Join Fragment
The Server selects a join fragment from the memory buffer and sends it.
Selection strategy:
startFrom | Join Fragment Selected |
|---|---|
"oldest" | Oldest join fragment in buffer (maximum catch-up time) |
"latest" | Most recent join fragment (lowest latency) |
The selected fragment is guaranteed to start with an IDR keyframe (join fragment).
Required fields:
| Field | Type | Description |
|---|---|---|
sentinelId | string | Identifies the stream |
sequence | integer | Fragment sequence number |
data | bytes | Raw fMP4 fragment (moof + mdat) |
Server Continues Pushing Fragments
From this point, the Server pushes new fragments to the Proctor as they arrive from the Sentinel.
Server-Initiated Keyframe for Fast Join
If a Proctor joins and there is no recent join fragment in the buffer, the Server requests an on-demand keyframe from the Sentinel.
See Control Messages for the keyframe request flow.
With a server-initiated keyframe:
Instant Preview (UX Strategy)
For carousel-style switching, the Proctor can join the next stream ~5 seconds early so video is already flowing before the user switches.
This is a UX optimization only. It does not introduce new protocol messages or change Server behavior.
Switching Streams
When a Proctor switches from one Sentinel to another:
Unsubscribe from Current Stream
Proctor notifies Server to stop sending fragments for the current Sentinel.
Join New Stream
Follow the standard join flow for the new Sentinel.
Reset MSE Buffer
In the browser, the Proctor must:
- Clear the existing
SourceBuffer - Append the new initialization segment
- Begin appending fragments from the new stream
Error Handling
| Condition | Server Response |
|---|---|
| Sentinel not found | Error: unknown Sentinel |
| Sentinel not streaming | Error: Sentinel offline |
| Authorization failure | Error: not authorized |
| No join fragment in buffer | Send initialization segment, request/await next join fragment |
Latency Considerations
| Factor | Impact on Join Latency |
|---|---|
| Buffer has join fragments | Immediate join (send from buffer) |
| Server requests keyframe | Wait for next capture cycle |
| No join fragment available | Up to max keyframe interval (20-30s) unless server requests a keyframe |
For lowest latency joins:
- Use
startFrom: "latest" - Keep recent join fragments in memory