前言
鉴于公司项目接入的极光IM的音视频聊天无法实现视频会议及踢人的相关功能。因此更换了音视频的相关第三方库。而环信提供了音视频会议的功能且环信的音视频功能就是基于Agroa的功能进行了二次封装。然后在此总结一下自己使用Agroa集成的一些流程及问题。
需要用到的技术文档
Agroa
的音视频聊天主要用到了三部分的技术支持。
- 语音通话
- 视频通话
- 云信令(原实时消息)
实现视频通话
做过音视频通话的应该都很清楚视频
和语音
通话唯一的区别
就是在于是否显示对方的实时视频流
。因此本文档只提供一下关于视频通话
的实现流程。
在Agroa官网创建一个新的项目
注册一个Agroa的账号
创建一个新的项目
-
去到项目管理页面
-
创建一个新的项目
项目名称
及使用场景
可以自行的去填写和选择一下。鉴权机制
直接选择默认的下面的这种模式就可以了。关于鉴权机制
具体的相关内容会随着后面的使用过程中慢慢的了解到的。在此就不在过多的说明了 -
配置项目信息(申请语音视频的通话频道)
在完成第二步的项目创建后实际是我们在自己测试的过程中还是无法实现语音、视频通话
的即使是配置了相关的语音视频协议
也是不行的。这是因为我们使用了调试模式
如果需要去做语音和视频通话
的功能需要先去申请一个频道
。
此处我们需要开启主要证书。 -
删除“无证书”(也可以选择不删除)
将无证书
删除后用户就无法直接登录
,项目正式上线后需要删除掉无证书
。而我个人在使用过程中是直接将无证书
给删除掉了的。
此处我已经将无证书
给删除掉了。而上面的次要证书
是在你开启主要证书
后自动生成的。 -
申请音视频的临时通话频道
通过主要证书
下的生成临时音视频token
进行申请
此处需要保留的信息是频道名
和临时Token
。
到此关于项目需要的一些前置的准备信息已经完成了
集成云信令的SDK
- 通过
pod
导入AgoraRtm_iOS
的库文件 - 下载官方项目然后将项目中的
SDK
导入到项目中
Agora RTM iOS SDK
登录云信令账号
云信令的账号不存在注册的情况。用户名可以自己随便填写
let kit = AgoraRtmKit(appId: "项目appId", delegate: self)
kit.login(byToken: "生成的byToken", user: "下面生成token使用到的uid", completion: {[weak self] code in
if code == .ok{
print("登录成功")
}
})
此处的kit使用的是一个局部变量。在正常的使用过程中要将kit设置成全局变量,因为这个属性在后续发起音视频聊天的时候需要用到这个kit
关于byToken
因为已经删除掉了项目中的无证书
,如果此处不填写byToken
是无法登录的,不删除无证书
可以不去填写此处的东西。
byToken
的生成网址
appID
-
appCertificate
项目主要证书的key -
uid
要用来登录的用户名
发起视频邀请
导入视频通话的sdk
- pod 'AgoraRtcEngine_iOS'
- 官网下载SDK
AgoraRtcEngine_iOS下载地址
-
发起视频通话
1.创建用户界面
- 本地视频窗口
- 远端视频窗口
2.导入类
在调用 Agora API 前,你需要在项目中导入 AgoraRtcKit 类,并定义一个 agoraKit 变量。
import AgoraRtcKit
class ViewController: UIViewController {
...
// 定义 agoraKit 变量
var agoraKit: AgoraRtcEngineKit?
}
3. 初始化 AgoraRtcEngineKit 对象
调用 sharedEngineWithAppId 创建并初始化 AgoraRtcEngineKit 对象。你需要将 YourAppID 替换为你的 Agora 项目的 App ID。
func initializeAgoraEngine() {
agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: "YourAPPID", delegate: self)
}
4. 设置本地视图
在加入频道前设置本地视图,以便在通话中看到本地图像
func setupLocalVideo() {
// 启用视频模块
agoraKit?.enableVideo()
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = 0
videoCanvas.renderMode = .hidden
videoCanvas.view = localView
// 设置本地视图
agoraKit?.setupLocalVideo(videoCanvas)
}
5. 加入频道
func joinChannel(){
// 频道内每个用户的 uid 必须是唯一的
agoraKit?.joinChannel(byToken: "YourToken", channelId: "YourChannelName", info: nil, uid: 0, joinSuccess: { (channel, uid, elapsed) in
})
}
此处channelId
使用的是申请音视频的临时通话频道
添加的频道id
给远端用户发送邀请
let localInvitation = AgoraRtmLocalInvitation.init(calleeId: "要邀请的用户uid")
localInvitation.channelId = "频道id"
localInvitation.content = "语音通话"
self.kit?.getRtmCall()?.send(localInvitation, completion: { code in
if code == .ok{
print("userb邀请成功")
}
})
//如果需要邀请多个人的话可以如下这样继续添加
let localInvitation1 = AgoraRtmLocalInvitation.init(calleeId: "要邀请的用户uid")
localInvitation1.channelId = "1234"
localInvitation1.content = "语音通话"
self.kit?.getRtmCall()?.send(localInvitation1, completion: { code in
if code == .ok{
print("userb邀请成功")
}
})
远端用户加入频道
远端用户收到通话邀请的监听
var invitaCallKit : AgoraRtmCallKit?
var invitaAgoraRtm : AgoraRtmRemoteInvitation?
/// 收到通话邀请
/// - Parameters:
/// - callKit: <#callKit description#>
/// - remoteInvitation: <#remoteInvitation description#>
func rtmCallKit(_ callKit: AgoraRtmCallKit, remoteInvitationReceived remoteInvitation: AgoraRtmRemoteInvitation) {
print("收到通话邀请")
self.invitaCallKit = callKit
self.invitaAgoraRtm = remoteInvitation
acceptBtn.isHidden = false
}
var invitaCallKit : AgoraRtmCallKit?
var invitaAgoraRtm : AgoraRtmRemoteInvitation?
self.invitaCallKit!.accept(self.invitaAgoraRtm!) { code in
print("点击了接收邀请")
}
本地端收到用户加入频道
// 监听 didJoinedOfUid 回调
// 远端用户加入频道时,会触发该回调
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = uid
videoCanvas.renderMode = .hidden
videoCanvas.view = remoteView
// 设置远端视图
agoraKit?.setupRemoteVideo(videoCanvas)
}
关于云信令需要用到的相关代理方法
云信令主要是实现呼叫邀请
相关的代理
-
iOS
-
Android
/// 收到通话邀请
/// - Parameters:
/// - callKit: <#callKit description#>
/// - remoteInvitation: <#remoteInvitation description#>
func rtmCallKit(_ callKit: AgoraRtmCallKit, remoteInvitationReceived remoteInvitation: AgoraRtmRemoteInvitation) {
print("收到通话邀请")
self.invitaCallKit = callKit
self.invitaAgoraRtm = remoteInvitation
acceptBtn.isHidden = false
}
func rtmCallKit(_ callKit: AgoraRtmCallKit, remoteInvitationFailure remoteInvitation: AgoraRtmRemoteInvitation, errorCode: AgoraRtmRemoteInvitationErrorCode) {
print("对端呼叫邀请失败")
}
//被叫方收到被叫接收邀请 -> 被叫方自己接收到自己加入频道的
func rtmCallKit(_ callKit: AgoraRtmCallKit, remoteInvitationAccepted remoteInvitation: AgoraRtmRemoteInvitation) {
self.agoraKit?.enableVideo()
let videoCanvas = AgoraRtcVideoCanvas()
videoCanvas.uid = 0
videoCanvas.renderMode = .hidden
videoCanvas.view = localView
agoraKit?.setupLocalVideo(videoCanvas)
self.agoraKit?.joinChannel(byToken: "006f5765e0372174c99a6cf50e93d0bd85cIAB6NOUbAUcVpaztm68yf76LAZ/S2iOiUYeik7SJ0SJK2KPg45sAAAAAEAAxc9bWck4HYgEAAQBxTgdi", channelId: "1234", info: nil, uid: UInt(arc4random()) % 100, joinSuccess: { channel, uid, elapsed in
print("被叫加入语音通话")
})
}
//主叫收到被叫接收邀请
func rtmCallKit(_ callKit: AgoraRtmCallKit, localInvitationAccepted localInvitation: AgoraRtmLocalInvitation, withResponse response: String?) {
print("被叫已接收邀请")
if joinNumber == 0 {
self.agoraKit?.joinChannel(byToken: "006f5765e0372174c99a6cf50e93d0bd85cIAB6NOUbAUcVpaztm68yf76LAZ/S2iOiUYeik7SJ0SJK2KPg45sAAAAAEAAxc9bWck4HYgEAAQBxTgdi", channelId: "1234", info: nil, uid: 0, joinSuccess: { [weak self] channel, uid, elapsed in
print("被叫加入语音通话")
self?.joinNumber = 1
})
}
// 发送取消邀请的功能
kit?.getRtmCall()?.cancel(localInvitation1, completion: { code in
print("userc 已经被我干掉了")
})
}
func rtmCallKit(_ callKit: AgoraRtmCallKit, remoteInvitationCanceled remoteInvitation: AgoraRtmRemoteInvitation) {
self.acceptBtn.isHidden = true
}
关于音视频中语音和视频流的开关装填设置
音视频流的相关设置参数主要是通过AgoraRtcEngineKit 类
实现的。
退出频道
agoraKit?.leaveChannel(nil)
销毁 AgoraRtcEngineKit 对象
AgoraRtcEngineKit.destroy()
后端生成token
token鉴权