会捷通客户端 SDK (iOS 版) 开发文档

会捷通客户端 SDK (iOS 版) 开发文档

概述

gallery-view

会捷通客户端 SDK 是⼀款视频会议软终端开发套件,开发者可以利⽤本 SDK 开发出具有清晰流畅的⾳视频体验和⾼清内容协作的⾳视频会议终端应用。会捷通客户端 SDK 具备强⼤的⽹络适应性,和独特的⾳视频抗⽹络丢包算法,配合会捷通云视讯平台使⽤,可以保证在 30% ⽹络丢包环境下视频依然清晰流畅,即使⽹络丢包⾼达 50%,依然可以保证⾳频通畅。 会捷通客户端 SDK 提供了丰富,⽽且简单易⽤的 API 接⼝。开发者不需要掌握丰富的⾳视频和信令相关知识,也可以使⽤本 SDK 开发出专业的视频会议软终端应用。 本⽂档详细介绍了 SDK 的各项功能,以及它们的使⽤⽅法。

系统要求

  • iOS 9 及以上

开发环境

  • xcode 10.0 及以上

示例代码

xcode-iOS

开发入门

初始化 SDK

使用 EVSDK 时,需要在工程中做如下配置:

文件 描述
添加SDK库⽂件evsdk.frameworks 示例代码⽬录/easyVideo-iOS/evsdk.framework
添加rootca.pem文件(没有此文件将导致无法入会) 将⽂件拷⻉到工程目录下边,设置给 SDK

在程序 AppDelegate 中初始化 SDK

//在AppDelegate+Ext.swift文件中

// MARK: EVSDK
    func setEVSDK() {
        let path = FileTools.getDocumentsFailePath()
        let logPath = path + "/Log"
        
        setDDLog(withPath: logPath)
        
        //设置Log路径
        evengine.setLog(EVLogLevel.message, path: logPath, file: "evsdk", size: 20*20*1024)
        evengine.enableLog(true)
        //初始化evsdk
        evengine.initialize(path, filename: "config")
        //设置最大接收
        evengine.setMaxRecvVideo(4)
        evengine.enablePreview(false)
        //设置Rootca文件
        evengine.setRootCA(FileTools.bundleFile("rootca.pem"))
        //设置带宽
        evengine.setBandwidth(2048)
        evengine.getDevice(.videoCapture)
        evengine.getDevice(.audioCapture)
    }

日志设置

EVSDK 会持续收集日志,打开日志收集需要做以下设置

/**
 用于设置sdk日志相关

 @param level 日志等级
 @param log_path 日志存放位置
 @param log_file_name 日志名称
 @param max_file_size 日志大小
 */
- (void) setLog:(EVLogLevel)level path:(NSString *_Nonnull)log_path file:(NSString *_Nullable)log_file_name size:(unsigned int)max_file_size;
//示例代码,示例代码日志储存路径为/Documents/Log
evengine.setLog(EVLogLevel.message, path: logPath, file: "evsdk", size: 20*20*1024)
//开启日志
evengine.enableLog(true)

设置呼叫带宽

/**
 设置呼叫带宽
 
 @param kbps 带宽大小
 @return 返回设置结果
 */
- (int) enablePreview:(BOOL)enable;
//示例代码设置2M带宽
evengine.setBandwidth(2048)

软件运行流程图

下图说明客户端应用从初始化开始,呼叫进入一个会议,再结束呼叫的基本流程。

uml diagram

登录

匿名方式入会

用户匿名方式入会的时候会执行:定位->匿名登录->注册视频服务->呼叫 (其中匿名登录以及注册视频服务均由SDK 处理)

  1. 定位服务、匿名登录、注册视频服务统一都由SDK处理只需要调用以下 API
/**
 用户执行匿名登录入会

 @param location_server 定位服务器
 @param port 端口号
 @param conference_number 会议号码
 @param display_name 用户在会议中的名称
 @param password 会议密码
 @return 返回 SDK 处理结果,UI一般可忽略
 */
- (int) joinConferenceWithLocation:(NSString *_Nonnull)location_server port:(unsigned int)port conference_number:(NSString *_Nonnull)conference_number display_name:(NSString *_Nonnull)display_name password:(NSString *_Nonnull)password;
//示例代码
appDelegate.evengine.joinConference(withLocation: "服务器", port: UInt32("端口")!, conference_number: "会议号码", display_name: "会议中的名字", password: "密码")
  1. 入会

当调用了匿名登录的 API 后,UI 会收到 SDK 回调:入会成功、入会失败。需要做出处理

//定位或者匿名登录错误会回调
- (void)onError:(EVError *_Nonnull)err;
//匿名登录成功会回调
- (void)onLoginSucceed:(EVUserInfo *_Nonnull)user;
//入会失败会回调
- (void)onCallEnd:(EVCallInfo * _Nonnull)info;
//入会成功会回调
- (void)onCallConnected:(EVCallInfo * _Nonnull)info;

用户正常登录

用户正常登录会执行:定位->登录->注册视频服务(其中注册视频服务由 SDK 处理)

1.定位
/**
 用户定位登录(包含等位跟登录)

 @param location_server 定位服务器
 @param port 端口号
 @param username 用户名
 @param password 密码
 @return 返回API结果UI可忽略
 */
- (int) loginWithLocation:(NSString *_Nonnull)location_server port:(unsigned int)port name:(NSString *_Nonnull)username password:(NSString *_Nonnull)password;
//示例代码
evengine.login(withLocation: "服务器", port: UInt32("端口"), name: "用户名", password: evengine .encryptPassword("密码"))
/** 登录后会收到SDK以下回调 */
//定位或者登录错误会回调
- (void)onError:(EVError *_Nonnull)err;
//登录成功会回调
- (void)onLoginSucceed:(EVUserInfo *_Nonnull)user;

窗口设置

EVSDK视频窗口分为三类 1. 远端窗口 2. 本地窗口 3. 内容窗口(双流、白板)

//示例代码里 最大窗口数设置了4个 即最多收到4人远端画面
[evengine setMaxRecvVideo:4];
1.远端窗口设置
/**
 设置远端窗口

 @param id 远端窗口数组
 @param size 远端窗口数量
 @return 返回结果(UI可以忽视,不作处理)
 */
- (int) setRemoteVideoWindow:(void *_Nullable[_Nonnull])id andSize:(unsigned int)size;
//示例代码(remoteArr 里的元素为UIView对象)
void * remoteArr[4];
[evengine setRemoteVideoWindow:remoteArr andSize:4];

2.本地窗口设置
/**
 设置本地窗口

 @param id 本地窗口对象
 @return 返回结果(UI可以忽视,不作处理)
 */
- (int) setLocalVideoWindow:(void *_Nullable)id;
//示例代码(本地窗口为UIView对象)
evengine.setLocalVideoWindow(Unmanaged.passUnretained(local.videoV).toOpaque())

3.内容窗口设置
/**
 设置内容窗口

 @param id 内容窗口对象
 @return 返回结果(UI可以忽视,不作处理)
 */
- (int) setRemoteContentWindow:(void *_Nullable)id;
//示例代码(内容窗口为UIView对象)
evengine.setRemoteContentWindow(Unmanaged.passUnretained(contentView).toOpaque())

实现视频通话

视频通话主要分为两种,一种是匿名入会(参考登录模块的匿名登录入会),一种是用户登录后入会

  • 设置用户入会后的头像以及视频背景图片(关闭摄像头所展示的图片)
/**
 设置会议中用户的头像以及背景图片

 @param background_file_path 背景图片
 @param user_image_path 用户图片
 @return UI可不作处理
 */
- (int) setUserImage:(NSString *_Nonnull)background_file_path filename:(NSString *_Nullable)user_image_path;
//示例
evengine.setUserImage(Bundle.main.path(forResource: "img_videomute", ofType: "jpg")!, filename: headImgPath)
  • 用户创建会议
  /**
  用户创建会议
   @param conference_number 创建会议的号码,这个参数要求必须是数字字符串,字符串的长度范围由服务器设置,默认情况要求如下:
          端口模式自定义会议号码可以是任意数字开头的 5-11 位数字,在同一个 MRU 上,一个会议的号码不能是另一个号码的前缀。
   @param conference_title 创建会议显示的名字
   @param password 加入会议所需要的密码,不设置则不需要入会密码
   @param id 传出参数,用于删除会议时使用,如果不结束删除会议,会议中有参会人员,则会议不会自动结束,如果会议中没有参会人员,会议会在5分钟后自动结束并删除。
   @return EV_OK 表示创建会议成功,EV_SERVER_NUMERICID_CONFLICTS 表示创建会议重复了。
           除了 EV_OK 以外的值都表示创建会议没有成功。
   */
- (int) createConference:(NSString *_Nonnull)conference_number conference_title:(NSString *_Nonnull)conference_title password:(NSString *_Nonnull)password id:(NSString* )id
  • 用户登录后主动入会
/// 用户加入会议
/// @param conference_number 会议号码
/// @param display_name 会议中的名字
/// @param password 会议密码
/// @param type 会议类型
- (int) joinConference:(NSString *_Nonnull)conference_number display_name:(NSString *_Nonnull)display_name password:(NSString *_Nonnull)password svcCallType:(EVSvcCallType)type;
//示例 注:会议如果没有密码可以不用给SDK传值,不传display_name则SDK会取用户名称当作会议名称
appDelegate.evengine.joinConference("会议号码", display_name: "会议中的名字", password: "密码", svcCallType: .conf)
  • 当调用了入会的 API 后,UI 会收到 SDK 回调:入会成功、入会失败。需要做出相应处理
//入会失败会回调
- (void)onCallEnd:(EVCallInfo * _Nonnull)info;
//入会成功会回调
- (void)onCallConnected:(EVCallInfo * _Nonnull)info;

主讲视图和画廊视图

  • 主讲视图

主讲视图

设置主讲视图模式

/**
 设置视频模式(主讲模式、画廊模式)

 @param layout EVLayoutRequest对象
 @return 返回结果(UI可不作处理)
 */
- (int) setLayout:(EVLayoutRequest *_Nonnull)layout;
//示例代码里主讲视图模式下 主视频窗口可以显示为1x1的窗口模式
let layout = EVLayoutRequest()
layout.page = .currentPage
layout.max_resolution = EVVideoSize(width: 0, height: 0)
layout.mode = .speakerMode
layout.max_type = ._1
appDelegate.evengine.setLayout(layout)

  • 画廊视图

画廊视图

设置画廊视图模式

/**
 设置视频模式(主讲模式、画廊模式)

 @param layout EVLayoutRequest对象
 @return 返回结果(UI可不作处理)
 */
- (int) setLayout:(EVLayoutRequest *_Nonnull)layout;
//示例代码里画廊视图模式下 主视频窗口可以显示为1x1、1x2、2x2、2x3、3x3的窗口模式(可根据需要调整窗口位置)
let layout = EVLayoutRequest()
layout.page = .currentPage
layout.max_resolution = EVVideoSize(width: 0, height: 0)
layout.mode = .galleryMode
layout.max_type = ._4
appDelegate.evengine.setLayout(layout)

静音和解除静音

执行本地麦克风开启或者关闭

/**
 是否启用麦克风

 @param enable YES为开启NO为关闭
 @return 返回结果可忽视
 */
- (int) enableMic:(BOOL)enable;
//示例代码
1.关闭麦克风
evengine.enableMic(false)
2.开启麦克风
evengine.enableMic(true)

申请举手发言

用户被管理员禁言后可以调用此API申请发言

/// 申请举手发言
/// @param val YES
- (int) requestRemoteUnmute:(BOOL)val;
//示例代码
evengine.requestRemoteUnmute(true)

查看当前麦克风状态

- (BOOL) micEnabled;

查看当前摄像头状态

- (BOOL) cameraEnabled;

是否打开高帧率

- (BOOL) highFPSEnabled;

获取当前用户的displayName

/// 获取当前用户displayname
- (NSString * _Nonnull) getDisplayName;
//示例代码
evengine.getDisplayName()

是否打开1080P

- (int) enableHD:(BOOL)enable;

进入语音或者视频模式

/// 进入语音或者视频h模式
/// @param active 0为语音 3为视频
- (int) setVideoActive:(int)active;
//示例代码
evengine.setVideoActive(0)

修改会中名字

/// 修改会中名字
/// @param display_name 会中名字
- (int) setInConfDisplayName:(NSString *_Nonnull)display_name;
//示例代码
evengine.setInConfDisplayName("修改名字")

关闭或打开本地视频

执行本地摄像头开启或者关闭

/**
 是否启用摄像头

 @param enable YES为开启NO为关闭
 @return 返回结果可忽视
 */
 - (int) enableCamera:(BOOL)enable;
 //示例代码
 1.关闭摄像头
 evengine.enableCamera(false)
 2.开启摄像头
 evengine.enableCamera(true)

切换前置后置摄像头

执行切换前置摄像头或者后置摄像头

/**
 切换摄像头

 @return 返回结果可忽视
 */
 - (int) switchCamera;
 //示例代码
 evengine.switchCamera()

接收和显示共享内容

当为 EVSDK 设置了内容窗口的时候,收到共享或者共享结束 SDK 都会通过回调的形式告诉终端

/**
 接收到内容分享或者内容分享结束的回调

 @param info EVContentInfo对象
 */
- (void)onContent:(EVContentInfo * _Nonnull)info;
//示例代码
func onContent(_ info: EVContentInfo) {
  
        if info.status == .denied {
            
        }else if info.status == .granted {
            if info.type == .content || info.type == .whiteBoard {
                if info.enabled {
                    if info.dir == .upload {
                        
                    }else {
                        contentView.isHidden = false
                        contentMenuView.isHidden = false
                        selectBtn.isSelected = false
                    }
                }else {
                    contentView.isHidden = true
                    contentMenuView.isHidden = true
                }
            }
        }else if info.status == .released {
            contentView.isHidden = true
            contentMenuView.isHidden = true
        }
    }

P2P呼叫相关内容

P2P 呼叫的基本流程如下图所示

uml diagram

P2P主动呼叫

/// P2P主动呼叫
/// @param conference_number 需要呼叫人的UserId
/// @param display_name 自己的名字
/// @param password 密码设为无
/// @param type EVSvcCallP2P
- (int) joinConference:(NSString *_Nonnull)conference_number display_name:(NSString *_Nonnull)display_name password:(NSString *_Nonnull)password svcCallType:(EVSvcCallType)type;
//示例代码
appDelegate.evengine.joinConference("用户名", display_name: "会议中的名字", password: "", svcCallType: .P2P)

接收到P2P呼叫请求

/// 收到邀请
/// @param info 会议详情
- (void)onJoinConferenceIndication:(EVCallInfo *_Nonnull)info;

__attribute__((visibility("default"))) @interface EVCallInfo : NSObject
@property (assign, nonatomic) BOOL isAudioOnly;
@property (assign, nonatomic) BOOL contentEnabled;
@property (copy, nonatomic) NSString *_Nonnull peer;//邀请人名字
@property (copy, nonatomic) NSString *_Nonnull conference_number;
@property (copy, nonatomic) NSString *_Nonnull password;
@property (strong, nonatomic) EVError *_Nonnull err;
@property (assign, nonatomic) BOOL isBigConference;
@property (assign, nonatomic) BOOL isRemoteMuted;
@property (assign, nonatomic) EVSvcCallType svcCallType;//会议类型判断为P2P邀请还是普通会议
@property (assign, nonatomic) EVSvcCallAction svcCallAction;
@end

接听

//拿到会议号码去呼叫当前P2P会议
func dialCall(sipNumber sip:String, isVideoMode flag:Bool, disPlayName name:String, withPassword password:String, callType type:EVSvcCallType) {}

挂断

- (void) acceptCall;

对方已接受P2P呼叫

- (void)onCallPeerConnected:(EVCallInfo * _Nonnull)info;

获取主叫方头像地址

- (void)onPeerImageUrl:(NSString*)imageUrl;

结束呼叫

在需要结束呼叫的时候调用 SDK 的离会 API

- (int) leaveConference;
//示例代码
evengine.leaveConference()
//退出成功后,会收到sdk的回调
- (void)onCallEnd:(EVCallInfo * _Nonnull)info;

API 参考

以下为用户相关接口回调

onLoginSucceed

/**
 登录成功回调

 @param user 返回用户信息
 */
- (void)onLoginSucceed:(EVUserInfo *_Nonnull)user;

onRegister

/**
 视频服务注册状态(注册状态变化的时候将会走此回调)

 @param registered YES为成功 NO为失败
 */

- (void)onRegister:(BOOL)registered;

onDownloadUserImageComplete

/**
 用户头像下载成功回调

 @param path 保存路径
 */
- (void)onDownloadUserImageComplete:(NSString *_Nonnull)path;

onUploadUserImageComplete

/**
 用户上传头像成功回调

 @param path 头像路径
 */
- (void)onUploadUserImageComplete:(NSString *_Nonnull)path;

onNetworkQuality

//信号的强度回调,quality_rating代表信号等级越小信号越差
- (void)onNetworkQuality:(float)quality_rating;

onMuteSpeakingDetected

//监测到说话但是麦克风未打开是会有此回调
- (void)onMuteSpeakingDetected;

enableSecure

/**
 是否启用https协议

 @param enable YES为https NO为http
 @return 结果返回
 */
- (int) enableSecure:(BOOL)enable;
//示例
[evengine enableSecure:YES];

encryptPassword

/**
 用户登录密码加密

 @param password 密码明文
 @return 返回加密后的密码
 */
- (NSString * _Nonnull) encryptPassword:(NSString * _Nonnull)password;
//示例
NSString *password = [evengine encryptPassword:password];

logout

/**
 用户退出

 @return 返回结果
 */
- (int) logout;
//示例
[evengine logout];

downloadUserImage

/**
 下载用户当前头像(需登录后调用)

 @param path 指定储存地址
 @return 返回结果
 */
- (int) downloadUserImage:(NSString *_Nonnull)path;
//示例
[evengine downloadUserImage:downloadimagepath];

uploadUserImage

/**
 向服务器上传用户头像

 @param path 上传图片地址
 @return 返回结果
 */
- (int) uploadUserImage:(NSString *_Nonnull)path;
//示例
[evengine uploadUserImage:downloadimagepath];

changePassword

/**
 修改当前用户密码

 @param oldpassword 原密码
 @param newpassword 新密码
 @return 返回结果
 */
- (int) changePassword:(NSString *_Nonnull)oldpassword newpassword:(NSString *_Nonnull)newpassword;
//示例(密码需要使用SDK方法加密)
int state =  [evengine changePassword:[evengine encryptPassword:oldpwStr] newpassword:[evengine encryptPassword:newpwStr]];
if (state == EVOK) {
    //修改成功
}

changeDisplayName

/**
 修改当前用户名称

 @param display_name 用户名称
 @return 返回结果
 */
- (int) changeDisplayName:(NSString *_Nonnull)display_name;
//示例
int state = [evengine changeDisplayName:displayNameStr];
if (state == EVOK) {
    //修改成功
}

getUserInfo

/**
 获取当前用户信息

 @return 返回当前用户信息
 */
- (EVUserInfo *_Nullable) getUserInfo;
//示例
EVUserInfo *userInfo = [evengine getUserInfo];
__attribute__((visibility("default"))) @interface EVUserInfo : NSObject
@property (copy, nonatomic) NSString *_Nonnull username;
@property (copy, nonatomic) NSString *_Nonnull displayName;
@property (copy, nonatomic) NSString *_Nonnull org;
@property (copy, nonatomic) NSString *_Nonnull email;
@property (copy, nonatomic) NSString *_Nonnull cellphone;
@property (copy, nonatomic) NSString *_Nonnull telephone;
@property (assign, nonatomic) BOOL everChangedPasswd;
@property (copy, nonatomic) NSString *_Nonnull dept;
@property (copy, nonatomic) NSString *_Nonnull customizedH5UrlPrefix;
@property (copy, nonatomic) NSString *_Nonnull token;
@end

以下为呼叫相关接口及回调

onCallConnected

/**
 入会成功之后走此回调

 @param info 当前呼叫信息
 */
- (void)onCallConnected:(EVCallInfo * _Nonnull)info;

onCallEnd

/**
 会议结束后走此回调

 @param info 会议信息
 */
- (void)onCallEnd:(EVCallInfo * _Nonnull)info;

onContent

/**
 主会场模式开启关闭通知(在主会场模式下,将只能收到一路远端视频)

 @param info 主会场信息
 */
- (void)onContent:(EVContentInfo * _Nonnull)info;
//示例代码
- (void)onContent:(EVContentInfo * _Nonnull)info
{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (info.type == EVStreamContent || info.type == EVStreamWhiteBoard) {
            if (info.enabled) {
                //当前会议为主会场模式
            }else{
                //当前会议为讨论模式
            }
        }
    });
}

onLayoutSiteIndication

/**
 收到禁言或者解除禁言的通知

 @param site 发起操作的用户
 */
- (void)onLayoutSiteIndication:(EVSite *_Nonnull)site;
//示例代码
- (void)onLayoutSiteIndication:(EVSite *_Nonnull)site
{
    dispatch_async(dispatch_get_main_queue(), ^{
    //is_local为YES,指的是当前自己操作的麦克风,否则为当前会议中的其他用户操作的麦克风
        if (site.is_local) {
            if (site.remote_muted) {
                //被禁言
            }else{
                //解除禁言
            }
        }else {
            if (site.mic_muted) {
                //被禁言
            }else {
                //解除禁言
            }
        }
    });
}

onLayoutSpeakerIndication

/**
 当前会议的发言者

 @param speaker 发言人信息
 */
- (void)onLayoutSpeakerIndication:(EVLayoutSpeakerIndication *_Nonnull)speaker;
//示例代码
- (void)onLayoutSpeakerIndication:(EVLayoutSpeakerIndication *_Nonnull)speaker
{
    dispatch_async(dispatch_get_main_queue(), ^{
        for (int i = 0; i<self->remoteList.count; i++)
        {
            self->remotVideoController = self->remoteList[i];
            
            if ([self->remotVideoController.userName.stringValue isEqualToString:speaker.speaker_name])
            {
                //当前这个窗口的人在发言
            }else{
                //其他窗口的人没有发言
            }
        }
    });
}

onJoinConferenceIndication

/**
 收到会议邀请的通知

 @param info 邀请会议的信息
 */
- (void)onJoinConferenceIndication:(EVCallInfo *_Nonnull)info;
__attribute__((visibility("default"))) @interface EVCallInfo : NSObject
@property (assign, nonatomic) BOOL isAudioOnly;
@property (assign, nonatomic) BOOL contentEnabled;
@property (copy, nonatomic) NSString *_Nonnull peer;
@property (copy, nonatomic) NSString *_Nonnull conference_number;
@property (copy, nonatomic) NSString *_Nonnull password;
@property (strong, nonatomic) EVError *_Nonnull err;
@end

onRecordingIndication

/**
 是否有录制终端参与

 @param info 录制终端信息
 */
- (void)onRecordingIndication:(EVRecordingInfo *_Nonnull)info;
//录制相关枚举
typedef NS_ENUM (NSUInteger, EVRecordingState) {
    EVRecordingStateNone = 0,//没有录制
    EVRecordingStateOn = 1,//正在录制
    EVRecordingStatePause = 2//暂停录制
};

onMessageOverlay

/**
 会议字幕相关通知

 @param msg 字幕信息
 */
- (void)onMessageOverlay:(EVMessageOverlay *_Nonnull)msg;
 __attribute__((visibility("default"))) @interface EVMessageOverlay : NSObject
@property (assign, nonatomic) BOOL enable;//是否开启字幕
@property (copy, nonatomic) NSString *_Nonnull content;//字幕内容
@property (assign, nonatomic) int displayRepetitions;//字幕重复次数
@property (assign, nonatomic) int displaySpeed;//字幕速度
@property (assign, nonatomic) int verticalBorder;//字幕垂直边界
@property (assign, nonatomic) int transparency;//字幕透明度
@property (assign, nonatomic) int fontSize;//字体大小
@property (copy, nonatomic) NSString *_Nonnull foregroundColor;//字体颜色
@property (copy, nonatomic) NSString *_Nonnull backgroundColor;//背景颜色
@end

onParticipant

/**
 获取当前参与会议人数

 @param number 当前参与人数
 */
- (void)onParticipant:(int)number;

当前会议禁止解除静音

//warn = EVWarnUnmuteAudioNotAllowed
- (void)onWarn:(EVWarn *)warn;

主持人解除当前终端静音时收到的回调

//warn = EVWarnUnmuteAudioIndication
- (void)onWarn:(EVWarn *)warn;
//示例代码
[appDelegate.evengine enableMic:NO];//不同意解除
[appDelegate.evengine enableMic:YES];//同意解除

远端静音提示

当会议中发生远端对该终端进行静音或者解除静音时,SDK会该回调事件

onUploadFeedback/**
 远端静音提示
 
 @param int, 当取值为0时,表示远端静音,否则为远端解除静音
 */
- (void)onMicMutedShow:(int)mic_muted;

其他接口及回调

setDeviceRotation

/**
 设置当前的设备旋转角度,一般关注为横竖屏

 @param rotation 当前设备旋转角度
 @return 可以忽略
 */
- (int) setDeviceRotation:(int)rotation;

audioInterruption

/**
 当前音视频被中断是的处理

 @param type 是否被中断
 @return 可以忽略
 */
- (int) audioInterruption:(int)type;

onError

/** SDK错误回调需要查看错误类型做出相应处理 */
- (void)onError:(EVError *_Nonnull)err;

onWarn

/** SDK会议中的警告回调需要查看错误类型做出相应处理 */
- (void)onError:(EVError *_Nonnull)err;
//示例
func onWarn(_ warn: EVWarn) {}

setDelegate

/**
 设置SDK代理

 @param aDelegate SDK代理
 */
- (void) setDelegate:(id<EVEngineDelegate>_Nonnull)aDelegate;
//示例代码
[evengine setDelegate:self];

enableHighFPS

/**
 设置高帧率

 @param enable YES为高帧率 NO为相反
 @return 返回结果
 */
- (int) enableHighFPS:(BOOL)enable;
//示例
[evengine enableHighFPS:YES];

getNetworkQuality

/**
 获取当前信号强度

 @return 返回信号数值
 */
- (float) getNetworkQuality;
//示例
float signalValue = [evengine getNetworkQuality];

错误码以及枚举类型

/** 信号统计相关枚举 */
typedef NS_ENUM (NSUInteger, EVStreamType) {
	EVStreamAudio = 0,//音频流
	EVStreamVideo = 1,//视频流
	EVStreamContent = 2,//分享内容
	EVStreamWhiteBoard = 3//白板
};

typedef NS_ENUM (NSUInteger, EVStreamDir) {
	EVStreamUpload = 0,//上传
	EVStreamDownload = 1,//下载
};
- (NSArray<EVStreamStats *> * _Nonnull) getStats;

/** 日志设置 */
typedef NS_ENUM (NSUInteger, EVLogLevel) {
    EVLogLevelDebug = 0,
    EVLogLevelMessage = 1,
    EVLogLevelWARNING = 2,
    EVLogLevelError = 3,
    EVLogLevelFatal = 4
};
- (void) setLog:(EVLogLevel)level path:(NSString *_Nonnull)log_path file:(NSString *_Nullable)log_file_name size:(unsigned int)max_file_size;

/** SDK返回错误信息类型 */
typedef NS_ENUM (NSUInteger, EVErrorType) {
    EVErrorTypeSdk = 0,//SDK错误
    EVErrorTypeServer = 1,//服务器错误
    EVErrorTypeLocate = 2,//定位错误
    EVErrorTypeCall = 3,//呼叫错误
    EVErrorTypeUnknown = 4//未知错误
};
//如果接收到SDK的错误回调,可以根据EVErrorType定位错误类型
- (void)onError:(EVError *_Nonnull)err;
__attribute__((visibility("default"))) @interface EVError : NSObject
@property (assign, nonatomic) EVErrorType type;
@property (assign, nonatomic) int code;
@property (copy, nonatomic) NSString *_Nonnull msg;
@end
//SDK 错误枚举
typedef NS_ENUM (NSUInteger, EVSdkError) {
    EVOK = 0,
    EVNG = 1,
    EVUninitialized = 2,
    EVBadFormat = 3,
    EVNotInConf = 4,
    EVBadParam = 5,
    EVRegisterFailed = 6,
    EVInternalError = 7
 };
 //服务器错误枚举
 typedef NS_ENUM (NSUInteger, EVServerError) {
    EVServerApiVersionNotSupported = 1000,
    EVServerInvalidToken = 1001,
    EVServerInvalidParameter = 1002,
    EVServerInvalidDevicesn = 1003,
    EVServerInvalidMediaType = 1004,
    EVServerPermissionDenied = 1005,
    EVServerWrongFieldName = 1006,
    EVServerInternalSystemError = 1007,
    EVServerOperationFailed = 1008,
    EVServerGetFailed = 1009,
    EVServerNotSupported = 1010,
    EVServerRedisLockTimeout = 1011,
    EVServerInvalidUserNamePassword = 1100,
    EVServerLoginFailedMoreThan5Times = 1101,
    EVServerAccountTemporarilyLocked = 1102,
    EVServerAccountDisabled = 1103,
    EVServerNoUsername = 1104,
    EVServerEmailMismatch = 1105,
    EVServerCompanyAdministratorNotInAnyCompany = 1106,
    EVServerFileUploadFailed = 1200,
    EVServerInvalidLicense = 1201,
    EVServerInvalidImportUserFile = 1202,
    EVServerInvalidTimeServiceAddress = 1300,
    EVServerFailedUpdateSystemProperties = 1301,
    EVServerConfNotExists = 1400,
    EVServerNumericidConflicts = 1401,
    EVServerConfUpdatingInProgress = 1402,
    EVServerConfDeletingInProgress = 1403,
    EVServerConfTerminatingInProgress = 1404,
    EVServerConfLaunchingInProgress = 1405,
    EVServerConfNotInApprovedStatus = 1406,
    EVServerConfNumericidOngoing = 1407,
    EVServerConfNotApprovedOrOngoing = 1409,
    EVServerParticipantNotExistsInConf = 1410,
    EVServerNumericidAlreadyInUse = 1412,
    EVServerInvalidConfTime = 1415,
    EVServerInvalidConfId = 1418,
    EVServerNotFoundSuitableMru = 1421,
    EVServerNotFoundSuitableGateway = 1422,
    EVServerFailedToConnectMru = 1424,
    EVServerNotAllowDuplicatedName = 1427,
    EVServerNotFoundConfInRedis = 1430,
    EVServerNotInLecturerMode = 1431,
    EVServerFailedToMuteAllParticipants = 1433,
    EVServerFailedToConnectParticipant = 1436,
    EVServerFailedToDisconnectParticipant = 1439,
    EVServerFailedToChangeLayout = 1442,
    EVServerFailedToSetSubtitle = 1445,
    EVServerFailedToMuteParticipantAudio = 1448,
    EVServerFailedToDeleteParticipant = 1451,
    EVServerFailedToInviteAvcEndpoint = 1454,
    EVServerFailedToInviteSvcEndpoints = 1455,
    EVServerConfRoomCompletelyFull = 1456,
    EVServerTimeoutToGenerateNumericid = 1457,
    EVServerNotFoundProfileNamedSvc = 1460,
    EVServerFailedToProlongConf = 1463,
    EVServerInvalidMeetingControlRequest = 1500,
    EVServerNameInUse = 1600,
    EVServerEmptyEndpointName = 1601,
    EVServerEmptyEndpointCallMode = 1602,
    EVServerEmptyEndpointSipUsername = 1603,
    EVServerEmptyEndpointSipPassword = 1604,
    EVServerEmptyEndpointAddress = 1605,
    EVServerInvalidSipUsername = 1606,
    EVServerInvalidIpAddress = 1607,
    EVServerEndpointNotExist = 1608,
    EVServerE164InUse = 1609,
    EVServerEndpointDeviceSnExist = 1610,
    EVServerSipUsernameRegistered = 1611,
    EVServerEndpointE164Invalid = 1612,
    EVServerNotFoundEndpointDeviceSn = 1613,
    EVServerNotFoundEndpointProvisionTemplate = 1614,
    EVServerDeviceSnExists = 1615,
    EVServerCanNotDeleteUserInReservedMeeting = 1700,
    EVServerEmptyUserPassword = 1701,
    EVServerEmptyUsername = 1702,
    EVServerEmptyUserDisplayName = 1703,
    EVServerInvalidUserEmail = 1704,
    EVServerInvalidCellphoneNumber = 1705,
    EVServerOriginalPasswordWrong = 1706,
    EVServerDuplicateEmailName = 1707,
    EVServerDuplicateCellphoneNumber = 1708,
    EVServerDuplicateUsername = 1709,
    EVServerInvalidConfRoomMaxCapacity = 1710,
    EVServerShouldAssignDepartmentToDepartmentAdministrator = 1711,
    EVServerEmptyUserEmail = 1712,
    EVServerEmptyUserCellphoneNumber = 1713,
    EVServerNotOrganizationAdministrator = 1714,
    EVServerCompanyNotExist = 1800,
    EVServerShortNameOfCompanyUsed = 1801,
    EVServerFullNameOfCompanyUsed = 1802,
    EVServerCompanyNotEmpty = 1803,
    EVServerEmptyCompanyShortName = 1804,
    EVServerAgentInUse = 1900,
    EVServerShortNameInUse = 1901,
    EVServerFullNameInUse = 1902,
    EVServerAgentNotExist = 1903,
    EVServerAgentNotEmpty = 1904,
    EVServerConfRoomExpired = 2000,
    EVServerNotActived = 2001,
    EVServerNotFoundSuitableRoom = 2003,
    EVServerNotFoundTemplateOrRoom = 2005,
    EVServerConfRoomInUse = 2006,
    EVServerConfRoomNumberInUse = 2009,
    EVServerConfRoomCapacityExceedsLimit = 2012,
    EVServerInvalidConfRoomCapacity = 2015,//PasswordRequired
    EVServerInvalidConfRoomNumber = 2018,
    EVServerRoomNotExists = 2021,
    EvServerRoomNotAllowAnonymousCall = 2031,
    EvServerRoomOnlyAllowOwnerActive = 2033,
    EvServerTrialPeriodExpired = 2035,
    EVServerCanNotDeleteDepartmentWithSubordinateDepartment = 2100,
    EVServerCanNotDeleteDepartmentWithUsersOrEndpoints = 2101,
    EVServerInvalidAcsConfiguration = 2200
};
//定位错误枚举
typedef NS_ENUM (NSUInteger, EVLocateError) {
    EVLocateFailedToReadBody = 10000,
    EVLocateFailedToParseBody = 10001,
    EVLocateLocationTimeout = 10002,
    EVLocateErrorInfoGeneral = 10003,
    EVLocateErrorInfoBadFormat = 10004,
    EVLocateUnexpected = 10005,
    EVLocateFailedToLocateClient = 10006,
    EVLocateFailedToLocateZone = 10007,
    EVLocateNoLocationDomain = 10008,
    EVLocateErrorLocationRequest = 10009
};
//呼叫相关错误枚举
typedef NS_ENUM (NSUInteger, EVCallError) {
    EVCallInvalidNumericid = 1001,
    EVCallInvalidUsername = 1003,
    EVCallInvalidUserid = 1005,
    EVCallInvalidDeviceid = 1007,
    EVCallInvalidEndpoint = 1009,

    EVCallServerUnlicensed = 2001,
    EVCallNotFoundSuitableMru = 2003,
    EVCallNeitherTemplateNorOngoingNorBindedRoom = 2005,
    EVCallLockTimeout = 2007,
    EVCallTemplateConfWithoutConfroom = 2009,
    EVCallRoomExpired = 2011,
    EVCallInvalidPassword = 2015,
    EVCallNoTimeSpaceToActivateRoom = 2017,
    EVCallConfPortCountUsedUp = 2023,
    EVCallOrgPortCountUsedUp = 2024,
    EVCallHaishenPortCountUsedUp = 2025,
    EVCallHaishenGatewayAudioPortCountUsedUp = 2027,
    EVCallHaishenGatewayVideoPortCountUsedUp = 2029,
    EVCallOnlyRoomOwnerCanActivateRoom = 2031,
    EVCallNotAllowAnonymousParty = 2033,
    EVCallTrialOrgExpired = 2035
};
//视频模式枚举
typedef NS_ENUM (NSUInteger, EVLayoutMode) {
    EVLayoutAutoMode =  0,
    EVLayoutGalleryMode =  1, 
    EVLayoutSpeakerMode =  2,
    EVLayoutSpecifiedMode =  3
};

屏幕共享

请参考 iOS 屏幕共享功能实现

上次更新: 6/6/2022, 3:52:43 PM