本文介绍如何实现语聊房。
声网在 agora-ent-scenarios 仓库中提供语聊房(普通版)源代码供你参考。
本节展示语聊房中常见的业务流程。
下图展示创建、进入、退出房间的流程。
下图展示房主邀请听众上麦的流程。在这个流程中,房主发起上麦邀请,如果听众接受邀请,房主会收到通知。听众上麦并修改麦位,然后发布自己的音频流。
下图展示听众向房主申请上麦的流程。在这个流程中,听众主动发起上麦申请,如果房主接受申请,房主修改麦位信息以让听众上麦。听众收到上麦消息后,发布自己的音频流。
声动语聊用到声网 RTC SDK 和即时通讯(IM)SDK。本节介绍如何在 Xcode 创建项目并集成这两个 SDK:
创建一个新的项目,Application 选择 App,Interface 选择 Storyboard,Language 选择 Swift。
为你的项目设置自动签名。
设置部署你的 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 |
将声网 RTC 和即时通讯 SDK 集成到你的项目。开始前请确保你已安装 CocoaPods,如尚未安装 CocoaPods,参考 Getting Started with CocoaPods 安装说明。
在终端里进入项目根目录,并运行 pod init
命令。项目文件夹下会生成一个 Podfile
文本文件。
打开 Podfile
文件,修改文件为如下内容。注意将 Your App
替换为你的 Target 名称。
platform :ios, '11.0'
target 'Your App' do
# 集成 RTC SDK
# x.y.z 请填写具体的 SDK 版本号,如 4.0.1 或 4.0.0.4。
# 可通过互动直播发版说明获取最新版本号。
pod 'AgoraRtcEngine_iOS', 'x.y.z'
# 集成即时通讯 SDK
pod 'Agora_Chat_iOS'
end
在终端内运行 pod install
命令安装 SDK。成功安装后,Terminal 中会显示 Pod installation complete!
。
如下时序图展示了如何登录即时通讯系统、获取房间列表、创建房间、进入房间、加入 RTC 频道、麦位管理、退出房间、离开 RTC 频道。声网云服务(Service)实现了房间列表的存储和房间生命周期的管理,声网即时通讯(IM)SDK 实现房间内的信令通信,声网 RTC SDK 承担实时音频的业务。本节会详细介绍如何调用声网云服务(ChatRoomServiceProtocol
)、IM SDK API、RTC SDK API 完成这些逻辑。
调用声网云服务中 ChatRoomServiceImp
类的 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 ?? "")")
}
}
参考如下步骤登录即时通讯(IM)系统:
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)
}
}
参考如下步骤初始化 AgoraRtcEngineKit:
sharedEngineWithAppId
方法初始化 AgoraRtcEngineKit
。let rtcKit: AgoraRtcEngineKit = AgoraRtcEngineKit.sharedEngine(withAppId: KeyCenter.AppId, delegate: nil)
调用 ChatRoomServiceImp
类中的 createRoom
方法创建一个房间。
ChatRoomServiceImp.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
方法进入房间。
// 显示加载提示
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
。
// 实现房间内的消息互动
@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。你可以参考开始使用声网平台从声网控制台获得临时用途的声网 RTC Token。你也可以参考使用 Token 鉴权获取正式用途的声网 RTC Token。临时 Token 的有效期为 24 小时,建议你仅在测试用途下使用。
你还可以调用 setChannelProfile
、setAudioProfile
、setAudioScenario
、setParameters
来为不同业务场景(语聊社交、KTV、游戏陪玩、专业音频直播场景)设置语聊房的最佳音效。
// 实现房间内的语音互动
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))
具体步骤详见麦位管理。
调用 ChatRoomServiceImp
类的 leaveRoom
方法离开房间。
ChatRoomServiceImp.getSharedInstance().leaveRoom(self.roomInfo?.room?.room_id ?? "") { _, _ in
}
调用 AgoraRtcEngineKit
类的 leaveChannel
方法离开 RTC 频道。
rtcKit.leaveChannel(nil)
调用 leaveChatroom:completion:
离开聊天室,调用 destroyChatroom:
销毁聊天室。调用 destroy
销毁 RTC 引擎。
AgoraChatClient.shared().roomManager?.leaveChatroom(currentRoomId, completion: { error in
})
AgoraChatClient.shared().roomManager?.destroyChatroom(currentRoomId)
AgoraRtcEngineKit.destroy()
rtcKit.delegate = nil