目录

客户端实现

场景描述

本文介绍如何通过环信 IM SDK 和 Agora RTC SDK 在 Android 项目里实现语聊房的主要功能。

技术原理

房间管理

语聊房 Demo 内部依赖环信 IM 聊天室与 Agora RTC 频道。

以下为房间管理流程图。

Demo 中创建或加入语聊房的流程如下:

  1. 启动 Demo。在 application 中调用 ChatroomConfigManager.getInstance.initRoomConfig 方法初始化环信 IM SDK。
  2. 利用手机号和验证码登录环信 IM。
  3. 登录 IM 后,通过 App Server 创建语聊房。成功后,房间创建者成为房主自动加入语聊房并跳转至语聊房页面。
  4. 进入房间后加入环信 IM 聊天室和 RTC 频道。 首先检查是否具有 RTC 所需权限。获取到所需权限并得到授权后执行 onPermissionGrant 方法,调用 initSdkJoin 进行 RTC 初始化(初始化 RTC 加入频道需要的参数由登录时由 App Server 返回)。
  5. 检查是否成功加入环信 IM 聊天室 和 RTC 频道。
    • 若成功加入,房主可以发送本地音频流和消息,观众可以发消息。
    • 若未成功加入,则退出房间,返回房间列表页面。
  6. 退出房间。

语聊房的用户角色如下表所示:

角色 描述
房主 语聊房创建者,在 Demo 中占用 0 号麦位,不可修改。房主可以接收、发送音频流和消息。
主播 进入语聊房后,通过上麦成为主播,可以接收、发送音频流和消息。
观众 进入语聊房后,未进行上麦的成员只能发送和接收消息。申请上麦或房主邀请上麦成功后,可以和主播实时互动。

语聊房的相关操作如下表所示:

操作 描述
创建房间 房主调用 App Server 的 ChatroomHttpManager.getInstance.createRoom 方法创建语聊房,创建成功后自动加入语聊房。房主自动上麦成为主播,更新房间内麦位信息。
创建语聊房前,房主调用 ChatroomConfigManager.getInstance.initRoomConfig 方法初始化环信 IM SDK。
加入房间 用户调用 App Server 的 ChatroomHttpManager.getInstance.joinRoom 方法加入语聊房。加入语聊房前,首先调用 ChatroomHttpManager.getInstance.loginWithToken 方法登录环信 IM,然后调用 initSdkJoin 进行 RTC 初始化。
离开房间 观众或主播可调用 ChatroomHttpManager.getInstance.leaveRoom 方法离开语聊房。房主离开语聊房,语聊房对象自动销毁,其他成员自动离开语聊房。
发送音频流 观众或主播可调用 RtcRoomController.get.joinChannel 方法发送音频流。
发送消息 语聊房内的用户可调用 ChatroomHelper.getInstance.sendTextMsg 或者 CustomMsgHelper.getInstance.sendCustomMsg 方法发送消息。观众也可以调用 ChatroomHelper.getInstance.sendGiftMsg 方法发送礼物消息。

麦位管理

麦位管理流程图如下所示:

麦位相关操作如下表所示:

操作 描述
邀请上麦 房主调用 ChatroomHttpManager.getInstance.invitationMic 方法邀请观众上麦。观众收到 ChatroomListener.receiveInviteSite 回调,选择是否上麦。
- 观众调用 ChatroomHttpManager.getInstance.agreeMicInvitation 方法同意上麦,成为主播,房间内所有用户会收到 ChatroomListener.roomAttributesDidUpdated,更新房间内麦位信息。
- 观众调用 ChatroomHttpManager.getInstance.rejectMicInvitation 方法拒绝上麦,房主收到 ChatroomListener receiveInviteRefusedSite 回调。
申请上麦 观众调用 ChatroomHttpManager.getInstance.submitMic 方法向房主申请上麦。房主收到 ChatroomListener.receiveApplySite 回调,选择同意或拒绝申请。
- 房主调用 ChatroomHttpManager.getInstance.applySubmitMic 方法同意上麦申请,房间内所有用户会收到 ChatroomListener roomAttributesDidUpdated 回调,更新房间内麦位信息。
- 房主调用 ChatroomHttpManager.getInstance.rejectSubmitMic 方法拒绝上麦申请,申请者收到 ChatroomListener receiveDeclineApply 回调。
撤销上麦申请 观众向房主申请上麦后,可以调用 ChatroomHttpManager.getInstance.cancelSubmitMic 方法撤销上麦申请。
下麦 下麦分为主动和被动两种方式:
- 主动下麦:主播可调用 ChatroomHttpManager.getInstance.leaveMic 方法下麦成为观众。
- 被踢下麦:房主调用 ChatroomHttpManager.getInstance.kickMic 方法对所在麦位主播发起下麦指令。
对于这两种下麦方式,房间内所有用户都会收到 ChatroomListener.roomAttributesDidUpdated 回调,更新房间内麦位信息。
开麦 房主和主播调用 ChatroomHttpManager.getInstance.cancelCloseMic 方法开麦,发言时房间内其他用户可听到。房间内所有用户会收到 ChatroomListener roomAttributesDidUpdated 回调,更新麦位状态。
关麦 房主和主播调用 ChatroomHttpManager.getInstance.closeMic 方法关麦,关闭自己的声音。房间内所有用户会收到 ChatroomListener roomAttributesDidUpdated 回调,更新麦位状态。
禁麦 房主调用 ChatroomHttpManager.getInstance.muteMic 方法禁麦,不允许指定连麦主播发言,该主播的音频流将关闭。包括主播在内的房间内所有用户会收到 ChatroomListener roomAttributesDidUpdated 回调,更新麦位状态。
解禁麦位 房主调用 ChatroomHttpManager.getInstance.cancelMuteMic 方法解禁麦位,恢复连麦主播的发言权限,即恢复该麦位主播的音频流。包括主播在内的房间内所有用户会收到 ChatroomListener.roomAttributesDidUpdated 回调,更新麦位状态。
锁麦 房主调用 ChatroomHttpManager.getInstance.lockMic 方法锁麦,不允许任何人上该麦位。锁麦时,若该麦位有主播连麦,该主播收到 ChatroomListener.roomAttributesDidUpdated 回调被踢下来成为普通观众。房间内所有用户也会收到该回调,更新房间内麦位信息。
解锁麦位 房主调用 ChatroomHttpManager.getInstance.cancelLockMic 方法解锁麦位,使指定麦位恢复空闲状态,观众可申请该麦位上麦。房间内所有用户会收到 ChatroomListener roomAttributesDidUpdated 回调,更新麦位状态。
换麦 主播调用 ChatroomHttpManager.getInstance.exChangeMic 方法换麦,即从当前麦位切换到另一个空闲麦位。包括主播在内的房间内所有用户会收到 ChatroomListener roomAttributesDidUpdated 回调,更新房间内麦位信息。

发送单向消息

邀请用户上麦的流程如下:

  1. 房主调用 RESTFul API 邀请用户上麦。
  2. App Server 收到邀请消息后,利用房主角色向用户发送该消息。
  3. 用户同意邀请后调用 RESTful API 上麦。
  4. App Server 设置聊天室属性通知房间全员刷新房间设置。

用户申请上麦的流程如下:

  1. 用户调用 RESTful 接口申请上麦。
  2. App Server 收到上麦申请消息后以用户角色向房主发送该消息。
  3. 房主收到上麦申请后调用 RESTful API 同意上麦。
  4. App Server 设置聊天室属性通知房间全员刷新房间设置。

发送礼物消息

发送礼物消息的流程如下:

  1. 用户 A 发送礼物详情到 App Server。
  2. App Server 统计礼物信息后对用户 A 返回响应。
  3. SDK 将礼物消息发送到语聊房。

前提条件

项目配置

产品 SDK 下载 集成文档
环信即时通讯 IM SDK 环信即时通讯 IM SDK 3.9.8 发送和接收消息
Agora RTC SDK Agora RTC SDK 4.0.1 实现音频通话

基础 API 参考

下表提供环信 IM SDK 和 Agora RTC SDK 的基本 API 参考。

初始设置

加入语聊房前,进行环信 IM SDK 初始化Agora RTC 初始化设置。

App Server 相关

以下表格为 App Server 的基础 API。

房间管理 API 如下表所示:

麦位管理 API 如下表所示:

礼物榜单 API 如下表所示:

API 实现功能
ChatroomHttpManager.getInstance.getGiftList 获取赠送礼物榜单。
ChatroomHttpManager.getInstance.sendGift 赠送礼物。

Agora RTC 相关

API 实现功能
initializeAndJoinChannel 初始化 app 并加入频道。

其他 API,详见声网官网

Easemob IM SDK 相关

Easemob IM SDK 的 API 如下表所示:

API 实现功能
EMClient.getInstance.init 初始化 IM SDK。
EMClient.getInstance.chatManager.sendMessage 发送消息。

语聊房监听

初始化 SDK(ChatroomConfigManager.getInstance.initRoomConfig)时已注册了连接监听、消息监听、聊天室监听,可以实现 ChatroomListener 接口。

音频相关

主播调用以下方法设置音频流:

API 实现功能
setAudioProfile [2/2] 设置音频编码属性。
muteLocalAudioStream 主播可以关闭或开启本地麦克风。
adjustRecordingSignalVolume 调节人声音量。

附加功能

最佳音效

设置最佳音效,示例代码如下:

annotation class SoundSelection {
                    companion object {
                        const val SocialChat = 0        //社交语聊

                        const val Karaoke = 1           //在线 K 歌

                        const val GamingBuddy = 2       //游戏陪玩

                        const val SoundCardHQ = 3       //专业主播
                    }
                }

                 rtcEngine?.apply {
            when (config.soundType) {
                SoundSelection.SocialChat, SoundSelection.Karaoke -> { // 社交语聊,KTV
                    setChannelProfile(Constants.CHANNEL_PROFILE_LIVE_BROADCASTING)
                    setAudioProfile(Constants.AUDIO_PROFILE_MUSIC_HIGH_QUALITY)
                    setAudioScenario(Constants.AUDIO_SCENARIO_GAME_STREAMING)
                }
                SoundSelection.GamingBuddy -> { // 游戏陪玩
                    setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION)
                }
                else -> { //专业主播
                    setAudioProfile(Constants.AUDIO_PROFILE_MUSIC_HIGH_QUALITY)
                    setAudioScenario(Constants.AUDIO_SCENARIO_GAME_STREAMING)
                    setParameters("{\"che.audio.custom_payload_type\":73}")
                    setParameters("{\"che.audio.custom_bitrate\":128000}")
                    // setRecordingDeviceVolume(128) 4.0.1 上才支持
                    setParameters("{\"che.audio.input_channels\":2}")
                }
            }
        }

AI 降噪

AI 降噪插件使用声网人工智能噪声消除算法,能够让远程交流和面对面交谈一样实时。

可以开启或关闭 AI 降噪以及设置中级降噪和高级降噪。示例代码如下:

internal class AgoraRtcDeNoiseEngine : RtcBaseDeNoiseEngine<RtcEngineEx>() {

    override fun closeDeNoise(): Boolean {
        engine?.apply {
            setParameters("{\"che.audio.ains_mode\":0}")
            setParameters("{\"che.audio.nsng.lowerBound\":80}")
            setParameters("{\"che.audio.nsng.lowerMask\":50}")
            setParameters("{\"che.audio.nsng.statisticalbound\":5}")
            setParameters("{\"che.audio.nsng.finallowermask\":30}")
            setParameters("{\"che.audio.nsng.enhfactorstastical\":200}")
        }
        return true
    }

    override fun openMediumDeNoise(): Boolean {
        engine?.apply {
            setParameters("{\"che.audio.ains_mode\":2}")
            setParameters("{\"che.audio.nsng.lowerBound\":80}")
            setParameters("{\"che.audio.nsng.lowerMask\":50}")
            setParameters("{\"che.audio.nsng.statisticalbound\":5}")
            setParameters("{\"che.audio.nsng.finallowermask\":30}")
            setParameters("{\"che.audio.nsng.enhfactorstastical\":200}")
        }
        return true
    }

    override fun openHeightDeNoise(): Boolean {
        engine?.apply {
            setParameters("{\"che.audio.ains_mode\":2}")
            setParameters("{\"che.audio.nsng.lowerBound\":10}")
            setParameters("{\"che.audio.nsng.lowerMask\":10}")
            setParameters("{\"che.audio.nsng.statisticalbound\":0}")
            setParameters("{\"che.audio.nsng.finallowermask\":8}")
            setParameters("{\"che.audio.nsng.enhfactorstastical\":200}")
        }
        return true
    }
}