# 通话操作
本文将介绍坐席基于 Juphoon RTC SDK 提供的通话操作能力实现的功能。
# 1. 通话属性变化
通话属性变化通过实现 JRTCAgentCallback (opens new window) 中的 onCallPropertyChanged (opens new window) 接口上报
/**
* 通话属性改变回调
* @note
* 重点关注屏幕共享,即当{@link JRTCRoomPropChangeParam.screenShare screenShare} 属性为 true 时,去处理屏幕共享相关事件。<br>
* 可根据 {@link JRTCGuest.shareStreamId shareStreamId} 和 {@link JRTCGuest.shareUserId shareUserId} 属性进行屏幕共享画面的渲染和停止渲染。
* @param changeParam 通话改变的属性
*/
- (void)onCallPropertyChanged:(JRTCRoomPropChangeParam *)changeParam;
示例代码:
- (void)onCallPropertyChanged:(JRTCRoomPropChangeParam *)changeParam;
if(changeParam.uploadAudio) {
//上传声音状态是否变化
} else if(changeParam.uploadVideo) {
//上传视频状态是否变化
} else if(changeParam.audioOut) {
//输出声音状态是否变化
} else if(changeParam.cdnState) {
//CDN推流状态是否变化
} else if(changeParam.remoteRecordState) {
//远程录制状态是否变化
} else if(changeParam.screenShare) {
//屏幕共享状态是否变化
}
}
通话属性变化详见 JRTCRoomPropChangeParam (opens new window) 。 其中对应通话属性的 bool 值,有变化的为 true,没有变化为 false。
# 2. 成员属性变化
成员属性变化通过实现 JRTCAgentCallback (opens new window) 中的 onMemberUpdate (opens new window) 接口上报。
/**
* 通话中成员属性更新回调
*
* 常用的有 {@link JRTCRoomParticipantChangeParam.volume 音量值}、{@link JRTCRoomParticipantChangeParam.audio 音频上传状态}、{@link JRTCRoomParticipantChangeParam.video 视频上传状态}等。<br>
* 例如当通话中有成员关闭视频传输,通话中所有成员都会收到此回调。
* @param participant 属性更新的成员对象
* @param changeParam 更新的属性对象
*/
- (void)onMemberUpdate:(JRTCRoomParticipant *)participant changeParam:(JRTCRoomParticipantChangeParam *)changeParam;
示例代码:
- (void)onMemberUpdate:(JRTCRoomParticipant *)part changeParam:(JRTCRoomParticipantChangeParam *)changeParam {
if (changeParam.video) {
if (part.video) {
// 视频流打开
} else {
// 视频流关闭
}
}
if (changeParam.audio) {
if (part.audio) {
// 音频流打开
} else {
// 音频流关闭
}
}
}
成员属性变化详见 JRTCRoomParticipantChangeParam (opens new window) 。 其中有对应成员属性的 bool 值,有变化的为 true,没有变化为 false 。
# 3. 获取所有通话成员
通过 participants (opens new window) 获取所有参会者成员,JRTCRoomParticipant (opens new window) 详见API文档。
/**
* 所有成员(包含自己、访客和其他坐席)
*/
@property (nonatomic, readonly, strong) NSArray <JRTCRoomParticipant *> *participants;
示例代码:
NSArray <JRTCRoomParticipant *> *participants = _agent.participants;
# 4. 获取访客成员
SDK 支持邀请三方座席(座席端功能)进入通话,可以通过以下接口获取所有访客成员列表,以及获取主访客成员。
/**
* 获取主访客成员
*
* 只有在通话中才能获得访客成员对象,否则为 nil
*/
@property (nonatomic, readonly, strong) JRTCRoomParticipant *mainGuestParticipant;
/**
* 访客成员列表
*
* 只有在通话中且通话中才能获得含有访客成员对象的数组,否则为空数组 <br>
* 当通话中不存在第三方访客时,获得一个仅含有主访客成员对象的数组 <br>
* 当通话中存在第三方访客时,获得一个含有主访客和第三方访客成员对象的数组
*/
@property (nonatomic, readonly, strong) NSArray<JRTCRoomParticipant *> *guestParticipants;
示例代码:
// 获取主访客对象
JRTCRoomParticipant *guest = _agent.mainGuestParticipant;
// 获取访客成员列表
NSArray<JRTCRoomParticipant *> *guestList = _agent.agentParticipants;
# 5. 获取自己对象
/**
* 获取自己对象
*
* @return 自己对象
*/
@property (nonatomic, strong, readonly) JRTCRoomParticipant *selfParticipant;
示例代码:
JRTCRoomParticipant *selfParticipant = _agent.selfParticipant;
# 6. 是否主座席
/**
* 是否主座席
*
* @return
* - true 主座席
* - false 其他三方座席
*/
@property (nonatomic, readonly, assign) bool isMainAgent;
示例代码:
// 是否主座席
_agent.isMainAgent;
# 7. 通话保持/取回
通话中座席可发起保持通话的操作,保持通话之后座席和访客皆停发音视频数据,双方将互相听不到声音看不到视频画面。
座席可以调用 setHoldState (opens new window) 接口保持/取回通话。
/**
* 保持/取回
*
* 可以通过 {@link getHoldState} 获取当前通话保持状态 <br>
* 保持通话后双方互相停止音视频流的发送与接收
* @param hold 保持或取回
* - true: 设置为保持状态
* - false: 设置为取回状态
* @return 接口调用结果
* - true: 接口调用成功,通话中的所有成员将会收到 {@link JRTCGuestCallback.onHoldStateChanged: onHoldStateChanged} 或 {@link JRTCAgentCallback.onHoldStateChanged: onHoldStateChanged} 回调
* - false: 接口调用异常
*/
- (bool)setHoldState:(bool)hold;
座席可以调用 getHoldState (opens new window) 获取当前通话保持状态。
/**
* 获取当前通话保持状态
*
* 座席可调用 {@link JRTCAgent.setHoldState: setHoldState} 接口修改当前通话的保持状态。
* @return 当前通话保持状态
* - true: 当前通话状态为保持
* - false: 当前通话状态为取回
*/
- (bool)getHoldState;
座席发起通话保持之后,通话中的所有成员都将收到 onHoldStateChanged (opens new window) 通话被保持的回调。
/**
* 收到通话保持或取回的回调
*
* 通话中座席可调用 {@link JRTCAgent.setHoldState: setHoldState} 接口保持通话或取回通话,通话中所有成员都会收到此回调。
* @param hold true 表示通话被保持,false 表示通话取回
*/
- (void)onHoldStateChanged:(bool)hold;
示例代码:
// 保持
[_agent setHoldState:true];
// 取回
[_agent setHoldState:false];
// 通话保持状态改变
- (void)onHoldStateChanged:(bool)hold {
if (hold == true) {
// 通话保持
} else {
// 通话取回
}
}
// 主动获取通话保持状态
bool hold = [_agent getHoldState];
if (hold == true) {
// 通话保持
} else {
// 通话取回
}
# 8. 音视频切换
通话中座席与访客皆可发起音视频通话切换的操作。
视频通话状态下座席访客互相可听到对方声音看到视频画面,语音通话状态下座席访客只能听到对方声音,看不到对方视频画面。
座席可以调用 turnCallType (opens new window) 接口进行音视频通话切换。
/**
* 音视频通话切换
*
* 可以通过 {@link getCallType} 接口获取当前的通话类型 <br>
* 通话中所有成员都将收到{@link JRTCGuestCallback.onCallTypeChanged: onCallTypeChanged} 或 {@link JRTCAgentCallback.onCallTypeChanged: onCallTypeChanged} 回调
* @param callType 通话类型
* - @ref CallTypeAudio: 语音通话
* - @ref CallTypeVideo: 视频通话
*/
- (void)turnCallType:(CallType)callType;
访客可以调用 getCallType (opens new window) 接口获取当前通话类型。
/**
* 获取当前通话类型
*
* 可通过 {@link turnCallType: turnCallType} 接口修改当前通话类型。
* @return 当前通话类型
* - @ref CallTypeAudio : 语音通话
* - @ref CallTypeVideo : 视频通话
*/
- (CallType)getCallType;
通话类型切换之后,参加通话的所有成员都将收到 onCallTypeChanged (opens new window) 通话类型切换的通知。
/**
* 音视频通话切换回调
*
* 通话中的访客和座席可分别调用 {@link JRTCGuest.turnCallType: turnCallType} 和 {@link JRTCAgent.turnCallType: turnCallType} 方法切换音视频通话模式,通话中所有成员都会收到此回调。
* @param callType 通话模式
* - @ref CallTypeAudio 语音通话模式
* - @ref CallTypeVideo 视频通话模式
*/
- (void)onCallTypeChanged:(CallType)callType;
示例代码:
// 切换到语音通话
[_agent turnCallType:CallTypeAudio];
// 切换到视频通话
[_agent turnCallType:CallTypeVideo];
// 获取当前通话类型
CallType callType = [_agent getCallType];
if (callType == CallTypeAudio) {
// 当前为语音通话
} else if (callType == CallTypeVideo) {
// 当前为视频通话
}
// 音视频通话切换回调
- (void)onCallTypeChanged:(CallType)callType {
if (callType == CallTypeAudio) {
// 切换为语音通话
} else if (callType == CallTypeVideo) {
// 切换为视频通话
}
}
# 9. 通话转接
在通话过程中将通话转给其他座席。可以指定座席或指定座席所在的业务组,如指定业务组将会随机选择业务组中一个空闲座席进行转接。
座席可调用 transferCall (opens new window) 接口进行通话转接。
/**
* 通话转接
*
* 支持转接到具体座席和转接到某个业务组 <br>
* 转接结果通过 {@link JRTCAgentCallback.onTransferCallResult:result: onTransferCallResult} 回调上报 <br>
* 座席调用转接接口成功时,访客会收到 {@link JRTCGuestCallback.onCallForwarding onCallForwarding} 回调
* @param type 转接类型,转接到具体座席或是转接到业务组
* - @ref TransferTypeGroup 转接到业务组
* - @ref TransferTypeStuff 转接到具体座席
* @param toUserId
* - 当转接类型为 @ref TransferTypeGroup 时,toUserId 需传入业务组号
* - 当转接类型为 @ref TransferTypeStuff 时,toUserId 需传入座席用户ID
* @return 接口调用结果
* - > 0: 操作id,对应 {@link JRTCAgentCallback.onTransferCallResult:result: onTransferCallResult} 回调的 operationId 参数
* - -1: 接口调用异常
*/
- (int)transferCall:(TransferType)type toUserId:(NSString *)toUserId;
转接接口调用成功时,转接结果会通过 JRTCAgentCallback (opens new window)的 onTransferCallResult (opens new window) 回调通知到座席。
/**
* 通话转接回调
*
* 调用 {@link JRTCAgent.transferCall:toUserId: transferCall} 接口将通话转接给其他座席或业务组时,会收到此回调。
* @param operationId 操作id,对应 {@link JRTCAgent.transferCall:toUserId: transferCall} 接口的返回值
* @param result 通话转接结果
* - true: 转接成功
* - false: 转接失败
*/
- (void)onTransferCallResult:(int)operationId result:(bool)result;
转接成功,访客会收到 JRTCGuestCallback (opens new window) 的 onCallForwarding (opens new window) 回调。
/**
* 座席通话转接回调
*
* 通话中座席调用 {@link JRTCAgent.transferCall:toUserId: transferCall} 接口将通话转接到某个座席或转接到某个业务组后,访客会收到此回调,然后访客需等待新的座席接听该通话。<br>
* 该过程中,访客通话状态不变,新的座席接听通话后,访客可通过 {@link onMemberJoin: onMemberJoin} 回调得知。
*/
- (void)onCallForwarding;
示例代码:
// 转接到指定坐席
[_agent transferCall:TransferTypeStuff toUserId:@"agent1"];
// 转接到业务组
[_agent transferCall:TransferTypeGroup toUserId:@"10086"];
// 通话转接结果回调
- (void)onTransferCallResult:(int)operationId result:(bool)result {
if (result == true) {
// 发起转接成功
} else {
// 发起转接失败
}
}
# 10. 单向视频
单向视频发起流程:
- 座席可通过调用 requestOnewayVideo (opens new window) 接口单向打开/关闭视频。
- 访客通过实现 JRTCGuestCallback (opens new window) 的 onOnewayVideoChanged (opens new window) 接口接受单向视频请求通知;
- 访客端应用层自行实现单向视频的功能,比如将对应的座席的视频画面进行遮挡,使访客无法看到座席画面;
/**
* 请求单向视频
*
* 座席调用此接口后,会向全体访客发送单向视频请求,访客会收到 {@link JRTCGuestCallback.onOnewayVideoChanged: onOnewayVideoChanged} 回调 <br>
* 应用需要自行实现单向视频功能,例如访客用图片遮挡该座席画面,SDK不会对画面进行单向处理
* @param turnOn 打开或关闭单向视频
* - true: 打开单向视频
* - false: 关闭单向录制
*/
- (void)requestOnewayVideo:(bool)turnOn;
示例代码:
// 请求单向视频
[_agent requestOnewayVideo:true];
// 取消单向视频
[_agent requestOnewayVideo:false];
# 11. 获取随路参数
访客呼叫时携带的额外信息,可以在座席收到来电通知 onCallStateChanged (opens new window) 回调中的 inviter 参数对象获取。
/**
* 通话状态改变回调
* @param type 通话状态改变类型,即以下情况会收到此回调:
* - @ref AgentCallStateChangeTypeIncoming 收到来电(访客呼叫、座席邀请、转接)
* - @ref AgentCallStateChangeTypeTalking 通话接通
* - @ref AgentCallStateChangeTypeTermed 通话挂断或被挂断
* @param incomingType 来电类型,当 type == {@link AgentCallStateChangeTypeIncoming} 时有效
* @param inviter 邀请成员对象,当 type == {@link AgentCallStateChangeTypeIncoming} 时有效
* @param reason 挂断原因,只在 type 为 @ref AgentCallStateChangeTypeTermed 时需要关注,详见 @ref CallTermReason
*/
- (void)onCallStateChanged:(AgentCallStateChangeType)type incomingType:(CallIncomingType)incomingType inviter:(nullable JRTCInviter *)inviter reason:(CallTermReason)reason;
示例代码:
- (void)onCallStateChanged:(AgentCallStateChangeType)type incomingType:(CallIncomingType)incomingType inviter:(nullable JRTCInviter *)inviter reason:(CallTermReason)reason {
if (type == AgentCallStateChangeTypeIncoming) {
//收到来电
NSString *extra = inviter.extraInfo;
}
}
# 12. 切换自己在通话中角色
/**
* 切换自己在通话中角色
*
* @note 需要先进入通话,目前只支持从观察者座席角色切换到主座席角色
*
* @param partRole 通话成员角色,目前只支持
* - @ref PartRoleTypeMainAgent : 主座席
* - @ref PartRoleTypeAgent : 次座席
* @return 接口调用结果
* - > 0: 操作id,对应 {@link JRTCAgentCallback.onSwitchPartRoleResult:operationId:error: onSwitchPartRoleResult} 回调的 operationId 参数
* - -1: 接口调用异常
*/
- (int)switchPartRole:(PartRoleType)partRole;
# 13. 踢出通话成员
/**
* 踢出通话成员
* @note 只有主座席角色可以使用该功能
*
* @param userId 成员用户ID
* @return 接口调用结果
* - > 0: 操作id,对应 {@link JRTCAgentCallback.onKickParticipantResult:operationId:error: onKickParticipantResult} 回调的 operationId 参数
* - -1: 接口调用异常
*/
- (int)kickParticipant:(NSString *)userId;