云信sdk语音匹配【Z1项目需求技术分享】

Z1项目V2.1 新增功能【语音匹配】,下面是对该功能实现的分享内容

下图是对该功能实现的逻辑流程梳理:

思路流程.png
文字复述.png

在查看云信音视频产品文档,结合功能需求,实现语音匹配需要使用到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 必须是唯一的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容