Skip to main content

Starting March 27, 2026, RC is rebranded as Nexconn. Existing RC SDK customers can continue using this documentation. New customers should refer to the Nexconn developer documentation.

Cross-Room Co-Streaming

In cross-room co-streaming, it's essential to distinguish between the primary room and secondary room. These concepts are relative and defined as follows:

  • Primary Room: The room initially joined by the local user.
  • Secondary Room: After a co-streaming invitation is accepted, both parties must join each other's rooms.

Before initiating cross-room co-streaming, both users must have joined their respective primary rooms. Co-streaming cannot proceed if either user hasn't joined their primary room.

Handling Co-Streaming Invitations

To establish co-streaming, one host sends an invitation, and the other responds by accepting or rejecting it.

Sending an Invitation

To send a cross-room co-streaming request, call the RCRTCEngine object's requestJoinSubRoom method. Upon successful delivery, the invitee will receive a notification via the onJoinSubRoomRequestReceived callback.

Future<int> requestJoinSubRoom(String roomId, String userId, [bool autoLayout = true, String? extra]);
ParameterTypeDescription
roomIdStringTarget room ID
userIdStringTarget user ID
autoLayoutboolWhether to use floating layout. If true, the server merges the invitee's streams into the inviter's view after successful room joining (default: floating layout only). If the invitee hasn't published streams, merging occurs upon publication. Regardless of autoLayout, both parties can manually set layouts using setLiveMixCustomLayouts. Once manually configured, subsequent auto-layout parameters become invalid. Default: true.
extraStringAdditional information
// Callback for inviting others to co-stream
engine.onJoinSubRoomRequested = (roomId, userId, code, message) {
if (code == 0) {
// Invitation sent successfully, awaiting response
} else {
// Failed to send invitation
}
};
// Invite another user to co-stream
engine.requestJoinSubRoom(roomId, userId);

Responding to an Invitation

When an invitation is received, the SDK triggers the RCRTCEngine object's onJoinSubRoomRequestReceived callback. The invitee must respond by either accepting or rejecting.

  • To accept, call responseJoinSubRoomRequest with agree set to true, then join the secondary room via joinSubRoom.
  • To reject, call responseJoinSubRoomRequest with agree set to false.
Future<int> responseJoinSubRoomRequest(String roomId, String userId, bool agree, [bool autoLayout = true, String? extra]);
ParameterTypeDescription
roomIdStringTarget room ID
userIdStringTarget user ID
autoLayoutBoolSame as above
extraStringAdditional information

After responding, the local user receives confirmation via onJoinSubRoomRequestResponded, while the inviter gets notified via onJoinSubRoomRequestResponseReceived.

  • If accepted, all non-audience users (except the invitee) in both rooms receive onJoinSubRoomRequestResponseReceived.
  • If rejected, only the inviter receives the rejection callback.
// Callback for received co-stream invitations
engine.onJoinSubRoomRequestReceived = (String roomId, String userId, String? extra) {
// Callback after accepting
engine.onJoinSubRoomRequestResponded = (String roomId, String userId, bool agree, int code, String? errMsg) {
if (code == 0) {
// Acceptance confirmed
} else {
// Failed to accept
}
};

// Accept the invitation
engine.responseJoinSubRoomRequest(roomId, userId, true);
};

Canceling an Invitation

If an inviter wishes to retract an invitation, call RCRTCEngine's cancelJoinSubRoomRequest method. The invitee will receive onCancelJoinSubRoomRequestReceived.

Future<int> cancelJoinSubRoomRequest(String roomId, String userId, [String? extra]);
ParameterTypeDescription
roomIdStringTarget room ID
userIdStringTarget user ID
// Callback for canceled invitations
engine.onJoinSubRoomRequestCanceled = (String roomId, String userId, int code, String? errMsg) {
if (code == 0) {
// Successfully canceled
} else {
// Failed to cancel
}
};

// Cancel the invitation
engine.cancelJoinSubRoomRequest(roomId, userId);

Joining Secondary Rooms

After accepting an invitation, both parties must join each other's rooms. Relative to the local user's primary room, the other room becomes a secondary room. Join via:

Future<int> joinSubRoom(String roomId);

Timing differs for inviters and invitees:

  • Invitee: After accepting (responseJoinSubRoomRequest with agree=true), call joinSubRoom.
  • Inviter: Upon receiving acceptance (onJoinSubRoomRequestResponseReceived), call joinSubRoom. This triggers onSubRoomJoined, onSubRoomBanded, and onUserJoined.
// Callback for joining secondary rooms
engine.onSubRoomJoined = (String roomId, int code, String? errMsg) {
if (code == 0) {
// Successfully joined
} else {
// Failed to join
}
}

// Join the secondary room
engine.joinSubRoom(roomId);

For multi-host scenarios:

  • Scenario A: If secondary rooms exist before joining the primary room, receive onSubRoomBanded after joinRoom, then optionally join those rooms.

    // Callback for pre-existing secondary rooms
    Function(String roomId)? onSubRoomBanded;
  • Scenario B: If another host initiates co-streaming after local joining, receive onSubRoomBanded to optionally join new secondary rooms.

Subscribing to Streams

After joining a secondary room, subscribe to its hosts' streams via:

  1. Direct subscription using subscribe (see Subscribing to Streams).

    engine.onSubscribed = (String id, RCRTCMediaType type, int code, String? message) {
    if (code == 0) {
    // Subscription successful
    } else {
    // Subscription failed
    }
    };

    engine.subscribe(userId, RCRTCMediaType.video);
  2. Automatic subscription via onRemotePublished when streams become available.

    engine.onRemotePublished = (String roomId, String userId, RCRTCMediaType type) {
    engine.subscribe(userId, type);
    }

To unsubscribe, use unsubscribe (see Unsubscribing).

Temporarily Pausing Co-Streaming

To pause co-streaming without ending it, leave the secondary room via leaveSubRoom with disband=false. This triggers onSubRoomLeft locally and onUserLeft for others, who may then unsubscribe.

// Callback for leaving
engine.onSubRoomLeft = (roomId, code, message) {
if (code == 0) {
// Successfully left
} else {
// Failed to leave
}
}

// Pause co-streaming
engine.leaveSubRoom(roomId, false);

The server automatically removes paused streams from the mix. To resume, rejoin the secondary room without re-invitation.

Ending Co-Streaming

To fully end co-streaming, call leaveSubRoom with disband=true. This unsubscribes from all streams and triggers onSubRoomLeft locally and onSubRoomDisband for others.

// Callbacks
Function(String roomId, int code, String? errMsg)? onSubRoomLeft;
Function(String roomId, String userId)? onSubRoomDisband;

Server-Initiated Room Removal

tip

Use server APIs to remove users from specific rooms.

  • Before removal, notify the client via IM to properly end co-streaming.

  • If removed from the primary room, receive onKicked. The SDK automatically leaves all rooms and cleans up resources.

  • If removed from a secondary room, receive onKicked and automatically leave that room while unsubscribing.

    // Callback for server-initiated removal
    Function(String? roomId, String? errMsg)? onKicked;