Z1项目V2.1 新增功能【语音匹配】,下面是对该功能实现的分享内容
下图是对该功能实现的逻辑流程梳理:
在查看云信音视频产品文档,结合功能需求,实现语音匹配需要使用到2个技术点:
1、邀请机制 【简称信令】
2、音视频通话
注意:使用前先进行初始化,挂好各自的delegate:NIMSignalManagerDelegate、NERtcEngineDelegateEx,这个就不多说,点击上面蓝色可查看方法。
预埋一下信令的代理:
/**
在线通知
@param eventType 信令操作事件类型
@param notifyResponse 信令通知回调数据
@discussion 用于通知信令相关的在线通知 NIMSignalingEventType 1-8有效
*/
- (void)nimSignalingOnlineNotifyEventType:(NIMSignalingEventType)eventType
response:(NIMSignalingNotifyInfo *)notifyResponse{
}
信令通知事件定义类型
/**
* 信令通知事件定义类型
*/
typedef NS_ENUM(NSInteger, NIMSignalingEventType){
/**
* 关闭频道
*/
NIMSignalingEventTypeClose = 1,
/**
* 加入频道
*/
NIMSignalingEventTypeJoin = 2,
/**
* 邀请加入频道
*/
NIMSignalingEventTypeInvite = 3,
/**
* 取消邀请
*/
NIMSignalingEventTypeCancelInvite = 4,
/**
* 拒绝加入频道
*/
NIMSignalingEventTypeReject = 5,
/**
* 接受邀请
*/
NIMSignalingEventTypeAccept = 6,
/**
* 离开频道
*/
NIMSignalingEventTypeLeave = 7,
/**
* 自定义事件
*/
NIMSignalingEventTypeContrl = 8,
};
--------------------------------------------------------分割线-----------------------------------------------------
下面我们进行功能实现:
步骤1:本地服务器的开始匹配机制,获取匹配的用户信息accid、audioUid、token等内容
步骤2:发送匹配邀请信息
/**
呼叫
@param request 呼叫请求
@param completion 完成回调
@discussion 用于用户新开一个频道并邀请对方加入频道,该接口为组合接口,等同于用户先创建频道,成功后加入频道并邀请对方
@discussion 错误码 200:成功 10405:房间已存在 10201:对方云信不在线 10202:对方推送不可达。该接口是用户呼叫场景的组合接口封装,调用该接口,sdk底层分别会 创建、加入、邀请,再返回用户结果,其中任何一步失败,就返回失败(其中邀请返回10201和10202,认为是成功,返回码还是10201和10202给上层),失败时,sdk需要主动close。常用于但不限于点对点呼叫发起。
@discussion error的错误码为10201和10202时,返回的房间信息时有效的,需要用户主动close房间
*/
- (void)signalingCall:(NIMSignalingCallRequest *)request
completion:(nullable NIMSignalingCallBlock)completion;
使用以上一步完成创建,邀请方法
// 创建频道发送邀请
-(void)my_signalingCall{
NIMSignalingCallRequest *callRequest = [[NIMSignalingCallRequest alloc] init];
///对方accid,被邀请者的账号
callRequest.accountId = [MYPhoneTicMatchManager sharedMYPhoneTicMatchManager].vmUserModel.matchUserInfo.accid;
///自己在频道中对应的uid
callRequest.uid = [MYPhoneTicMatchManager sharedMYPhoneTicMatchManager].vmUserModel.userInfo.audioUid;
///通知事件额外字段,非必填
callRequest.customInfo = self.signalingCallcustomInfo;
///邀请唯一标识(用于标识持续呼叫),必填,长度必须小于128,超出会报参数错误
callRequest.requestId = NSStringFormat(@"%.0f",[[NSDate date] timeIntervalSince1970]);
///是否存离线,YES表示存离线,NO表示不存离线,非必填,默认为NO
callRequest.offlineEnabled = NO;
///频道类型,必填
callRequest.channelType = NIMSignalingChannelTypeAudio;
NIMSignalingPushInfo *pushInfo = [[NIMSignalingPushInfo alloc] init];
pushInfo.needPush = YES;
pushInfo.pushTitle = curUser.nickName;
pushInfo.pushContent = @"语音匹配";
callRequest.push = pushInfo;
[[NIMSDK sharedSDK].signalManager signalingCall:callRequest completion:^(NSError * _Nullable error, NIMSignalingChannelDetailedInfo * _Nullable response) {
/// 错误码 200:成功 10405:房间已存在 10201:对方云信不在线 10202:对方推送不可达
/// error的错误码为10201和10202时,返回的房间信息时有效的,需要用户主动close房间
if (error) {
// 错误例如:signalingCall--Error Domain=NIMRemoteErrorDomain Code=10202 "通用音视频协议:对方推送亦不可达" UserInfo={NSLocalizedDescription=通用音视频协议:对方推送亦不可达, enum=NIMRemoteErrorCodeSignalResPeerPushOffline}
APILog(@"signalingCall--%@",error.description);
if (error.code == 10201||error.code == 10202) {
[MYHUDTool showMessageText:@"该用户临时不在线,请重新匹配~"];
[self my_hiddenWindowView];
}
}else{
APILog(@"创建邀请成功");
self.callUser = YES;//拨打方
}
}];
}
完成邀请工作,并通过信令NIMSignalManagerDelegate监控邀请的反馈
步骤3:自动接受邀请
图上的B用户通过NIMSignalManagerDelegate收到邀请类型为NIMSignalingEventTypeInvite的携带通话信息信号
case NIMSignalingEventTypeInvite:
{
NIMSignalingInviteNotifyInfo *info = (NIMSignalingInviteNotifyInfo *)notifyResponse;
self.channelId = notifyResponse.channelInfo.channelId;
APILog(@"邀请加入频道");
{
///接受电话的人保存用户信息
NSString * customInfo = info.customInfo;
NSDictionary * dic = [self dictionaryWithJsonString:customInfo];
MYTicMatchUserModel * vmUserModel = [MYTicMatchUserModel yy_modelWithDictionary:dic];
self.vmUserModel = vmUserModel;
}
}
保存好通话信息后进行自动接受邀请【自动接受为项目需要可视情况而定】
/**
接受邀请
@param request 接受邀请请求
@param completion 完成回调
@discussion 接受频道接口
不开自动加入开关:该接口只接受邀请并告知邀请者,并同步通知自己的其他在线设备,但不会主动加入频道,需要单独调用加入接口
打开自动加入开关:该接口为组合接口,等同于先调用接受邀请,成功后再加入房间。
@discussion 错误码 200:成功 10404:房间不存在 10408:邀请不存在或已过期 10409:邀请已经拒绝 10410:邀请已经接受 10407:已经房间内 10420:已经在房间内(自己的其他端) 10419:房间人数超限 10417:uid冲突
*/
- (void)signalingAccept:(NIMSignalingAcceptRequest *)request
completion:(nullable NIMSignalingAcceptBlock)completion;
步骤4:完成步骤3后,用户A会检测到对方接受邀请的信号,类型为:NIMSignalingEventTypeAccept
此时用户A就开始进入创建音频频道,进入频道,等待对方进入。
* @param token 安全认证签名(NERTC Token)。可设置为:
- null。调试模式下可设置为 null。安全性不高,建议在产品正式上线前在云信控制台中将鉴权方式恢复为默认的安全模式。
- 已获取的NERTC Token。安全模式下必须设置为获取到的 Token 。若未传入正确的 Token 将无法进入房间。推荐使用安全模式。
* @param channelName 房间名称,设置相同房间名称的用户会进入同一个通话房间。<br>字符串格式,长度为1~ 64 字节。支持以下89个字符:a-z, A-Z, 0-9, space, !#$%&()+-:;≤.,>? @[]^_{|}~”
* @param uId 用户的唯一标识 id,房间内每个用户的 uId 必须是唯一的。
<br>uId 可选,默认为 0。如果不指定(即设为 0),SDK 会自动分配一个随机 uId,并在 NERtcJoinChannelCompletion 中返回,App 层必须记住该返回值并维护,SDK 不对该返回值进行维护。
- (void)onNERtcEngineUserDidJoinWithUserID:(uint64_t)userID
userName:(NSString *)userName
步骤5:完成步骤3后,用户B加入到用户A创建同一个信令频道中
APILog(@"接受邀请成功");
NIMSignalingJoinChannelRequest * signalingJoinChannelRequest = [[NIMSignalingJoinChannelRequest alloc] init];
signalingJoinChannelRequest.channelId = info.channelInfo.channelId;
[[NIMSDK sharedSDK].signalManager signalingJoinChannel:signalingJoinChannelRequest completion:^(NSError * _Nullable error, NIMSignalingChannelDetailedInfo * _Nullable response) {
}];
步骤6:完成步骤5后,用户B也开始进入到用户A已经创建的音频频道
* 加入音视频房间。
* <br>加入音视频房间时,如果指定房间尚未创建,云信服务器内部会自动创建一个同名房间。
* - SDK 加入房间后,同一个房间内的用户可以互相通话,多个用户加入同一个房间,可以群聊。使用不同 App Key 的 App 之间不能互通。
* - 成功调用该方加入房间后,远端会触发 onNERtcEngineUserDidJoinWithUserID 回调。
* - 用户成功加入房间后,默认订阅房间内所有其他用户的音频流,可能会因此产生用量并影响计费。如果想取消订阅,可以通过调用相应的 mute 方法实现。
* - 直播场景下的观众角色可以通过 switchChannelWithToken 快速切换房间。
* @param token 安全认证签名(NERTC Token)。可设置为:
- null。调试模式下可设置为 null。安全性不高,建议在产品正式上线前在云信控制台中将鉴权方式恢复为默认的安全模式。
- 已获取的NERTC Token。安全模式下必须设置为获取到的 Token 。若未传入正确的 Token 将无法进入房间。推荐使用安全模式。
* @param channelName 房间名称,设置相同房间名称的用户会进入同一个通话房间。<br>字符串格式,长度为1~ 64 字节。支持以下89个字符:a-z, A-Z, 0-9, space, !#$%&()+-:;≤.,>? @[]^_{|}~”
* @param uId 用户的唯一标识 id,房间内每个用户的 uId 必须是唯一的。
<br>uId 可选,默认为 0。如果不指定(即设为 0),SDK 会自动分配一个随机 uId,并在 NERtcJoinChannelCompletion 中返回,App 层必须记住该返回值并维护,SDK 不对该返回值进行维护。
* @param completion 操作完成的 block 回调。
* @return 操作返回值,被执行了则返回 0。
* @endif
*/
- (int)joinChannelWithToken:(NSString *)token
channelName:(NSString *)channelName
myUid:(uint64_t)uId
completion:(NERtcJoinChannelCompletion)completion;
此时用户B会下面方法中收到用户A加入音频频道信息
/**
* 远端用户加入当前房间回调。
* 该回调提示有远端用户加入了房间,并返回新加入用户的 ID;如果加入之前,已经有其他用户在房间中了,新加入的用户也会收到这些已有用户加入房间的回调。
* 该回调在如下情况下会被触发:
* - 远端用户调用 joinChannelWithToken 方法加入房间。
* - 远端用户网络中断后重新加入房间。
* @param userID 用户 ID。
* @param userName 新加入房间的远端用户名。废弃字段,无需关注。
*/
- (void)onNERtcEngineUserDidJoinWithUserID:(uint64_t)userID
userName:(NSString *)userName
步骤7:当双方都收到音频频道对方进入的信息后【步骤7方法中】,进行扣费等逻辑处理
步骤8:结束音频通话
1、退出音频频道
///离开房间,即挂断或退出通话。
/// * <br>结束通话时,必须调用leaveChannel结束通话,否则无法开始下一次通话。
[NERtcEngine.sharedEngine leaveChannel];
[NERtcEngine destroyEngine];
2、退出邀请信令频道
/**
关闭频道
@param request 关闭频道请求
@param completion 完成回调
@discussion 该接口可以由创建者和频道内所有成员调用,无权限限制。调用该接口成功后,其他所有频道内的成员都回收到频道结束的通知,被动离开频道。此时其他成员需要调用离开接口,也不会收到别人的离开通知。
@discussion 错误码 200:成功 10406:不在房间内
*/
- (void)signalingCloseChannel:(NIMSignalingCloseChannelRequest *)request
completion:(nullable NIMSignalingOperationBlock)completion;
但是呢!!!~~
以上内容是比较顺利的情况,在App运用中会发现各种各种的错误问题,我们也要考虑到:
1.呼叫请求error
- 拨打方创建信令频道,加入频道,邀请对方的时候,对方用户可能存在不在线或者注销了账号,销毁了App等,归结就是对方不能收到邀请的信号。具体方法如下:
/**
呼叫
@param request 呼叫请求
@param completion 完成回调
@discussion 用于用户新开一个频道并邀请对方加入频道,该接口为组合接口,等同于用户先创建频道,成功后加入频道并邀请对方
@discussion 错误码 200:成功 10405:房间已存在 10201:对方云信不在线 10202:对方推送不可达。该接口是用户呼叫场景的组合接口封装,调用该接口,sdk底层分别会 创建、加入、邀请,再返回用户结果,其中任何一步失败,就返回失败(其中邀请返回10201和10202,认为是成功,返回码还是10201和10202给上层),失败时,sdk需要主动close。常用于但不限于点对点呼叫发起。
@discussion error的错误码为10201和10202时,返回的房间信息时有效的,需要用户主动close房间
*/
- (void)signalingCall:(NIMSignalingCallRequest *)request
completion:(nullable NIMSignalingCallBlock)completion;
根据项目需要处理发生error的逻辑。
2.加入音频房间error
/*
* 加入音视频房间。
* <br>加入音视频房间时,如果指定房间尚未创建,云信服务器内部会自动创建一个同名房间。
* - SDK 加入房间后,同一个房间内的用户可以互相通话,多个用户加入同一个房间,可以群聊。使用不同 App Key 的 App 之间不能互通。
* - 成功调用该方加入房间后,远端会触发 onNERtcEngineUserDidJoinWithUserID 回调。
* - 用户成功加入房间后,默认订阅房间内所有其他用户的音频流,可能会因此产生用量并影响计费。如果想取消订阅,可以通过调用相应的 mute 方法实现。
* - 直播场景下的观众角色可以通过 switchChannelWithToken 快速切换房间。
* @param token 安全认证签名(NERTC Token)。可设置为:
- null。调试模式下可设置为 null。安全性不高,建议在产品正式上线前在云信控制台中将鉴权方式恢复为默认的安全模式。
- 已获取的NERTC Token。安全模式下必须设置为获取到的 Token 。若未传入正确的 Token 将无法进入房间。推荐使用安全模式。
* @param channelName 房间名称,设置相同房间名称的用户会进入同一个通话房间。<br>字符串格式,长度为1~ 64 字节。支持以下89个字符:a-z, A-Z, 0-9, space, !#$%&()+-:;≤.,>? @[]^_{|}~”
* @param uId 用户的唯一标识 id,房间内每个用户的 uId 必须是唯一的。
<br>uId 可选,默认为 0。如果不指定(即设为 0),SDK 会自动分配一个随机 uId,并在 NERtcJoinChannelCompletion 中返回,App 层必须记住该返回值并维护,SDK 不对该返回值进行维护。
* @param completion 操作完成的 block 回调。
* @return 操作返回值,被执行了则返回 0。
* @endif
*/
三个参数的内容条件需要注意:
channelName:长度为1~ 64 字节。支持以下89个字符,
token:调试模式下可设置为 null,安全模式下必须设置为获取到的 Token,
uid : 用户的唯一标识 id,房间内每个用户的 uId 必须是唯一的。