Audience Connection
功能介绍
观众连麦功能是一种实时互动交流方式,通过观众连麦功能,主播可以与多达9个观众进行实时互动,无论是解答问题、分享经验还是进行娱乐互动,都能极大地提升观众的参与感和满意度。这种直接的互动和交流为商业化运营提供了更加便捷和高效的渠道,同时也为观众提供了更加个性化和定制化的购物体验。观众连麦功能适用于多个场景,包括电商直播、娱乐直播、在线教学等。
单人连麦 | 多人连麦 |
| |
使用说明
说明:
此说明介绍在TUILiveKit中的观众连麦功能使用说明,如您未使用TUILIveKit而直接使用了LIveCoreView 或 RTCRoomEngine,可忽略此步骤,直接跳转至接入流程或相应的API文档。
观众发起连麦申请
点击连麦请求按钮 | 选择连麦方式 | 发送连麦请求,等待主播同意 | 主播同意后,连麦成功 |
| | | |
主播处理观众连麦请求
收到观众的连麦请求 | 点击连麦用户,打开连麦面板 | 点击同意后,连麦成功 |
| | |
接入流程
观众连麦流程
TUILiveKit 观众连麦功能 主要是通过 LiveCoreView 实现(除Flutter),您可以调用如下 API 函数,实现观众连麦功能。以观众 B 申请和主播 A 连麦为例实现如下。
说明:
以下是由 LiveCoreView 提供的主动调用方法。
所有的回调方法是指 LiveCoreView 设置的 ConnectionObserver 对象中的回调方法。
在Flutter TUILiveKit中,观众连麦功能直接通过RTCRoomEngine实现。以下所有Flutter相关内容在是TUILiveKit中,调用由RTCRoomEngine提供的方法以实现对应功能供您参考。
观众发送连麦请求
观众 B 给主播 A 发送连麦请求。
val userId = "anchorUserId"; // 修改为房主的UserId,传入空字符串时默认为房主UserIdval timeout = 60;liveCoreView.requestIntraRoomConnection(userId, 10, null)
String userId = "anchorUserId"; // 修改为房主的UserId,传入空字符串时默认为房主UserIdint timeout = 60;liveCoreView.requestIntraRoomConnection(userId, timeout, true, null);
let timeout = 60let userId = "anchorUserId" // 修改为房主的UserId,传入空字符串时默认为房主UserIdliveCoreView.requestIntraRoomConnection(userId: "", timeOut: timeOut, openCamera: true) {} onError: { code, message in}
NSInteger timeout = 60;NSString userId = "anchorUserId" // 修改为房主的UserId,传入空字符串时默认为房主UserId[liveCoreView requestIntraRoomConnection:""timeOut:timeoutonSuccess:^(void) {} onError:^(NSInteger code, NSString * _Nonnull message) {}];
// 文件位置:Flutter/lib/service/impl/room_engine_service.dart@overrideTUIRequest takeSeat(int seatIndex, int timeout, TUIRequestCallback? requestCallback) {return roomEngine.takeSeat(seatIndex, timeout, requestCallback);}
主播端收到连麦请求
主播 A 会在 onUserConnectionRequest 回调方法中收到 观众B 的连麦请求。
override fun onUserConnectionRequest(inviterUser: UserInfo) {Log.i(TAG, "收到观众连线请求:${inviterUser.userId}")}
@Overridepublic void onUserConnectionRequest(LiveStreamDefine.LiveUser inviterUser) {Log.i(TAG, "收到观众连线请求:" + inviterUser.userId);}
func onUserConnectionRequest(inviterUser: TUIUserInfo) {print("收到观众连线请求:\(inviterUser.userId)")}
- (void)onUserConnectionRequest:(TUIUserInfo *)inviterUser {NSLog(@"收到观众连线请求:%@", hostUser.userId);}
在Flutter中,主播 A 会在
RTCRoomEngine
的onRequestReceived
回调中收到观众 B 的连麦请求。// 文件位置:Flutter/lib/manager/observer/live_observer.dartsuper.onRequestReceived = (request) {LiveKitLogger.info("$tag onRequestReceived:[request:$request");liveController.seatController.onRequestReceived(request);};
主播响应连麦请求
主播 A 收到观众的连麦请求后,可以调用 respondIntraRoomConnection 响应观众 B 是否同意连麦。
// 主播同意连麦liveCoreView.respondIntraRoomConnection(audienceBUserId, true, null)
// 主播同意连麦liveCoreView.respondIntraRoomConnection(userId, true, null);// 主播拒绝连麦liveCoreView.respondIntraRoomConnection(userId, false, null);
// 主播同意连麦liveCoreView.respondIntraRoomConnection(userId: audienceBUserId, isAccepted: true) {} onError: { code, message in}
// 主播同意连麦[liveCoreView respondIntraRoomConnection:audienceBUserIdisAccepted:YESonSuccess:^(void) {} onError:^(NSInteger code, NSString * _Nonnull message) {}];
// 文件位置:Flutter/lib/service/impl/room_engine_service.dartmTUIRoomEngine.responseRemoteRequest(requestId, true, new TUIRoomDefine.ActionCallback() {@Overridepublic void onSuccess() {}@Overridepublic void onError(TUICommonDefine.Error error, String message) {}});
观众收到主播响应回调
主播 A 同意观众 B 连麦请求后, 观众 B 会通过 onUserConnectionAccepted 回调收到主播 A 同意连麦的回调。
override fun onUserConnectionAccepted(inviterUser: UserInfo) {Log.i(TAG, "观众同意连线:${inviterUser.userId}")}
@Overridepublic void onUserConnectionAccepted(LiveStreamDefine.LiveUser liveUser) {Log.i(TAG, "观众同意连线:" + liveUser.userId);}@Overridepublic void onUserConnectionRejected(LiveStreamDefine.LiveUser liveUser) {Log.i(TAG, "观众拒绝连线:" + liveUser.userId);}
func onUserConnectionAccepted(userId: String) {print("观众同意连线:\(userId)")}
- (void)onUserConnectionAccepted:(NSString *)userId {NSLog(@"观众同意连线:%@", userId);}
在Flutter中,观众收到主播响应连麦申请的回调由
takeSeat
接口中的requestCallback
给出。具体示例可以参考以下代码:// 文件位置:Flutter/lib/manager/controller/seat_controller.dartTUIRequest request = liveService.takeSeat(index,timeout,TUIRequestCallback(onAccepted: (String requestId, String userId) { // 连麦申请被同意},onRejected: (String requestId, String userId, String message) { // 连麦申请被拒绝},onCancelled: (String requestId, String userId) { // 连麦申请取消},onTimeout: (String requestId, String userId) { // 连麦申请超时},onError: (String requestId, String userId, TUIError error, String message) { // 错误回调},));
连麦用户列表发生变化的回调
主播 A 同意观众 B 连麦请求后, LiveCoreView 会同时给主播 A 和观众 B 发送连麦用户发生变化。
override fun onConnectedUsersUpdated(inviterUser: UserInfo) {Log.i(TAG, "连麦用户列表发生变化")}
@Overridepublic void onConnectedUsersUpdated(List<UserInfo> userList, List<UserInfo> joinList, List<UserInfo> leaveList) {Log.i(TAG, "连麦用户列表发生变化");}
func onConnectedUsersUpdated(userList: [TUIUserInfo], joinList: [TUIUserInfo], leaveList: [TUIUserInfo]) {print("连麦用户列表发生变化")}
- (void)onConnectedUsersUpdated:(NSArray<TUIUserInfo *> *)userListjoinList:(NSArray<TUIUserInfo *> *)joinListleaveList:(NSArray<TUIUserInfo *> *)leaveList {NSLog(@"连麦用户列表发生变化"); // 如果需要,您可以在这里处理 userList、joinList 和 leaveList}
// 文件位置:Flutter/lib/manager/observer/live_observer.dartsuper.onSeatListChanged = (seatList, seatedList, leftList) {LiveKitLogger.info("$tag($hashCode) onSeatListChanged:[seatList:$seatList ,seatedList:$seatedList,leftList:$leftList]");liveController.target?.seatController.onSeatListChanged(seatList, seatedList, leftList);};
断开连麦流程
观众连麦成功后,主播挂断观众的连麦
观众 B 和主播 A 连麦成功后,主播 A 断开和观众 B 的连麦。
val userId = "audienceBUserId"liveCoreView.disconnectUser(userId, null)
String userId = "audienceUserId";liveCoreView.disconnectUser(userId, null);
let userId = "audienceBUserId"liveCoreView.disconnectUser(userId: userId) {} onError: { code, message in}
NSString *userId = @"audienceBUserId";[liveCoreView disconnectUser:userIdonSuccess:^{} onError:^(NSInteger code, NSString * _Nonnull message) {}];
// 文件位置:Flutter/lib/service/impl/room_engine_service.dartmLiveService.kickUserOffSeatByAdmin(0, userId, new TUIRoomDefine.ActionCallback() {@Overridepublic void onSuccess() {}@Overridepublic void onError(TUICommonDefine.Error error, String message) {}});
观众收到主播断开连麦的回调
主播 A 断开和观众 B 的连麦请求后,观众 B 会收到 onUserConnectionTerminated 回调。
override fun onUserConnectionTerminated(inviterUser: UserInfo) {Log.i(TAG, "主播关闭连线")}
@Overridepublic void onUserConnectionTerminated() {Log.i(TAG, "主播关闭连线");}
func onUserConnectionTerminated() {print("主播关闭连线")}
- (void)onUserConnectionTerminated {NSLog(@"主播关闭连线");}
Flutter中,主播 A 断开和观众 B 的连麦请求后,观众 B 会收到在
RTCRoomEngine
的onKickedOffSea
t回调。// 文件位置:Flutter/lib/manager/observer/live_observer.dartsuper.onKickedOffSeat = (seatIndex, userInfo) {LiveKitLogger.info("$tag($hashCode) onKickedOffSeat:[seatIndex:$seatIndex,userInfo:$userInfo");liveController.target?.seatController.onKickedOffSeat(seatIndex, userInfo);};
观众连麦成功后,观众结束连麦
观众 B 和主播 A 连麦成功后,观众 B 主动断开连麦可以调用 terminateIntraRoomConnection。
liveCoreView.terminateIntraRoomConnection()
liveCoreView.terminateIntraRoomConnection();
liveCoreView.terminateIntraRoomConnection()
[liveCoreView terminateIntraRoomConnection]
// 文件位置:Flutter/lib/service/impl/room_engine_service.dartmLiveService.leaveSeat(new TUIRoomDefine.ActionCallback() {@Overridepublic void onSuccess() {}@Overridepublic void onError(TUICommonDefine.Error error, String message) {}});
主播收到观众断开连线的回调
当观众 B 主动断开连麦时,主播会收到 onUserConnectionExited 回调。
override fun onUserConnectionExited(inviterUser: LiveStreamDefine.LiveUser) {Log.i(TAG, "观众退出连线")}
@Overridepublic void onUserConnectionExited(UserInfo liveUser) {Log.i(TAG, "观众退出连线:${liveUser.userId}");}
func onUserConnectionExited(userInfo: TUIUserInfo) {print("观众退出连线")}
- (void)onUserConnectionExited:(TUIUserInfo *)userInfo {NSLog(@"观众退出连线");}
Flutter中,您可以在
onSeatListChanged
回调给出的leftList
中,查看断开连麦的观众。// 文件位置:Flutter/lib/manager/observer/live_observer.dartsuper.onSeatListChanged = (seatList, seatedList, leftList) {LiveKitLogger.info("$tag($hashCode) onSeatListChanged:[seatList:$seatList ,seatedList:$seatedList,leftList:$leftList]");liveController.target?.seatController.onSeatListChanged(seatList, seatedList, leftList);};
说明:
观众连麦时序图