このページは現在英語版のみで提供されており、日本語版も近日中に提供される予定です。ご利用いただきありがとうございます。

Audience Connection

Description of the Feature

The 'audience mic link' feature is a real-time interactive communication method. By using the audience mic link feature, hosts can interact in real time with up to 9 audience members, whether it's answering questions, sharing experiences, or engaging in entertainment interactions, all of which significantly enhance the audience's engagement and satisfaction. This direct interaction and communication provide a more convenient and efficient channel for commercial operations and also offer the audience a more personalized and customized shopping experience. The audience mic link feature is suitable for multiple scenarios, including e-commerce live streaming, entertainment live streaming, and online teaching.
Dual-person Mic Connection
Group Mic Connection







Use Instructions

Note:
This note introduces the audience mic connection feature in TUILiveKit. If you are not using TUILiveKit and are directly using LiveCoreView or RTCRoomEngine, you can skip this step and go directly to the Access Process or the corresponding API documentation.

Audience initiates join microphone application.

Click the co-mic request button
Choose the way to connect the microphone
Send a connection request and wait for the host to agree
After the host agrees, the connection is successful













The host handles the audience's mic connection requests.

Received the audience's connection request
Click on the connected mic user to open the connection dashboard
After clicking agree, the connection is successful










Access Process

Audience mic connection process

The TUILiveKit audience mic connection feature is mainly implemented through LiveCoreView. You can call the following API functions to implement the audience mic connection feature. As an example, Audience B requests to connect with Anchor A as follows.
Note:
The following are active call methods provided by LiveCoreView.
All callback methods refer to the callback methods in the ConnectionObserver object set by LiveCoreView.
In Flutter TUILiveKit, the audience mic connection feature is directly implemented through RTCRoomEngine. All Flutter-related content below is in TUILiveKit, calling methods provided by RTCRoomEngine to achieve the corresponding feature for your reference.

Audience sends a mic connection request

Audience B sends a mic connection request to Anchor A. Anchor A will receive the mic connection request from Audience B in the onUserConnectionRequest callback.
Android
iOS
Flutter
Kotlin
Java
val userId = "anchorUserId"; // Change to the UserId of the anchor. If an empty string is passed in, it defaults to the UserId of the anchor.
val timeout = 60;
liveCoreView.requestIntraRoomConnection(userId, timeout, null)
String userId = "anchorUserId"; // Change to the UserId of the anchor. If an empty string is passed in, it defaults to the UserId of the anchor.
int timeout = 60;
liveCoreView.requestIntraRoomConnection(userId, timeout, true, null);
Swift
OC
let timeout = 60
let userId = "anchorUserId" // Change to the UserId of the anchor. If an empty string is passed in, it defaults to the UserId of the anchor.
liveCoreView.requestIntraRoomConnection(userId: "", timeOut: timeOut, openCamera: true) {
} onError: { code, message in
}
NSInteger timeout = 60;
NSString userId = "anchorUserId" // Change to the UserId of the anchor. If an empty string is passed in, it defaults to the UserId of the anchor.
[liveCoreView requestIntraRoomConnection:""
timeOut:timeout
onSuccess:^(void) {
} onError:^(NSInteger code, NSString * _Nonnull message) {
}];
Dart
// File Location: Flutter/lib/service/impl/room_engine_service.dart

@override
TUIRequest takeSeat(int seatIndex, int timeout, TUIRequestCallback? requestCallback) {
return roomEngine.takeSeat(seatIndex, timeout, requestCallback);
}

The anchor receives the mic connection request

Anchor A will receive Audience B's mic connection request in the onUserConnectionRequest callback method.
Android
iOS
Flutter
Kotlin
Java
override fun onUserConnectionRequest(inviterUser: UserInfo) {
Log.i(TAG, "Received audience connection request: ${inviterUser.userId}")
}
@Override
public void onUserConnectionRequest(LiveStreamDefine.LiveUser inviterUser) {
Log.i(TAG, "Received audience connection request: " + inviterUser.userId);
}
Swift
OC
func onUserConnectionRequest(inviterUser: TUIUserInfo) {
print("Received audience connection request: \(inviterUser.userId)")
}
- (void)onUserConnectionRequest:(TUIUserInfo *)inviterUser {
NSLog(@"Received audience connection request: %@", hostUser.userId);
}
In Flutter, Anchor A will receive Audience B's mic connection request in the RTCRoomEngine's onRequestReceived callback.
Dart
// File Location: Flutter/lib/manager/observer/live_observer.dart

super.onRequestReceived = (request) {
LiveKitLogger.info("$tag onRequestReceived:[request:$request");
liveController.seatController.onRequestReceived(request);
};

Anchor responds to the mic connection request

After Anchor A receives Audience B's mic connection request, they can call respondIntraRoomConnection to respond to Audience B on whether the mic connection is accepted.
Android
iOS
Flutter
Kotlin
Java
// Anchor agrees to mic connection
liveCoreView.respondIntraRoomConnection(audienceBUserId, true, null)
// Anchor agrees to mic connection
liveCoreView.respondIntraRoomConnection(userId, true, null);

// Anchor rejects the mic connection
liveCoreView.respondIntraRoomConnection(userId, false, null);
Swift
OC
// Anchor agrees to mic connection
liveCoreView.respondIntraRoomConnection(userId: audienceBUserId, isAccepted: true) {
} onError: { code, message in
}
// Anchor agrees to mic connection
[liveCoreView respondIntraRoomConnection:audienceBUserId
isAccepted:YES
onSuccess:^(void) {
} onError:^(NSInteger code, NSString * _Nonnull message) {
}];
Dart
// File Location: Flutter/lib/service/impl/room_engine_service.dart

mTUIRoomEngine.responseRemoteRequest(requestId, true, new TUIRoomDefine.ActionCallback() {
@Override
public void onSuccess() {}

@Override
public void onError(TUICommonDefine.Error error, String message) {}
});

The audience receives the anchor's response callback

After Anchor A agrees to the co-broadcast request from Audience B, Audience B will receive Anchor A's agreement to co-broadcast through the onUserConnectionAccepted callback.
Android
iOS
Flutter
Kotlin
Java
override fun onUserConnectionAccepted(inviterUser: UserInfo) {
Log.i(TAG, "Audience agrees to connect:${inviterUser.userId}")
}
@Override
public void onUserConnectionAccepted(LiveStreamDefine.LiveUser liveUser) {
Log.i(TAG, "Audience agrees to connect:" + liveUser.userId);
}

@Override
public void onUserConnectionRejected(LiveStreamDefine.LiveUser liveUser) {
Log.i(TAG, "Audience rejects to connect:" + liveUser.userId);
}
Swift
OC
func onUserConnectionAccepted(userId: String) {
print("Audience agrees to connect: \(userId)")
}
- (void)onUserConnectionAccepted:(NSString *)userId {
NSLog(@"Audience agrees to connect: %@", userId);
}
In Flutter, the callback for the audience receiving the host's response to the mic connection request is provided by the takeSeat API's requestCallback. For specific examples, refer to the following code:
// File Location: Flutter/lib/manager/controller/seat_controller.dart

TUIRequest request = liveService.takeSeat(
index,
timeout,
TUIRequestCallback(
onAccepted: (String requestId, String userId) { // connection request
},
onRejected: (String requestId, String userId, String message) { // connection request rejected
},
},
onCancelled: (String requestId, String userId) { // connection request cancell
},
onTimeout: (String requestId, String userId) { // Mic connection request timed ou
},
onError: (String requestId, String userId, TUIError error, String message) { // Error callback
},
));

Callback for changes in the list of co-broadcasting users

After Host A agrees to the co-broadcast request from Audience B, LiveCoreView will send notifications to both Host A and Audience B about the changes in co-broadcasting users.
Android
iOS
Flutter
Kotlin
Java
override fun onConnectedUsersUpdated(inviterUser: UserInfo) {
Log.i(TAG, "Callback for changes in the list of co-broadcasting user")
}
@Override
public void onConnectedUsersUpdated(List<UserInfo> userList, List<UserInfo> joinList, List<UserInfo> leaveList) {
Log.i(TAG, "Callback for changes in the list of co-broadcasting user");
}
Swift
OC
func onConnectedUsersUpdated(userList: [TUIUserInfo], joinList: [TUIUserInfo], leaveList: [TUIUserInfo]) {
print("Callback for changes in the list of co-broadcasting user")
}
- (void)onConnectedUsersUpdated:(NSArray<TUIUserInfo *> *)userList
joinList:(NSArray<TUIUserInfo *> *)joinList
leaveList:(NSArray<TUIUserInfo *> *)leaveList {
NSLog(@"Callback for changes in the list of co-broadcasting user");
}
// File Location: Flutter/lib/manager/observer/live_observer.dart

super.onSeatListChanged = (seatList, seatedList, leftList) {
LiveKitLogger.info(
"$tag($hashCode) onSeatListChanged:[seatList:$seatList ,seatedList:$seatedList,leftList:$leftList]");
liveController.target?.seatController.onSeatListChanged(seatList, seatedList, leftList);
};

Process of disconnecting audio connection

After the audience successfully connects, the host hangs up the mic connection

After Audience B and Host A successfully connect, Host A disconnects the mic connection with Audience.
Android
iOS
Flutter
Kotlin
Java
val userId = "audienceBUserId"
liveCoreView.disconnectUser(userId, null)
String userId = "audienceUserId";
liveCoreView.disconnectUser(userId, null);
Swift
OC
let userId = "audienceBUserId"
liveCoreView.disconnectUser(userId: userId) {
} onError: { code, message in
}
NSString *userId = @"audienceBUserId";
[liveCoreView disconnectUser:userId
onSuccess:^{
} onError:^(NSInteger code, NSString * _Nonnull message) {
}];
Dart
// File Location: Flutter/lib/service/impl/room_engine_service.dart

mLiveService.kickUserOffSeatByAdmin(0, userId, new TUIRoomDefine.ActionCallback() {
@Override
public void onSuccess() {}

@Override
public void onError(TUICommonDefine.Error error, String message) {}
});

The audience receives a callback when the host disconnects the interactive connection.

After Host A disconnects the mic connection with Audience B, Audience B will receive the onUserConnectionTerminated callback.
Android
iOS
Flutter
Kotlin
Java
override fun onUserConnectionTerminated(inviterUser: UserInfo) {
Log.i(TAG, "Host closes the connection")
}
@Override
public void onUserConnectionTerminated() {
Log.i(TAG, "Host closes the connection");
}
Swift
OC
func onUserConnectionTerminated() {
print("Host closes the connection")
}
- (void)onUserConnectionTerminated {
NSLog(@"Host closes the connection");
}
In Flutter, after Anchor A disconnects the mic connection request with Audience B, Audience B will receive a notification in the RTCRoomEngine's onKickedOffSeat callback.
// File Location: Flutter/lib/manager/observer/live_observer.dart

super.onKickedOffSeat = (seatIndex, userInfo) {
LiveKitLogger.info("$tag($hashCode) onKickedOffSeat:[seatIndex:$seatIndex,userInfo:$userInfo");
liveController.target?.seatController.onKickedOffSeat(seatIndex, userInfo);
};

After the audience successfully connects, the audience ends the mic connection

After Audience B successfully connects with Anchor A, Audience B can actively disconnect by calling terminateIntraRoomConnection.
Android
iOS
Flutter
Kotlin
Java
liveCoreView.terminateIntraRoomConnection()
liveCoreView.terminateIntraRoomConnection();
Swift
OC
liveCoreView.terminateIntraRoomConnection()
[liveCoreView terminateIntraRoomConnection]
Dart
// File Location: Flutter/lib/service/impl/room_engine_service.dart

mLiveService.leaveSeat(new TUIRoomDefine.ActionCallback() {
@Override
public void onSuccess() {}

@Override
public void onError(TUICommonDefine.Error error, String message) {}
});

The anchor receives a callback when an audience member disconnects.

When Audience B actively disconnects the mic, the anchor will receive the onUserConnectionExited callback.
Android
iOS
Flutter
Kotlin
Java
override fun onUserConnectionExited(inviterUser: LiveStreamDefine.LiveUser) {
Log.i(TAG, "Audience exits the connection")
}
@Override
public void onUserConnectionExited(UserInfo liveUser) {
Log.i(TAG, "Audience exits the connection:${liveUser.userId}");
}
Swift
OC
func onUserConnectionExited(userInfo: TUIUserInfo) {
print("Audience exits the connection")
}
- (void)onUserConnectionExited:(TUIUserInfo *)userInfo {
NSLog(@"Audience exits the connection");
}
In Flutter, you can check the audience who disconnected from the mic in the leftList provided by the onSeatListChanged callback.
// File Location: Flutter/lib/manager/observer/live_observer.dart

super.onSeatListChanged = (seatList, seatedList, leftList) {
LiveKitLogger.info(
"$tag($hashCode) onSeatListChanged:[seatList:$seatList ,seatedList:$seatedList,leftList:$leftList]");
liveController.target?.seatController.onSeatListChanged(seatList, seatedList, leftList);
};
Note:
The connection feature is implemented based on LiveCoreView. If you need to extend the connection feature, please refer to the LiveCoreView documentation.

Mic Connection Sequence Diagram