实现1 对 1 音视频通话

更新时间: 2023/12/12 09:55:17

本文介绍 1 对 1 音视频通话的实现方法。

前提条件

请确保您已完成以下操作:

开发环境

开发环境要求如下:

环境要求 说明
iOS 版本 11.0 及以上的 iPhone 或者 iPad 真机
CPU 架构 ARM64、ARMV7
IDE XCode
其他 安装 CocoaPods。

示例项目源码

1 对 1 娱乐社交示例项目源码,跑通示例项目的方法请参见跑通示例项目

注意事项

1 对 1 娱乐社交场景方案的呼叫能力基于云信呼叫组件,具体请参见呼叫组件文档

技术原理

音视频通话的时序图如下图所示。

sequenceDiagram

    actor  A as 用户A
    participant HJA as 呼叫组件A
    participant G2 as RTC服务器
    participant XL as 信令服务器
    participant HJB as 呼叫组件B
    participant server as 业务服务器
    actor B as 用户B


    A ->> server: 请求校验是否可以发起呼叫
    server -->> A: 返回校验结果,分配ChannelName、uid等信息(可选)

    Note over A,B: 呼叫
    rect rgb(191, 223, 255)
    A ->> HJA: A发起呼叫邀请
    HJA ->> XL: 呼叫组件发起呼叫邀请
    XL -->> HJB: A邀请B的信令
    HJB -->> B: A邀请B
    B ->> HJB: B接听
    HJB ->> XL: B接听
    HJB ->> G2: B加入RTC
    XL -->> HJA: B接听的信令
    HJA ->> G2: A加入RTC
    HJA -->> A: B接听
    end

    Note over A,B: 计费
    G2 ->> server: 发送用户A 加入房间的抄送
    G2 ->> server: 发送用户B 加入房间的抄送
    server ->> server: 开始计费
    A ->> server: 通话中客户端向业务服务器发送计费心跳(可选)

    alt 一方挂断电话 
    G2 ->> server: 发送用户离开房间的抄送
    server ->> server: 停止计费
    server -->> A: 发送通话话单

    else 出现欠费
    server -->> G2: 出现欠费,销毁房间
    G2 -->> HJA: 通话结束
    HJA -->> A: 通话结束
    G2 -->> HJB: 通话结束
    HJB -->> B: 通话结束
    end

步骤1 集成呼叫组件 SDK

1 对 1 娱乐社交场景方案的呼叫能力基于云信呼叫组件实现。

  1. 引入呼叫组件。

V1.8.0 版本开始,呼叫组件内部没有引入 NERTC,请在 Podfile 中添加以下内容,单独引入 NERTC SDK 。

    pod 'NERtcCallKit', '1.8.0'
    pod 'NERtcSDK', '4.6.43', :subspecs => ['RtcBasic']    
    // subspecs => ['RtcBasic']用于指定使用RTC基础版本,不包含美颜功能。若要使用美颜功能,此行请修改为 pod 'NERtcSDK', '4.6.43'

步骤2 初始化呼叫组件

呼叫组件实现为单实例,通过接口 NERtcCallKit.sharedInstance 获取此实例,调用实例方法 setupAppKey 完成初始化。

setupAppKey 方法为使用组件前必须调用的方法,若未初始化直接调用其他组件方法,会发生不可预知的问题或故障。

示例代码

 #import <NERtcCallKit/NERtcCallKit.h>
@interface SomeViewController()<NERtcCallKitDelegate>
@end

@implementation SomeViewController

- (void)viewDidLoad {
    [self setupSDK];
}

- (void)setupSDK {
    NERtcCallOptions *option = [NERtcCallOptions new];
    option.APNSCerName = @"anps cer name";    //输入 APNs 推送证书名
    option.VoIPCerName = "your push kit cer";  //输入 pushkit 的证书名
    NERtcCallKit *callkit = [NERtcCallKit sharedInstance];
    [callkit setupAppKey:@"app key" options:option];

    // 请求 rtc token 服务,若非安全模式则不需设置。V1.8.0及之后版本不需要执行如下配置。V1.8.0之前版本需要执行如下配置。
    callkit.tokenHandler = ^(uint64_t uid, void (^complete)(NSString *token, NSError *error)) {
        // 获取token以及回传给SDK(通常从业务服务器获取)
        NSString *token = @"get your token";
        complete(token,nil);
    };
}

@end

步骤3 登录和登出

若已经在 App 内实现了 NIMSDK 登录和登出逻辑,则不必调用相应的登录、登出接口,直接跳过此步骤即可。

使用组件的 -[NERtcCallKit login:] 进行登录,使用 -[NERtcCallKit logout:] 进行登出,登出或未进行登录则不能进行呼叫。

示例代码

[[NERtcCallKit sharedInstance] login:@"im accid" token:@"im token" completion:^(NSError * _Nullable error) {

}];

[[NERtcCallKit sharedInstance] logout:^(NSError * _Nullable error) {

}];

步骤4 实现呼叫功能

示例代码

///构造携带数据
NSDictionary *attachment = @{
    CALLER_USER_NAME : [NEOneOnOneKit getInstance].localMember.nickName,
    CALLER_USER_MOBILE : [NEOneOnOneKit getInstance].localMember.mobile,
    CALLER_USER_AVATAR : [NEOneOnOneKit getInstance].localMember.avatar
  };
  NSString *jsonString = [[NSString alloc]
      initWithData:[NSJSONSerialization dataWithJSONObject:attachment
                                                   options:NSJSONWritingPrettyPrinted
                                                     error:nil]
          encoding:NSUTF8StringEncoding];
        
    [[NERtcCallKit sharedInstance] call:accountId
                                            type:(isAudio) ? NERtcCallTypeAudio : NERtcCallTypeVideo
                                      attachment:jsonString
                                     globalExtra:nil
                                       withToken:nil
                                     channelName:nil
                                      completion:^(NSError *_Nullable error) {
                                        @strongify(self) NSLog(@"%@", error);
                                        if (error.code != 0) {
                                          // 未接通
                                        } else {
                                          //已接通
                                        }
                                      }];

步骤5 实现挂断功能

示例代码

[[NECallKitPstn sharedInstance] hangupWithCompletion:^(NSError *_Nullable error) {

          }];

步骤6 实现接听功能

示例代码

[[NERtcCallKit sharedInstance] accept:^(NSError *_Nullable error) {
          @strongify(self) if (error) {
            if (error.code == 10404) {
              /// NERTCCallKit 内部问题,后期会优化
              ///按照正常接听处理
            }
            NSLog(@"error -- %@", error.description);
          }
        }];

步骤7 添加呼叫监听

示例代码

///添加监听
[[NECallKitPstn sharedInstance] addDelegate:self];
 
 ///对方已取消连接
 - (void)onUserCancel:(NSString *)userID {

}
///对方同意
- (void)onUserAccept:(NSString *)userID {
}

/// 远端加入回调
- (void)onUserEnter:(NSString *)userID {
}
/// 自己加入成功的回调,通常用来上报、统计等
- (void)onJoinChannel:(NERtcCallKitJoinChannelEvent *)event {

}

///远端用户拒绝
- (void)onUserReject:(NSString *)userID {
}
///远端用户正在忙
- (void)onUserBusy:(NSString *)userID {
}

/// 连接超时
- (void)onCallingTimeOut {
}
///通话结束
- (void)onCallEnd {
  
}
/// 本端断网
- (void)onDisconnect:(NSError *)reason {
  
}

/// 对端断网
- (void)onUserDisconnect:(NSString *)userID {
  
}

/// 视频关闭
- (void)onVideoMuted:(BOOL)muted userID:(NSString *)userID {
  
}
///用户离开
- (void)onUserLeave:(NSString *)userID {
}

///发生错误
- (void)onError:(NSError *)error {

}

/// 用户加入
- (void)onNERtcEngineUserDidJoinWithUserID:(uint64_t)userID userName:(NSString *)userName {
  
}

如果您需要移除呼叫监听,请参考如下示例代码:

oc[[NERtcCallKit sharedInstance] removeDelegate:self];

步骤8 实现小窗功能

示例代码

oc// 小窗模式
// changeToSmall 为父类控制器(NECallViewBaseController)函数
[self changeToSmall];

// 恢复正常模式
// 重写父类函数
- (void)changeToNormal {
  self.maskView.hidden = YES;
  [super changeToNormal];
  //其余操作:例如小窗前大小窗切换了,恢复的时候如果想恢复成小窗前的样式,需要记录状态值,然后在此处恢复的时候需要刷新
}

小窗

进阶功能

此文档是否对你有帮助?
有帮助
去反馈
  • 前提条件
  • 开发环境
  • 示例项目源码
  • 注意事项
  • 技术原理
  • 步骤1 集成呼叫组件 SDK
  • 步骤2 初始化呼叫组件
  • 步骤3 登录和登出
  • 步骤4 实现呼叫功能
  • 步骤5 实现挂断功能
  • 步骤6 实现接听功能
  • 步骤7 添加呼叫监听
  • 步骤8 实现小窗功能
  • 进阶功能