实现语聊房
本文介绍如何实现语聊房,包含登录系统、初始化引擎、创建房间、麦位管理、退出房间。
示例项目
声网在 agora-ent-scenarios
仓库中提供实现语聊房的源代码供你参考。
业务流程
本节展示语聊房中常见的业务流程。
进出房间
下图展示创建、进入、退出房间的流程。
房主邀请听众上麦
下图展示房主邀请听众上麦的流程。在这个流程中,房主发起上麦邀请,如果听众接受邀请,房主会收到通知。听众上麦并修改麦位,然后发布自己的音频流。
听众申请上麦
下图展示听众向房主申请上麦的流程。在这个流程中,听众主动发起上麦申请,如果房主接受申请,房主修改麦位信息以让听众上麦。听众收到上麦消息后,发布自己的音频流。
准备开发环境
前提条件
开始前,请确保你的开发环境满足如下要求:
- Xcode 13.0 及以上。
- iOS 设备,版本 13.0 及以上。
- 有效的苹果开发者账号。
- 可以访问互联网的计算机。确保你的网络环境没有部署防火墙,否则无法正常使用声网服务。
- 参考开通服务创建声网开发者账号和声网项目,并获取项目的 App ID 和临时 Token。
集成 SDK
语聊房用到声网实时互动 (RTC) SDK 和即时通讯 (IM) SDK。本节介绍如何在 Xcode 创建项目并集成这两个 SDK:
-
参考 Create a project 创建一个新的项目,Application 选择 App,Interface 选择 Storyboard,Language 选择 Swift。
信息如果你没有添加过开发团队信息,会看到 Add account... 按钮。点击该按钮并按照屏幕提示登入 Apple ID,点击 Next,完成后即可选择你的 Apple 账户作为开发团队。
-
为你的项目设置自动签名。
-
设置部署你的 App 的目标设备。
-
添加项目的设备权限。在项目导航栏中打开
info.plist
文件,编辑属性列表,添加以下属性:key type value Privacy - Microphone Usage Description String 使用麦克风的目的,例如 for a live interactive streaming Privacy - Camera Usage Description String 使用摄像头的目的,例如 for a live interactive streaming 信息- 如果你的项目中需要添加第三方插件或库(例如第三方摄像头),且该插件或库的签名与项目的签名不一致,你还需勾选 Hardened Runtime > Runtime Exceptions 中的 Disable Library Validation。
- 更多注意事项,可以参考 Preparing Your App for Distribution。
-
将声网实时互动和即时通讯 SDK 集成到你的项目。开始前请确保你已安装 CocoaPods,如尚未安装 CocoaPods,参考 Getting Started with CocoaPods 安装说明。
-
在终端里进入项目根目录,并运行
pod init
命令。项目文件夹下会生成一个Podfile
文本文件。 -
打开
Podfile
文件,修改文件为如下内容。注意将Your App
替换为你的 Target 名称。Rubyplatform :ios, '11.0'
target 'Your App' do
# 集成 RTC SDK
# x.y.z 请填写具体的 SDK 版本号,如 4.4.1
# 可通过实时互动发版说明获取最新版本号
pod 'AgoraRtcEngine_iOS', 'x.y.z'
# 集成即时通讯 SDK
pod 'Agora_Chat_iOS'
end
-
-
在终端内运行
pod install
命令安装 SDK。成功安装后,Terminal 中会显示Pod installation complete!
。
实现语聊房
你需要声网实时互动 (RTC) SDK、即时通讯 (IM) SDK 和云服务 (Service) 共同搭建语聊房场景。其中:
- 实时互动 SDK 承担实时音频的业务。
- 即时通讯 SDK 实现房间内的信令通信。
- 云服务 (Service) 实现了房间列表的存储和房间生命周期的管理。
本节会详细介绍如何调用声网云服务(voiceServiceProtocol
)、IM SDK 和 RTC SDK 的 API 完成登录即时通讯系统、获取房间列表、创建房间、进入房间、加入 RTC 房间、离开 RTC 房间等关键逻辑。完整的调用时序可以参考 API 时序图。
声网云服务为内部自研服务,暂不对外提供。你可以调用声网云服务的 API 用于测试,但是对于正式环境,声网建议你参考文档自行实现相似的一套服务。如需协助,请联系技术支持。
1. 获取房间列表
调用声网云服务中 voiceServiceProtocol
类的 fetchRoomList
方法获取房间列表。获取到房间列表后刷新 UI 并将房间列表展示在界面上。
ChatRoomServiceImp.getSharedInstance().fetchRoomList(page: 0) { error, rooms in
self.roomList.refreshControl?.endRefreshing()
if error == nil {
guard let rooms = rooms else {return}
let roomsEntity: VRRoomsEntity = VRRoomsEntity()
roomsEntity.rooms = rooms
roomsEntity.total = rooms.count
self.fillDataSource(rooms: roomsEntity)
self.roomList.reloadData()
self.empty.isHidden = (rooms.count > 0)
} else {
self.view.makeToast("\(error?.localizedDescription ?? "")")
}
}
2. 登录即时通讯系统
参考如下步骤登录即时通讯 (IM) 系统:
- 根据前提条件开启声网即时通讯服务,并获取登录即时通讯系统所需的用户名 (ID) 和 Token。
- 调用声网即时通讯(IM)SDK 中
AgoraChatClient
类的loginWithUsername:token:completion:
方法并传入即时通讯服务的用户名和 Token 以登录即时通讯系统。
@objc public func loginIM(userName: String, token: String, completion: @escaping (String, AgoraChatError?) -> Void) {
if AgoraChatClient.shared().isLoggedIn {
completion(AgoraChatClient.shared().currentUsername ?? "", nil)
} else {
// 登录即时通讯系统
// 此处的 Token 为声网 Chat Token
// 不要和声网 RTC Token 混淆
AgoraChatClient.shared().login(withUsername: userName, token: token, completion: completion)
}
}
3. 初始化 RtcEngine
参考如下步骤初始化 RtcEngine
:
- 根据开通服务在声网控制台创建声网项目后,复制界面的 App ID。
- 调用声网 RTC SDK 中的
sharedEngineWithAppId
方法创建并初始化AgoraRtcEngineKit
。
let rtcKit: AgoraRtcEngineKit = AgoraRtcEngineKit.sharedEngine(withAppId: KeyCenter.AppId, delegate: nil)
4. 创建并进入房间
参考如下步骤创建并进入房间:
-
调用
ChatRoomServiceImp
类中的createRoom
方法创建一个房间。SwiftChatRoomServiceImp.getSharedInstance().createRoom(room: entity) { error, room in
SVProgressHUD.dismiss()
self.view.window?.isUserInteractionEnabled = true
if let room = room,error == nil {
self.entryRoom(room: room)
} else {
SVProgressHUD.showError(withStatus: "Create failed!".localized())
}
} -
调用
ChatRoomServiceImp
类的joinRoom
方法进入房间。Swift// 显示加载提示
SVProgressHUD.show(withStatus: "Loading".localized())
// 生成声网 RTC Token
// 不要和声网 Chat Token 搞混淆
NetworkManager.shared.generateToken(channelName: room.channel_id ?? "", uid: VLUserCenter.user.id, tokenType: .token007, type: .rtc) { token in
VLUserCenter.user.agoraRTCToken = token ?? ""
// 进入房间
ChatRoomServiceImp.getSharedInstance().joinRoom(room.room_id ?? "") { error, room_entity in
SVProgressHUD.dismiss()
if VLUserCenter.user.chat_uid.isEmpty || VLUserCenter.user.im_token.isEmpty || self.initialError != nil {
SVProgressHUD.showError(withStatus: "Fetch IMconfig failed!")
return
}
self.mapUser(user: VLUserCenter.user)
let info: VRRoomInfo = VRRoomInfo()
info.room = room
info.mic_info = nil
self.isDestory = false
let vc = VoiceRoomViewController(info: info)
self.navigationController?.pushViewController(vc, animated: true)
self.normal.roomList.isUserInteractionEnabled = true
}
} -
语聊房里需要有消息聊天和语音聊天,因此你还需进行如下操作:
-
调用声网 IM SDK 中
joinChatRoom
实现房间内的消息互动。方法中的参数含义和支持取值请参考joinChatRoom
。Swift// 实现房间内的消息互动
@objc func joinedChatRoom(roomId: String, completion: @escaping ((AgoraChatroom?, AgoraChatError?) -> Void)) {
AgoraChatClient.shared().roomManager?.joinChatroom(roomId, completion: { room, error in
if error == nil, let id = room?.chatroomId {
self.currentRoomId = id
}
completion(room, error)
})
} -
调用声网 RTC SDK 中
AgoraRtcEngineKit
类的joinChannelByToken
加入 RTC 频道以实现房间内的实时音频通话。方法中的参数含义和支持取值请参考joinChannelByToken
。在这一步里需要填写声网 RTC Token。你可以使用开通服务中获取的临时 Token,也可以参考使用 Token 鉴权获取正式用途的声网 RTC Token。临时 Token 的有效期为 24 小时,建议你仅在测试用途下使用。你还可以调用
setChannelProfile
、setAudioProfile
、setAudioScenario
、setParameters
来为不同业务场景(语聊社交、KTV、游戏陪玩、专业音频直播场景)设置语聊房的最佳音效。Swift// 实现房间内的语音互动
rtcKit.delegate = self
rtcKit.enableAudioVolumeIndication(200, smooth: 3, reportVad: true)
self .setParametersWithMD()
// 在线 K 歌房和泛娱乐社交场景下推荐设置
if type == .ktv || type == .social {
// 设置频道属性为直播
rtcKit.setChannelProfile(.liveBroadcasting)
// 设置 48 kHz 采样率,音乐编码,单声道,编码码率最大值为 96 Kbps
rtcKit.setAudioProfile(.musicHighQuality)
// 设置为高音质场景
rtcKit.setAudioScenario(.gameStreaming)
} else if type == .game {
// 1 对 1 游戏陪玩通话场景下推荐
// 设置频道属性为通信
rtcKit.setChannelProfile(.communication)
} else if type == .anchor {
// 专业音频直播场景下推荐设置
// 设置频道属性为直播
rtcKit.setChannelProfile(.liveBroadcasting)
// 指定 48 kHz 采样率,音乐编码,双声道,编码码率最大值为 128 Kbps
rtcKit.setAudioProfile(.musicHighQualityStereo)
// 设置为高音质场景
rtcKit.setAudioScenario(.gameStreaming)
// 设置私有参数以获得好的实时音频互动体验
rtcKit.setParameters("{\"che.audio.custom_payload_type\":73}")
rtcKit.setParameters("{\"che.audio.custom_bitrate\":128000}")
rtcKit.setParameters("{\"che.audio.input_channels\":2}")
}
setAINS(with: .mid)
rtcKit.setParameters("{\"che.audio.start_debug_recording\":\"all\"}")
rtcKit.setEnableSpeakerphone(true)
rtcKit.setDefaultAudioRouteToSpeakerphone(true)
// 加入 RTC 频道
// 此处的 Token 为声网 RTC Token
let code: Int32 = rtcKit.joinChannel(byToken: token, channelId: channelName, info: nil, uid: UInt(rtcUid ?? 0))
-
5. 麦位管理
具体步骤详见麦位管理。
6. 退出房间
参考如下步骤退出并销毁语聊房。
-
调用
ChatRoomServiceImp
类的leaveRoom
方法离开房间。SwiftChatRoomServiceImp.getSharedInstance().leaveRoom(self.roomInfo?.room?.room_id ?? "") { _, _ in
} -
调用
AgoraRtcEngineKit
类的leaveChannel
方法离开 RTC 频道。SwiftrtcKit.leaveChannel(nil)
-
调用
leaveChatroom:completion:
离开聊天室,调用destroyChatroom:
销毁聊天室。调用destroy
销毁 RTC 引擎。SwiftAgoraChatClient.shared().roomManager?.leaveChatroom(currentRoomId, completion: { error in
})
AgoraChatClient.shared().roomManager?.destroyChatroom(currentRoomId)
AgoraRtcEngineKit.destroy()
rtcKit.delegate = nil
API 时序图
如下时序图展示了如何登录即时通讯系统、获取房间列表、创建房间、进入房间、加入 RTC 频道、麦位管理、退出房间、离开 RTC 频道。