多人实时通话


多人实时通话分为视频通话和语音通话,目前不提供音视频互转接口。

文件介绍

多人音视频相关头文件

IEMConferenceManager.h:多人音视频操作接口

EMConferenceManagerDelegate.h:多人音视频回调接口

EMCallConference.h:多人音视频会议对象

EMCallStream.h:数据流对象

EMCallStream.h/EMStreamParam:上传数据流时的数据流参数

EMCallLocalView.h: 显示本地视频的页面

EMCallRemoteView.h: 显示对方视频的页面

EMCallConference中会出现两个ID属性,分别是callId和confId,两个ID都是标识符,callId是本地生成,confId是服务器端生成,邀请或者加入所需要的均为confId

代码集成

注册监听

[[EMClient sharedClient].conferenceManager addDelegate:self delegateQueue:nil];

创建并加入会议

[[EMClient sharedClient].conferenceManager createAndJoinConferenceWithPassword:@"密码" completion:block];

邀请其他人进入(建议用户自定义) & 被邀请者监听邀请信令

1.“邀请其他人进入”功能支持自定义实现,可以利用EMMessage实现,示例代码如下:

//SEND:
NSString *currentUser = [EMClient sharedClient].currentUsername;
EMCmdMessageBody *cmdChat = [[EMCmdMessageBody alloc] initWithAction:@"inviteToJoinConference"];
EMMessage *message = [[EMMessage alloc] initWithConversationID:aUserName from:currentUser to:aUserName body:cmdChat ext:@{@"confId":self.conference.confId, @"creater":currentUser, @"type":[NSNumber numberWithInteger:self.type]}];
message.chatType = EMChatTypeChat;
[[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:nil];
//RECV:
- (void)cmdMessagesDidReceive:(NSArray *)aCmdMessages
{
    for (EMMessage *message in aCmdMessages) {
        EMCmdMessageBody *cmdBody = (EMCmdMessageBody *)message.body;
        NSString *action = cmdBody.action;
        if ([action isEqualToString:@"inviteToJoinConference"]) {
            NSString *confId = [message.ext objectForKey:@"confId"];
            EMCallType type = (EMCallType)[[message.ext objectForKey:@"type"] integerValue];
            NSString *creater = [message.ext objectForKey:@"creater"];
            ConferenceViewController *confController = [[ConferenceViewController alloc] initWithConferenceId:confId creater:creater type:type];
            [self.mainController.navigationController pushViewController:confController animated:NO];

        } 
    }
}

2.SDK提供了默认的邀请方法,但是建议用户自定义,因为如果对方不在线,则无法收到该邀请,登录之后仍然不会收到该邀请, 示例代码如下:

//SEND:
[[EMClient sharedClient].conferenceManager inviteUserToJoinConference:self.conference userName:aUserName password:nil ext:jsonString error:&error];
//RECV:
- (void)userDidRecvInvite:(NSString *)aConfId password:(NSString *)aPassword ext:(NSString *)aExt
{
    NSData *jsonData = [aExt dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
    EMCallType type = (EMCallType)[[dic objectForKey:@"type"] integerValue];
    NSString *creater = [dic objectForKey:@"creater"];
    ConferenceViewController *confController = [[ConferenceViewController alloc] initWithConferenceId:aConfId creater:creater type:type];
    [self.mainController.navigationController pushViewController:confController animated:NO];
}

被邀请者加入会议

调用join成功后,其他人会收到[EMConferenceManagerDelegate userDidJoin:user:]回调

[[EMClient sharedClient].conferenceManager joinConferenceWithConfId:confId password:@"" completion:nil];

上传本地数据流

上传数据流成功后,其他人会收到[EMConferenceManagerDelegate streamDidUpdate:addStream:]回调

EMCallPubConfig *pubConfig = [[EMCallPubConfig alloc] init];
    pubConfig.streamName = loginUser;
    pubConfig.enableVideo = self.type == EMCallTypeVideo ? YES : NO;
    pubConfig.localView = [[EMCallLocalView alloc] initWithFrame:frame];
    [[EMClient sharedClient].conferenceManager publishConference:self.conference pubConfig:pubConfig completion:^(NSString *pubStreamId, EMError *aError) {
        //code
    }];

取消上传本地数据流

取消数据流成功后,其他人会收到[EMConferenceManagerDelegate streamDidUpdate:removeStream:]回调

[[EMClient sharedClient].conferenceManager unpublishConference:self.conference streamId:pubStreamId completion:^(EMError *aError) {
        //code
    }];

订阅其他人的数据流

收到[EMConferenceManagerDelegate streamDidUpdate:addStream:]回调后,可以订阅该EMStream

- (void)streamDidUpdate:(EMCallConference *)aConference addStream:(EMCallStream *)aStream
{
    if ([aConference.callId isEqualToString:self.conference.callId]) {
        [self _subStream:aStream];
    }
}

- (void)_subStream:(EMCallStream *)aStream
{
    EMCallRemoteView *remoteView = nil;
    if (self.type == EMCallTypeVideo) {
        remoteView = [[EMCallRemoteView alloc] initWithFrame:frame];
    }

    __weak typeof(self) weakSelf = self;
    [[EMClient sharedClient].conferenceManager subscribeConference:self.conference streamId:aStream.streamId remoteVideoView:remoteView completion:^(EMError *aError) {
            //code
     }];
}

取消订阅的数据流

[[EMClient sharedClient].conferenceManager unsubscribeConference:self.conference streamId:pubStreamId completion:^(EMError *aError) {
        //code
    }];

离开会议

离开会议成功后,其他人会收到[EMConferenceManagerDelegate userDidLeave:user:]回调

[[EMClient sharedClient].conferenceManager leaveConference:self.conference completion:nil];

其他操作:切换摄像头、静音、禁用本地视频

这三个操作成功后,其他人会收到[EMConferenceManagerDelegate streamDidUpdate:stream:]回调