实现语聊房(基于NERoom)

更新时间: 2023/08/30 03:00:57

本文档为您展示通过 NERoom房间组件实现语聊房场景的相关步骤,帮助您在业务中实现麦位管理、低延时语音互动、文字聊天等能力。

开发环境要求

开发环境要求如下:

环境要求 说明
JDK 版本 1.8.0 及以上版本
Android API 版本 API 21 及以上版本
Android Studio 版本 5.0 及以上版本
CPU架构 ARM 64、ARMV7
IDE Android Studio
其他 依赖 Androidx,不支持 support 库。
Android 系统 5.0 及以上版本的真机。

前提条件

方案架构

基于NERoom的方案架构.png

方案架构说明如下:

  • 主播、连麦者和观众加入同一个音视频房间。
  • 主播和连麦者在音视频房间内进行音频流的实时发布和订阅。
  • 观众在音视频房间内仅订阅音频流,不发布音频流。

API调用时序图

sequenceDiagram
  participant hostClientA as 主播A client
  participant NERoomA as NERoom
  participant app_server as VoiceRoom_Server
  participant NERoomB as NERoom
  participant audienceB as 观众B client


  note over hostClientA, audienceB: 主播开播
  hostClientA ->> NERoomA: createRoom
  NERoomA ->> app_server: createRoom
  app_server -->> hostClientA: 房间信息
  hostClientA ->> NERoomA: joinRoom
  NERoomA ->> app_server: joinRoom
  app_server -->> hostClientA: 加入成功
  hostClientA ->> NERoomA: unmuteMyAudio
  NERoomA ->> app_server: unmuteMyAudio

  note over hostClientA, audienceB: 观众进入房间
  audienceB ->> NERoomB: joinRoom
  NERoomB ->> app_server: joinRoom
  app_server -->> audienceB: 房间信息
  audienceB ->> NERoomB: unmuteMyAudio
  NERoomB ->> app_server: unmuteMyAudio


sequenceDiagram
participant hostClientA as 主播A client
participant NERoomA as NERoom
participant app_server as VoiceRoom_Server
participant NERoomB as NERoom
participant audienceB as 观众B client

note over hostClientA, audienceB: 抱观众上麦
hostClientA ->> NERoomA: sendSeatInvitation <br>(邀请上麦)
NERoomA ->> app_server: sendSeatInvitation <br>(邀请上麦)
app_server -->> NERoomB: onSeatInvitationAccepted <br>(自动同意上麦的回调)
NERoomB -->> audienceB: onSeatInvitationAccepted <br>(自动同意上麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomA: onSeatInvitationAccepted <br>(自动同意上麦的回调)
NERoomA -->> hostClientA: onSeatInvitationAccepted <br>(自动同意上麦的回调)
app_server -->> NERoomA: onSeatListChanged <br> (麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI

note over hostClientA, audienceB: 将观众移出麦位
hostClientA ->> NERoomA: kickSeat <br>(主播踢观众B下麦)
NERoomA ->> app_server: kickSeat <br>(主播踢观众B下麦)
app_server -->> NERoomB: onSeatKicked <br>(主播踢观众B下麦的回调)
NERoomB -->> audienceB: onSeatKicked <br>(主播踢观众B下麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomA: onSeatKicked <br>(主播踢观众B下麦的回调)
NERoomA -->> hostClientA: onSeatKicked <br>(主播踢观众B下麦的回调)
app_server -->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI


sequenceDiagram
participant hostClientA as 主播A client
participant NERoomA as NERoom
participant app_server as VoiceRoom_Server
participant NERoomB as NERoom
participant audienceB as 观众B client


note over hostClientA, audienceB: 观众申请上麦
audienceB ->> NERoomB: submitSeatRequest <br>(申请上麦)
NERoomB ->> app_server: submitSeatRequest <br>(申请上麦)
app_server ->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB ->> audienceB: onSeatListChanged <br>(麦位变更的回调)
app_server ->> NERoomA: onSeatRequestSubmitted <br>(观众B申请上麦的回调)
NERoomA ->> hostClientA: onSeatRequestSubmitted <br>(观众B申请上麦的回调)
app_server ->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA ->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI

alt 主播同意上麦申请
hostClientA ->> NERoomA: approveSeatRequest <br>(主播同意上麦申请)
NERoomA ->> app_server: approveSeatRequest <br>(主播同意上麦申请)
app_server ->> NERoomA: onSeatRequestApproved <br>(主播同意上麦申请的回调)
NERoomA ->> hostClientA: onSeatRequestApproved <br>(主播同意上麦申请的回调)
app_server ->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA ->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
app_server ->> NERoomB: onSeatRequestApproved <br>(主播同意上麦申请的回调)
NERoomB ->> audienceB: onSeatRequestApproved <br> (主播同意上麦申请的回调)
app_server ->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB ->> audienceB: onSeatListChanged <br> (麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI
else 主播拒绝上麦申请
hostClientA ->> NERoomA: rejectRequestSeat <br>(主播不同意上麦申请)
NERoomA ->> app_server: rejectRequestSeat <br>(主播不同意上麦申请)
app_server -->> NERoomA: onSeatRequestRejected <br>(主播拒绝观众B上麦的回调)
NERoomA -->> hostClientA: onSeatRequestRejected <br>(主播拒绝观众B上麦的回调)
app_server -->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomB: onSeatRequestRejected <br>(主播拒绝观众B上麦的回调)
NERoomB -->> audienceB: onSeatRequestRejected <br>(主播拒绝观众B上麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI
end


sequenceDiagram
participant hostClientA as 主播A client
participant NERoomA as NERoom
participant app_server as VoiceRoom_Server
participant NERoomB as NERoom
participant audienceB as 观众B client

note over hostClientA, audienceB: 观众取消申请上麦
audienceB ->> NERoomB: cancelSeatRequest<br> (取消申请上麦)
NERoomB ->> app_server: cancelSeatRequest <br> (取消申请上麦)
app_server -->> NERoomA: onSeatRequestCancelled <br>(观众B取消上麦的回调)
NERoomA -->> hostClientA: onSeatRequestCancelled <br>(观众B取消上麦的回调)
app_server -->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomB: onSeatRequestCancelled <br>(观众B取消上麦的回调)
NERoomB -->> audienceB: onSeatRequestCancelled <br> (观众B取消上麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI

note over hostClientA, audienceB: 观众下麦
audienceB ->> NERoomB: leaveSeat (下麦)
NERoomB ->> app_server: leaveSeat (下麦)
app_server -->> NERoomA: onSeatLeave <br>(观众B成功下麦的回调)
NERoomA -->> hostClientA: onSeatLeave <br>(观众B成功下麦的回调)
app_server -->> NERoomA: onSeatListChanged <br>(麦位变更的回调)
NERoomA -->> hostClientA: onSeatListChanged <br>(麦位变更的回调)
app_server -->> NERoomB: onSeatLeave <br>(观众B成功下麦的回调)
NERoomB -->> audienceB: onSeatLeave <br>(观众B成功下麦的回调)
app_server -->> NERoomB: onSeatListChanged <br>(麦位变更的回调)
NERoomB -->> audienceB: onSeatListChanged <br>(麦位变更的回调)
audienceB ->> audienceB: 刷新UI
hostClientA ->> hostClientA: 刷新UI


登录鉴权

调用 NEAuthService 实例中的login接口进行账号登录。

NEAuthService authService = NERoomKit.getInstance().getService(NEAuthService.class);
String account="your account";
String token="your token";
authService.login(account,token, new NECallback2<Unit>() {
    @Override
    public void onSuccess(@Nullable Unit unit) {
        super.onSuccess(unit);
    }

    @Override
    public void onError(int code, @Nullable String message) {
        super.onError(code, message);
    }
});

示例代码中的your accountyour token是您的应用服务器向 NERoom 服务器申请创建账号时,返回的 userUuiduserToken 的值,具体请参见创建账号

主播开播

  1. 主播调用 createRoom 接口创建房间。

    创建房间麦位 NESeatInitParams 参数说明:

    参数 类型 描述
    seatCount int 麦位数量
    seatRequestApprovalMode int NESeatRequestApprovalMode 内获取麦位申请审批模式。
    • OFF:关闭审批模式,即成员提交申请后不需要管理员同意,可直接上麦。
    • ON:开启审批模式,即成员提交申请后需要管理员同意才能上麦。
    seatInvitationConfirmMode int 麦位邀请确认模式。
    • OFF: 关闭确认模式,即管理员邀请其他成员上麦,不需要被邀请的成员确认,可直接上麦。
    • ON:开启确认模式,即管理员邀请其他成员上麦,需要被邀请的成员确认,接受后方可上麦。

    示例代码如下:

    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            String roomUuid="123";
            String roomName="roomName";
            int templateId= 21;
            String password = "12345";
            Map<String,String> initialProperties = new HashMap<String,String>();
            initialRoomProperties.put("custom-property-key0", "custom-property-value0");
            initialRoomProperties.put("custom-property-key1", "custom-property-value1");
            /// 设置麦位数量8个,麦位申请需要审批。房主邀请上麦不需要观众同意
            NESeatInitParams seatInitParams = new NESeatInitParams(8,NESeatRequestApprovalMode.ON,NESeatInvitationConfirmMode.OFF);
            NECreateRoomParams params=new NECreateRoomParams(roomUuid,roomName,templateId, password,seatInitParams, initialProperties);
            NECreateRoomOptions options = new NECreateRoomOptions();
            roomService.createRoom(params, options, new NECallback2<Unit>() {
                @Override
                public void onSuccess(@Nullable Unit unit) {
                    super.onSuccess(unit);
                    Log.d(TAG,"success");
                }
    
                @Override
                public void onError(int code, @Nullable String message) {
                    super.onError(code, message);
                    Log.d(TAG,"error");
                }
            });
    
  2. 主播调用 joinRoom接口加入房间。

    示例代码如下:

    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            String roomUuid="123";
            String userName="userName";
            String role="host";//从模板获取角色名称,比如PK直播的场景中的角色名为:host,invited_host,audience
            String password = "password"; //设置为null,表示没有密码
            Map<String,String> initialProperties = new HashMap<String,String>();
            initialProperties.put("custom-property-key0", "custom-property-value0");
            initialProperties.put("custom-property-key1", "custom-property-value1");
            roomService.joinRoom(new NEJoinRoomParams(roomUuid, userName, role, password, initialProperties), new NEJoinRoomOptions(), new NECallback2<NERoomContext>() {
                @Override
                public void onSuccess(@Nullable NERoomContext neRoomContext) {
                    super.onSuccess(neRoomContext);
                    Log.d(TAG,"success");
                }
    
                @Override
                public void onError(int code, @Nullable String message) {
                    super.onError(code, message);
                    Log.d(TAG,"error");
                }
            });
    
  3. 调用 joinRtcChannel 接口加入音视频房间。

    示例代码如下:

    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext!=null){
                roomContext.getRtcController().joinRtcChannel(new NECallback2<Unit>() {
                    @Override
                    public void onSuccess(@Nullable Unit unit) {
                        super.onSuccess(unit);
                        Log.d(TAG,"success");
                    }
    
                    @Override
                    public void onError(int code, @Nullable String message) {
                        super.onError(code, message);
                        Log.d(TAG,"error");
                    }
                });
            }
    
  4. 调用 addRoomListener 接口监听房间里的事件。

    示例代码如下:

    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext!=null){
                roomContext.addRoomListener(new NERoomListener() {
                    @Override
                    public void onMemberRoleChanged(@NonNull NERoomMember member, @NonNull NERoomRole oldRole, @NonNull NERoomRole newRole) {
                        
                    }
    
                    @Override
                    public void onMemberJoinRoom(@NonNull List<? extends NERoomMember> members) {
    
                    }
    
                    @Override
                    public void onMemberLeaveRoom(@NonNull List<? extends NERoomMember> members) {
    
                    }
    
                    @Override
                    public void onRoomEnded(@NonNull NERoomEndReason reason) {
    
                    }
    
                    @Override
                    public void onMemberJoinRtcChannel(@NonNull List<? extends NERoomMember> members) {
    
                    }
    
                    @Override
                    public void onMemberLeaveRtcChannel(@NonNull List<? extends NERoomMember> members) {
    
                    }
    
                    @Override
                    public void onRtcChannelError(int code) {
    
                    }
    
                    @Override
                    public void onMemberJoinChatroom(@NonNull List<? extends NERoomMember> members) {
    
                    }
    
                    @Override
                    public void onMemberLeaveChatroom(@NonNull List<? extends NERoomMember> members) {
    
                    }
    
                    @Override
                    public void onMemberAudioMuteChanged(@NonNull NERoomMember member, boolean mute, NERoomMember operateBy) {
    
                    }
    
                    @Override
                    public void onMemberVideoMuteChanged(@NonNull NERoomMember member, boolean mute, NERoomMember operateBy) {
    
                    }
    
                    @Override
                    public void onMemberScreenShareStateChanged(@NonNull NERoomMember member, boolean isSharing, NERoomMember operateBy) {
    
                    }
    
                    @Override
                    public void onReceiveChatroomMessages(@NonNull List<? extends NERoomMessage> messages) {
    
                    }
    
                    @Override
                    public void onMemberWhiteboardStateChanged(@NonNull NERoomMember member, boolean isSharing, NERoomMember operateBy) {
    
                    }
    
                    @Override
                    public void onWhiteboardError(int code, @NonNull String message) {
    
                    }
    
                    @Override
                    public void onRoomLiveStateChanged(@NonNull NELiveState state) {
    
                    }
    
                    @Override
                    public void onRoomLockStateChanged(boolean isLocked) {
    
                    }
    
                    @Override
                    public void onMemberNameChanged(@NonNull NERoomMember member, @NonNull String name) {
    
                    }
    
                    @Override
                    public void onRoomPropertiesChanged(@NonNull Map<String, String> properties) {
    
                    }
    
                    @Override
                    public void onRoomPropertiesDeleted(@NonNull Map<String, String> properties) {
    
                    }
    
                    @Override
                    public void onMemberPropertiesChanged(@NonNull NERoomMember member, @NonNull Map<String, String> properties) {
    
                    }
    
                    @Override
                    public void onMemberPropertiesDeleted(@NonNull NERoomMember member, @NonNull Map<String, String> properties) {
    
                    }
    
                    @Override
                    public void onRtcAudioVolumeIndication(@NonNull List<NEMemberVolumeInfo> volumes, int totalVolume) {
    
                    }
    
                    @Override
                    public void onRtcAudioOutputDeviceChanged(@NonNull NEAudioOutputDevice device) {
    
                    }
    
                });
            }
    
  5. 收到加入成功的 onMemberJoinRoom 回调后,调用 unmuteMyAudio 方法开启本地音频采集。

    示例代码如下:

    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext != null) {
                roomContext.getRtcController().unmuteMyAudio(new NECallback2<Unit>() {
                    @Override
                    public void onSuccess(@Nullable Unit unit) {
                        super.onSuccess(unit);
                        Log.d(TAG,"success");
                    }
    
                    @Override
                    public void onError(int code, @Nullable String message) {
                        super.onError(code, message);
                        Log.d(TAG,"error");
                    }
                });
            }
    

6.调用 submitSeatRequest 方法上麦。

示例代码如下:

NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        if (roomContext != null) {
            roomContext.getSeatController().submitSeatRequest(1,new NECallback2<Unit>() {
                @Override
                public void onSuccess(@Nullable Unit unit) {
                    super.onSuccess(unit);
                    Log.d(TAG,"success");
                }

                @Override
                public void onError(int code, @Nullable String message) {
                    super.onError(code, message);
                    Log.d(TAG,"error");
                }
            });
        }

观众进入房间

  1. 观众调用 joinRoom接口加入房间。

  2. 观众调用 addRoomListener 接口监听房间里的事件。

  3. 观众调用 muteMyAudio 方法关闭本地音频采集。

    等到上麦后,再开启本地音频采集。

麦位管理

添加麦位事件监听

调用 addSeatListener 接口,监听麦位相关的事件。

示例代码如下:

NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        if (roomContext != null) {
            roomContext.getSeatController().addSeatListener(new NESeatEventListener() {
            
            @Override
            public void onSeatManagerAdded(List<String> managers) {

            }
            @Override
            public void onSeatManagerRemoved(List<String> managers) {
            }
            @Override
            public void onSeatRequestSubmitted(int seatIndex, String user) {
            }
            @Override
            public void onSeatRequestCancelled(int seatIndex, String user) {
            }
            @Override
            public void onSeatRequestApproved(int seatIndex, String user, String operateBy, boolean isAutoAgree) {
                
            }
            @Override
            public void onSeatRequestRejected(int seatIndex, String user, String operateBy) {
                
            }
            @Override
            public void onSeatInvitationReceived(int seatIndex, String user, String operateBy) {
                
            }
            @Override
            public void onSeatInvitationCancelled(int seatIndex, String user, String operateBy) {
            
            }
            @Override
            public void onSeatInvitationAccepted(int seatIndex,String user, boolean isAutoAgree) {
            }
            @Override
            public void onSeatInvitationRejected(int seatIndex, String user) {
            }
            @Override
            public void onSeatLeave(int seatIndex, String user) {
            }
            @Override
            public void onSeatKicked(int seatIndex, String user, String operateBy) {
            }
            @Override
            public void onSeatListChanged(List<NESeatItem> seatItems) {
            
            }
        });
        }

主播邀请观众上麦

  • 主播调用 sendSeatInvitation 接口邀请观众上麦。

    String userId = "56789";
    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext != null) {
                roomContext.getSeatController().sendSeatInvitation(userId,new NECallback2<Unit>() {
                    @Override
                    public void onSuccess(@Nullable Unit unit) {
                        super.onSuccess(unit);
                        Log.d(TAG,"success");
                    }
    
                    @Override
                    public void onError(int code, @Nullable String message) {
                        super.onError(code, message);
                        Log.d(TAG,"error");
                    }
                });
            }
    
  • 主播也可以在邀请观众上麦时指定麦位。

    String userId = "56789";
    int index = 2;
    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext != null) {
                roomContext.getSeatController().sendSeatInvitation(index,userId,new NECallback2<Unit>() {
                    @Override
                    public void onSuccess(@Nullable Unit unit) {
                        super.onSuccess(unit);
                        Log.d(TAG,"success");
                    }
    
                    @Override
                    public void onError(int code, @Nullable String message) {
                        super.onError(code, message);
                        Log.d(TAG,"error");
                    }
                });
            }
    

主播同意观众上麦

主播调用 approveSeatRequest 接口同意观众上麦。

String userId = "56789";
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        if (roomContext != null) {
            roomContext.getSeatController().approveSeatRequest(userId,new NECallback2<Unit>() {
                @Override
                public void onSuccess(@Nullable Unit unit) {
                    super.onSuccess(unit);
                    Log.d(TAG,"success");
                }

                @Override
                public void onError(int code, @Nullable String message) {
                    super.onError(code, message);
                    Log.d(TAG,"error");
                }
            });
        }

主播拒绝观众上麦

主播调用 rejectSeatRequest 接口拒绝观众上麦。

String userId = "56789";
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        if (roomContext != null) {
            roomContext.getSeatController().rejectSeatRequest(userId,new NECallback2<Unit>() {
                @Override
                public void onSuccess(@Nullable Unit unit) {
                    super.onSuccess(unit);
                    Log.d(TAG,"success");
                }

                @Override
                public void onError(int code, @Nullable String message) {
                    super.onError(code, message);
                    Log.d(TAG,"error");
                }
            });
        }

主播将观众移出麦位

主播调用 kickSeat 接口将观众移出麦位。

String userId = "56789";
NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        if (roomContext != null) {
             roomContext.getSeatController().kickSeat(userId,new NECallback2<Unit>() {
                 @Override
                 public void onSuccess(@Nullable Unit unit) {
                     super.onSuccess(unit);
                     Log.d(TAG,"success");
                 }

                 @Override
                 public void onError(int code, @Nullable String message) {
                     super.onError(code, message);
                     Log.d(TAG,"error");
                 }
             });
        }

观众申请上麦

观众调用 submitSeatRequest 接口申请上麦。

  • 观众不指定麦位

    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext != null) {
                roomContext.getSeatController().submitSeatRequest(new NECallback2<Unit>() {
                    @Override
                    public void onSuccess(@Nullable Unit unit) {
                        super.onSuccess(unit);
                        Log.d(TAG,"success");
                    }
    
                    @Override
                    public void onError(int code, @Nullable String message) {
                        super.onError(code, message);
                        Log.d(TAG,"error");
                    }
                });
            }
    
  • 观众指定麦位

    int seatIndex = 2;
    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext != null) {
                roomContext.getSeatController().submitSeatRequest(seatIndex,new NECallback2<Unit>() {
                    @Override
                    public void onSuccess(@Nullable Unit unit) {
                        super.onSuccess(unit);
                        Log.d(TAG,"success");
                    }
    
                    @Override
                    public void onError(int code, @Nullable String message) {
                        super.onError(code, message);
                        Log.d(TAG,"error");
                    }
                });
            }
    

观众取消申请上麦

观众调用 cancelSeatRequest 接口取消申请上麦。

NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        if (roomContext != null) {
             roomContext.getSeatController().cancelSeatRequest(new NECallback2<Unit>() {
                 @Override
                 public void onSuccess(@Nullable Unit unit) {
                     super.onSuccess(unit);
                     Log.d(TAG,"success");
                 }

                 @Override
                 public void onError(int code, @Nullable String message) {
                     super.onError(code, message);
                     Log.d(TAG,"error");
                 }
             });
        }

观众主动下麦

观众调用 leaveSeat 接口下麦。

NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        if (roomContext != null) {
             roomContext.getSeatController().leaveSeat(new NECallback2<Unit>() {
                 @Override
                 public void onSuccess(@Nullable Unit unit) {
                     super.onSuccess(unit);
                     Log.d(TAG,"success");
                 }

                 @Override
                 public void onError(int code, @Nullable String message) {
                     super.onError(code, message);
                     Log.d(TAG,"error");
                 }
             });
        }

离开房间

  1. 调用 leaveRoom 接口离开房间。

    示例代码如下:

    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext!=null){
                roomContext.leaveRoom(new NECallback2<Unit>() {
                    @Override
                    public void onSuccess(@Nullable Unit unit) {
                        super.onSuccess(unit);
                        Log.d(TAG,"success");
                    }
    
                    @Override
                    public void onError(int code, @Nullable String message) {
                        super.onError(code, message);
                        Log.d(TAG,"error");
                    }
                });
            }
    
  2. 离开房间成功后,会触发 NERoomListener.onMemberLeaveRoom 回调,通知房间内所有成员。

  3. 主播调用 endRoom 接口删除房间。

    示例代码如下:

    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
    NERoomContext roomContext = roomService.getRoomContext(roomUuid);
    if (roomContext!=null){
        roomContext.endRoom(new NECallback2<Unit>() {
            @Override
            public void onSuccess(@Nullable Unit unit) {
                super.onSuccess(unit);
                Log.d(TAG,"success");
            }
    
            @Override
            public void onError(int code, @Nullable String message) {
                super.onError(code, message);
                Log.d(TAG,"error");
            }
        });
    }
    
  4. 删除房间成功后,会触发 NERoomListener 协议中的 onRoomEnded 回调方法。

进阶功能

伴音

  1. 调用 RtcControllerstartAudioMixing 方法播放伴音。

NERoomCreateAudioMixingOption 参数说明如下表所示。

参数 类型 描述
path String 待播放的音乐文件的绝对路径或 URL 地址,支持本地 SD 卡中的绝对路径或 URL 地址
loopCount int 伴音循环播放的次数。1:(默认)播放一次。≤ 0:无限循环播放
sendEnabled boolean 是否将伴音发送远端,默认为 true,即远端用户可以听到该伴音。
sendVolume int 音乐文件的发送音量,取值范围为 0~200。默认为 100,表示使用文件的原始音量。
playbackEnabled boolean 是否本地播放伴音。默认为 true,即本地用户可以听到该伴音。
playbackVolume int 音乐文件的播放音量,取值范围为 0~200。默认为 100,表示使用文件的原始音量。
startTimeStamp long 音乐文件开始播放的时间,UTC 时间戳,即从1970 年 1 月 1 日 0 点 0 分 0 秒开始到事件发生时的毫秒数。默认值为 0,表示立即播放。
sendWithAudioType NERoomRtcAudioStreamType 伴音跟随音频主流还是辅流,默认跟随主流。
  • NERtcAudioStreamTypeMain:伴音跟随主流
  • NERtcAudioStreamTypeSub:伴音跟随辅流
  1. 设置伴音的音量。

    • 通过 setAudioMixingSendVolume 设置伴音的发送音量
    • 通过 setAudioMixingPlaybackVolume 设置伴音的播放音量。
  2. 在离开房间前调用 stopAudioMixing 结束伴音。

示例代码如下:

NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        String path = "音频文件地址";
        int loopCount = 1;
        boolean sendEnabled = true;
        int sendVolume = 100;
        boolean playbackEnabled = true;
        int playbackVolume = 100;
        long startTimeStamp = 0;
        NERoomRtcAudioStreamType sendWithAudioType = NERoomRtcAudioStreamType.NERtcAudioStreamTypeMain
        NERoomCreateAudioMixingOption options = new NERoomCreateAudioMixingOption(path,loopCount,sendEnabled,sendVolume,
        playbackEnabled,playbackVolume,startTimeStamp,sendWithAudioType);
        if (roomContext != null) {
            roomContext.getRtcController().startAudioMixing(options);
        }
        if (roomContext != null) {
            roomContext.getRtcController().setAudioMixingSendVolume(80);
        }

        if (roomContext != null) {
            roomContext.getRtcController().setAudioMixingPlaybackVolume(80);
        }

        if (roomContext != null) {
            roomContext.getRtcController().stopAudioMixing();
        }

音效

  1. 调用 RtcControllerplayEffect 方法播放音效。

    NERoomCreateAudioEffectOption 参数说明如下表所示。

    参数 类型 描述
    path String 待播放的音乐文件的绝对路径或 URL 地址,支持本地 SD 卡中的绝对路径或 URL 地址
    loopCount int 音效循环播放的次数。1:(默认)播放一次。≤ 0:无限循环播放
    sendEnabled boolean 是否将音效发送远端,默认为 true,即远端用户可以听到该音效。
    sendVolume int 音效文件的发送音量,取值范围为 0~200。默认为 100,表示使用文件的原始音量。
    playbackEnabled boolean 是否本地播放音效。默认为 true,即本地用户可以听到该音效。
    playbackVolume int 音乐文件的播放音量,取值范围为 0~200。默认为 100,表示使用文件的原始音量。
    startTimeStamp long 音乐文件开始播放的时间,UTC 时间戳,即从1970 年 1 月 1 日 0 点 0 分 0 秒开始到事件发生时的毫秒数。默认值为 0,表示立即播放。
    sendWithAudioType NERoomRtcAudioStreamType 伴音跟随音频主流还是辅流,默认跟随主流。
    • NERtcAudioStreamTypeMain:伴音跟随主流
    • NERtcAudioStreamTypeSub:伴音跟随辅流
  2. 设置音效的音量。

    • 调用 setEffectSendVolume 方法设置音效文件发送音量。

    • 调用 setEffectPlaybackVolume 方法设置音效文件播放音量。

  3. 在离开房间前,调用 stopAllEffects 方法停止播放所有音效文件。

示例代码如下:

NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
        NERoomContext roomContext = roomService.getRoomContext(roomUuid);
        String path = "音效文件地址";
        int loopCount = 1;
        boolean sendEnabled = true;
        int sendVolume = 100;
        boolean playbackEnabled = true;
        int playbackVolume = 100;
        long startTimeStamp = 0;
        NERoomRtcAudioStreamType sendWithAudioType = NERoomRtcAudioStreamType.NERtcAudioStreamTypeMain
        NERoomCreateAudioEffectOption options = new NERoomCreateAudioEffectOption(path,loopCount,sendEnabled,sendVolume,
        playbackEnabled,playbackVolume,startTimeStamp,sendWithAudioType);
        if (roomContext != null) {
            roomContext.getRtcController().playEffect(options);
        }
        if (roomContext != null) {
            roomContext.getRtcController().setEffectSendVolume(0, 80);
        }

        if (roomContext != null) {
            roomContext.getRtcController().setEffectPlaybackVolume(0, 80);
        }

        if (roomContext != null) {
            roomContext.getRtcController().stopAllEffects();
        }

耳返

  1. 通过 onRtcAudioOutputDeviceChanged 监听播放设备的变化,当监听到播放设备切换为耳机时才开启耳返。
    public void onRtcAudioOutputDeviceChanged(@NonNull NEAudioOutputDevice device) {
        switch (device) {
            case SPEAKER_PHONE:
                Log.d(TAG, "扬声器");
                break;
            case WIRED_HEADSET:
                Log.d(TAG, "有线耳机");
                break;
            case EARPIECE:
                Log.d(TAG, "听筒");
                break;
            case BLUETOOTH_HEADSET:
                Log.d(TAG, "蓝牙耳机");
                break;
        }
    }
    
  2. 调用 enableEarBack 方法开启耳返。
    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
    int volumn = 100; // 耳返音量 默认100
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext != null) {
                roomContext.getRtcController().enableEarBack(volumn);
            }
    
  3. 调用 disableEarBack 方法关闭耳返。
    NERoomService roomService = NERoomKit.getInstance().getService(NERoomService.class);
            NERoomContext roomContext = roomService.getRoomContext(roomUuid);
            if (roomContext != null) {
                roomContext.getRtcController().disableEarBack();
            }
    
此文档是否对你有帮助?
有帮助
去反馈
  • 开发环境要求
  • 前提条件
  • 方案架构
  • API调用时序图
  • 登录鉴权
  • 主播开播
  • 观众进入房间
  • 麦位管理
  • 添加麦位事件监听
  • 主播邀请观众上麦
  • 主播同意观众上麦
  • 主播拒绝观众上麦
  • 主播将观众移出麦位
  • 观众申请上麦
  • 观众取消申请上麦
  • 观众主动下麦
  • 离开房间
  • 进阶功能
  • 伴音
  • 音效
  • 耳返