iOS 端如何实现不依赖群组的实时音视频通话?
1、单聊会话进行音视频通话时,如何将其他用户加入音视频通话。
2、群聊会话进行音视频通话时,如何将群组外的其他用户加入到音视频通话中
发布时间: 2018-01-19 14:37
回答:
如何实现不依赖群组的实时音视频通话(RTC)?
#要实现不依赖群组的多人音视频通话,需要客户端和服务器端分别实现对应的逻辑
##服务器端
生成 mediaId。 mediaId要求一个全局唯一的整数,且
0 < mediaId < 0x7fffffff
调用 IM Server API 通过 private 消息发送 RTC 相关信令。调用 IM Server API 发送消息时,需要特别注意以下参数:
fromUserId=当前用户(自己)的id toUserId=参会者1&toUserId=参会者2 // 除自己外的,所有参会者拼在一起 isPersisted=0 isCounted=0 isIncludeSender=0
##客户端
具体步骤如下:
1. 如果开发者想要不依赖会话类型,在调用 startMultiCallViewController: targetId:mediaType:userIdList: 时使用如下方式调用:
/// idList为用户id列表 if (idList.count > 0) { [[RCCall sharedRCCall] startMultiCallViewController:0 targetId:nil mediaType:RCCallMediaAudio userIdList:idList]; }
2. RCCallClient. 设置外部信令服务器代理,请务必使用全局代理,确保在拨打和接听的时候代理对象都存活,这样才能确保正常通话。
/*! 设置外部信令服务器代理 @param signalServerDelegate 外部信令服务器代理 @discussion 默认情况下 app 使用融云消息作为信令即可,不需要设置此代理,此时有个限制就是所有的通话必须在某一个会话中进行,比如群组。如果您需要摆脱会话的限制,请使用 server api 服务实现本代理,然后 startCall 时 conversationType 传 0,targetId 传 nil,calllib 会调用您设置的代理来发送消息。 请务必使用一个全局代理,确保在拨打和接听 VoIP 的时候代理对象都存活,这样才能确保正常通话。 */ - (void)setSignalServerDelegate:(id<RCCallSignalServerDelegate>)signalServerDelegate;
3. 实现代理方法 (伪代码)
/*! 获取通话参与者的唯一媒体ID,必须保证每次电话会议的每个人的媒体ID都是全局唯一的。 @param successBlock 为当前用户分配的媒体 Id 成功的回调 @param errorBlcok 获取媒体 Id 失败的回调 */ - (void)getUniqueMediaId:(void (^)(NSString *mediaId))successBlock error:(void (^)(int errorCode))errorBlcok { NSString *url = @"xxx/xxxx/media_id"; [XXHTTPUtility requestWithHTTPMethod:HTTPRequestMethodGet URLString:url parameters:nil response:^(RCEHTTPResult *result) { if (result.success) { NSString *mediaId = [NSString stringWithFormat:@"%@", result.content]; successBlock(mediaId); } else { RCELogE(@"getConferenceStatus http error, result is %@", result); errorBlcok((int)result.errorCode); } }]; } /*! 发送 VoIP 信令消息。 @param messageContent 消息内容 @param toUserIdList 接收者的 Id @param pushContent pushContent @param pushData pushData @param successBlock 成功的回调 @param errorBlcok 失败的回调 */ - (void)sendVoipSignalMessage:(RCMessageContent *)messageContent toUserIdList:(NSArray<NSString *> *)toUserIdList pushContent:(NSString *)pushContent pushData:(NSString *)pushData success:(void (^)(void))successBlock error:(void (^)(int errorCode))errorBlcok { NSString *url = @"xxxxxxxxx/messages"; NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; [dic setObject:@(ConversationType_PRIVATE) forKey:@"conversation_type"]; [dic setObject:toUserIdList forKey:@"target_ids"]; [dic setObject:[[messageContent class] getObjectName] forKey:@"object_name"]; [dic setObject:[[NSString alloc] initWithData:[messageContent encode] encoding:NSUTF8StringEncoding] forKey:@"content"]; if (pushContent) { [dic setObject:pushContent forKey:@"push_content"]; } if (pushData) { [dic setObject:pushData forKey:@"push_data"]; } [dic setObject:@(([[messageContent class] persistentFlag] & MessagePersistent_ISPERSISTED) > 0 ? 1 : 0) forKey:@"persisted"]; [dic setObject:@(1) forKey:@"include_sender"]; [XXHTTPUtility requestWithHTTPMethod:HTTPRequestMethodPost URLString:url parameters:dic response:^(RCEHTTPResult *result) { if (result.success) { if (successBlock) { successBlock(); } } else { if (errorBlcok) errorBlcok((int)result.errorCode); } }]; } /*! Voip通话结束返回的统计信息 @param summary 通话统计 */ - (void)onVoipCallSummary:(RCCallSummaryMessage *)summary { //根据业务逻辑从 summary 中获取信息,用来生成通话记录。 }
4. 由于CallKit中默认实现的选择用户功能是基于会话类型的,所以开发者需要实现选择全局用户的视图控制器 XXSelectUserViewController(该控制器应提供选择用户和已选用户不能被重复选择的功能,还需返回被选中用户的 userid 列表)
5. 在视频通话页面用户点击邀请按钮时,会调用 RCCallAudioMultiCallViewController 中inviteUserButtonClicked方法,在该方法中开发者可以使用自己实现的 XXSelectUserViewController 建议pesent该控制器
6. 用户选择完成关闭XXSelectUserViewController页面后,获取到选择的用户列表 调用 inviteRemoteUsers:mediaType:接口完成发起邀请的操作
伪代码如下:
- (void)inviteUserButtonClicked { [self didTapInviteUserButton]; UIViewController *svc = [[XXSelectUserViewController alloc] initWithSuccess:^(NSArray *addUserIdList) { [weakSelf.callSession inviteRemoteUsers:addUserIdList mediaType:weakSelf.mediaType]; }]; [weakSelf presentViewController:svc animated:YES completion:nil]; }