Stream a single participant's video
By default, Realtime Media Streams (RTMS) sends the video data of the active speaker. If your app needs to track a specific participant, you can switch to individual stream mode. In this mode, you choose which participant's video to receive and can change that selection at any time during the meeting.
Note
Only one individual video stream can be active at a time. Subscribing to a new participant automatically unsubscribes from the previous one.
Prerequisites
Complete the Working with streams flow through Step 3: App establishes signaling connection before configuring individual video streams.
Step 1: Configure the media handshake request
When sending the media handshake request, set data_opt to 4 (VIDEO_SINGLE_INDIVIDUAL_STREAM) in the video media parameters. This tells the RTMS server that your app will manage video subscriptions manually rather than receiving the active speaker automatically.
{
"msg_type": 3,
"protocol_version": 1,
"meeting_uuid": "your_meeting_uuid",
"rtms_stream_id": "your_rtms_stream_id",
"signature": "your_signature",
"media_type": 2,
"media_params": {
"video": {
"codec": 5,
"resolution": 2,
"data_opt": 4,
"fps": 25
}
}
}
No video data is sent until you subscribe to a participant.
Step 2: Subscribe to participant video events
Once the stream is active, subscribe to PARTICIPANT_VIDEO_ON (event type 8) and PARTICIPANT_VIDEO_OFF (event type 9) events using the Subscribe to events message. These events tell your app which participants have their cameras on and are available to subscribe to.
{
"msg_type": 18,
"event_type": [8, 9]
}
Step 3: Receive participant video events
When a participant turns their camera on, the signaling connection sends a participant video on event. Use the user_id from this event to send a video subscription request in the next step.
{
"msg_type": 6,
"event": {
"event_type": 8,
"timestamp": 1727384349123,
"participants": [
{
"user_id": 16778240
}
]
}
}
When a participant turns their camera off, the signaling connection sends a participant video off event. If your app is currently subscribed to that participant, no further video data will arrive until you subscribe to a different participant.
{
"msg_type": 6,
"event": {
"event_type": 9,
"timestamp": 1727384349123,
"participants": [
{
"user_id": 16778240
}
]
}
}
Step 4: Subscribe to a participant's video stream
Send a video subscription request through the signaling connection with the user_id of the participant you want to receive video from. Set subscribe to true to start receiving video from that participant, or false to stop.
{
"msg_type": 28,
"user_id": 16778240,
"subscribe": true,
"timestamp": 1738392033699
}
The signaling connection responds with a video subscription response. A status_code of 0 means the subscription was successful and video data will begin arriving on the media connection.
{
"msg_type": 29,
"user_id": 16778240,
"status_code": 0,
"reason": "OK",
"timestamp": 1738392033699
}
Step 5: Switch to a different participant
To switch the video stream to a different participant, send a new video subscription request with the new participant's user_id. You do not need to unsubscribe from the current participant first, the RTMS server handles this automatically when the new subscription request arrives.
{
"msg_type": 28,
"user_id": 98765432,
"subscribe": true,
"timestamp": 1738392099000
}
Step 6: Unsubscribe from a participant's video stream
To stop receiving video without subscribing to a different participant, send a video subscription request with subscribe set to false. No video data will be sent until you send a new subscription request.
{
"msg_type": 28,
"user_id": 16778240,
"subscribe": false,
"timestamp": 1738392099000
}
Handling video gaps
When there is no active individual subscription — such as after a participant turns off their camera or you have explicitly unsubscribed — the RTMS server sends no video data. If your app is recording the meeting for playback, insert filler frames during these gaps when muxing video with audio. Use timestamps from audio packets to determine the duration of each gap. For more information, see Combining media data.