[TOC]
云直播观看端SDK开发指南
1.概述
1.1 阅读对象
本文档为技术文档,需要阅读者:
- 具备基本的iOS开发能力
- 准备接入CC视频的直播SDK相关功能
- 对CC云直播产品使用方法有基础的了解,使用帮助地址
1.2 功能特性
功能 | 描述 |
---|---|
直播视频 | 观看直播视频 |
文档展示 | 能够观看当前直播文档,文档添加水印 |
线路更换 | 观看卡顿请换个线路 |
清晰度 | 支持直播多清晰度切换播放 |
答题卡 | 支持实时检测课堂学生的掌握程度 |
问答 | 能够发送问题和接受回答信息 |
简介 | 支持对直播间的信息展示 |
问卷 | 支持对观看直播的人进行信息采集 |
广播 | 支持发送全体消息 |
连麦 | 支持与直播人员进行音视频沟通 |
签到 | 支持签到功能 |
抽奖 | 支持抽奖功能 |
随堂测 | 支持随堂测互动 |
修改昵称 | 支持自定义昵称 |
聊天互动 | 支持与房间内的其他人聊天互动和一对一私聊 |
跑马灯 | 支持直播防录屏功能 |
2.开发准备
2.1 开发环境
- Xcode 10.0 或以上版本
- 支持 iOS 10.0 或以上版本的 iOS 设备
- 有效的 获得场景视频 云直播账号
2.2 SDK配置
2.2.1 CocoaPods集成
已安装CocoaPods
如果是有连麦的SDK:
pod 'CCLivePlaySDK', '~> 3.8.0'
如果是无连麦的SDK:
v3.11.2 之前的版本请用如下链接:
pod 'CCLivePlaySDK', :podspec => 'https://raw.githubusercontent.com/CCVideo/Live_iOS_Play_SDK/3.8.0/CCLivePlaySDK.podspec'
v3.11.2 之后的版本请用如下链接:
pod 'CCLivePlaySDK', :podspec => 'https://hdgit.bokecc.com/ccvideo/Live_iOS_Play_SDK/raw/3.11.2/CCLivePlaySDK.podspec'
PS:其中3.8.0与3.11.2为SDK版本号可自行更改。
未安装CocoaPods
-
安装CocoaPods
打开终端:>_ 1、查看当前Ruby版本
ruby -v
2、升级Ruby环境,首先需要安装rvm(第一步要下载一些东西等两分钟左右)
curl -L get.rvm.io | bash -s stable source ~/.bashrc source ~/.bash_profile
3、查看rvm版本
rvm -v 显示如下(或者是其他版本) rvm 1.29.3 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]
4、列出ruby可安装的版本信息
rvm list known 显示如下 # MRI Rubies [ruby-]1.8.6[-p420] [ruby-]1.8.7[-head] # security released on head [ruby-]1.9.1[-p431] [ruby-]1.9.2[-p330] [ruby-]1.9.3[-p551] [ruby-]2.0.0[-p648] [ruby-]2.1[.10] [ruby-]2.2[.10] [ruby-]2.3[.7] [ruby-]2.4[.4] [ruby-]2.5[.1] // 重点在这里 重点在这里 重点在这里 [ruby-]2.6[.0-preview2] // 测试版 ruby-head .....
5、安装一个ruby版本
rvm install 2.5.1 // 注意:安装过程中需要两次按下 Enter 键, 第二次按下后需要输入电脑访问密码(不可见,只管输入就行); // 如果你电脑没有安装Xcode和Command Line Tools for Xcode以及Homebrew 会自动下载安装,建议提前安装这三者. 这里很多小伙伴会遇到错误,大部分是因为没有安装Homebrew造成,所以所以所以要提前安装比较好 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
6、设置为默认版本
rvm use 2.5.1 --default
7、更换源
sudo gem update --system gem sources --remove https://rubygems.org/ gem sources --add https://gems.ruby-china.com/
8、为了验证你的Ruby镜像是并且仅是ruby-china,执行以下命令查看
gem sources -l 如果是以下结果说明正确,如果有其他的请自行百度解决 *** CURRENT SOURCES *** https://gems.ruby-china.com/
9、这时候才正式开始安装CocoaPods
sudo gem install -n /usr/local/bin cocoapods
10、如果安装了多个Xcode使用下面的命令选择(一般需要选择最近的Xcode版本)
sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
11、安装本地库
pod setup
12、执行以上命令后
Setting up CocoaPods master repo $ /usr/bin/git clone https://github.com/CocoaPods/Specs.git master --progress Cloning into 'master'... remote: Counting objects: 1879515, done. remote: Compressing objects: 100% (321/321), done. Receiving objects: 21% (404525/1879515), 73.70 MiB | 22.00 KiB/ 然后就是漫长的等待,当然,网络好的情况下会更快
-
在Podfile文件中添加
如果是有连麦的SDK: pod 'CCLivePlaySDK', '~> 3.8.0' 如果是无连麦的SDK: v3.11.2 之前的版本请用如下链接: pod 'CCLivePlaySDK', :podspec => 'https://raw.githubusercontent.com/CCVideo/Live_iOS_Play_SDK/3.8.0/CCLivePlaySDK.podspec' v3.11.2 之后的版本请用如下链接: pod 'CCLivePlaySDK', :podspec => 'https://hdgit.bokecc.com/ccvideo/Live_iOS_Play_SDK/raw/3.11.2/CCLivePlaySDK.podspec' PS:其中3.8.0与3.11.2为SDK版本号可自行更改。
-
在终端中执行
pod install
ps:目前CocoaPods集成仅支持3.8.0及以后的版本,旧版本暂不支持CocoaPods集成
2.2.2 手动集成
1.将SDK文件夹内的所有文件拖到项目中
command + b 编译,如果报错" file '...xxx/IJKMediaFramework.framework/IJKMediaFramework' for architecture arm64 "
解决方案:
Targets -> Build Settings -> 搜索 "Enable Bitcode" 设置为 "NO"
2.command + r 运行
如果报错" dyld: Library not loaded: @rpath/XXX.framework "
解决方案:
Targets -> Build Phases ->
点击左上角 "+" 按钮 ->
选择 "New Copy Files Phase" ->
点击新添加的 Copy Files 前面的下拉箭头 ->
Destination 选择 "Frameworks" ->
点击当前目录下的 "+" 将SDK包含的.framework 包添加即可
2.3 日志存储 *( 3.17.7 升级须知,必须添加该方法)
注:日志收集功能为 必选项 ,本地接入需要使用最新的 CCBundle 资源文件
新增依赖库 | Cocoapods 接入 | 本地接入 | 签名选择 |
---|---|---|---|
CCFuncTool.framework (动态库) | pod 'HDSCCFuncTool' | 下载zip包中 CCFuncTool 文件夹下,拖入项目中 | Embed & Sign |
SSZipArchive.framework (动态库) | pod 'HDSSZip' | 下载zip包中 CCFuncTool 文件夹下,拖入项目中 | Embed & Sign |
CocoaLumberjack.framework (动态库) | pod 'HDSCocoaLumberjack' | 下载zip包中 HDSCocoaLumberjack 文件夹下,拖入项目中 | Embed & Sign |
在AppDelegate.m文件导入头文件
#import "CCSDK/HDSPreserve.h"
在启动方法中添加日志存储
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 日志收集
[[HDSPreserve shared] HDSApplicationDidFinishLaunching];
return YES;
}
- (void)applicationWillTerminate:(UIApplication *)application {
// 日志收集
[[HDSPreserve shared] HDSApplicationWillTerminate];
}
2.4 错误码
服务错误类型
ERROR_SERVICE_TYPE
ERROR_ROOM_STATE = 1001 直播间状态不可用,可能没有开始推流
ERROR_USELESS_INFO = 1002 没有获取到有用的视频信息
ERROR_PASSWORD = 1003 密码错误
系统错误类型
ERROR_SYSTEM_TYPE
ERROR_RETURNDATA = 1004 返回内容格式错误
ERROR_PARAMETER = 1005 直播间信息填写错误
ERROR_NETWORK = 1006 网络异常
ERROR_LOGINDATA = 1007 登录
ERROR_PLAYERURL = 1008 视频播放地址
ERROR_QUESTIONLIST = 1009 问卷列表
ERROR_STATISTICAL = 1010 问卷统计
ERROR_DOCLIST = 1011 文档列表
ERROR_HISTORY = 1012 历史信息
PRACTICE_LIST = 1013 随堂测试
PRACTICECOMMIT = 1014 提交随堂测试
PRACTICESTATIS = 1015 获取随堂测统计
PRACTICERANK = 1016 获取随堂测排名
ERROR_SOCKET = 1017 socket加载失败
ERROR_PUNCH = 1018 获取打卡信息失败
ERROR_PUNCHCOMMIT = 1019 获取打卡提交结果失败
ERROR_DRMURL = 1020 获取加密地址失败
ERROR_QUERYLOTTERY = 1021 抽奖2.0 查询抽奖信息失败
ERROR_QUERYPERSIONALLOTTERY = 1022 抽奖2.0 查询个人中奖失败"
ERROR_COMMITWINNERINFO = 1023 抽奖2.0 提交中奖信息"
ERROR_REQUESTMETADATA = 1024 获取元数据异常
ERROR_DOCINITERROR = 1025 文档初始化失败
ERROR_GETSUMMARYINFO = 1026 获取摘要接口失败
2.5 打包上线报错
打包上线过程出现以下错误,关于不支持 x86_64 和 i386 等情况.
The following issues occurred while distributing your application.
App Store Connect Operation Error
ERROR ITMS-90097:"Unsupported Architectures. The executable for CCLiveCloud.app/Frameworks/CCSDK.framework contains unsupported architectures '[x86_64]."
App Store Connect Operation Error
ERROR ITMS-90097:"Unsupported Architectures. The executable for CCLiveCloud.app/Frameworks/DWDrmServer.framework contains unsupported architectures '[x86_64]."
App Store Connect Operation Error
ERROR ITMS-90097:"Unsupported Architectures. The executable for CCLiveCloud.app/Frameworks/IJKMediaFramework.framework contains unsupported architectures '[x86_64]."
App Store Connect Operation Error
ERROR ITMS-90097:"Unsupported Architectures. The executable for CCLiveCloud.app/Frameworks/WebRTC.framework contains unsupported architectures '[x86_64,i386]."
解决方案: Target --> Build Phases --> 点击"+"按钮,选择"New Run Script Phase",在 Run Script 内添加以下脚本方法:
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done
添加上之后,重新打包上线即可.
3.快速集成
3.1 配置参数
3.1.1 调用方法
/**
* @brief 登录房间
* @param parameter 配置参数信息
* 必填参数 userId; //用户ID
* 必填参数 roomId; //房间ID
* 必填参数 viewerName; //用户名
* 必填参数 token; //房间密码
* (选填参数) viewercustomua; //用户自定义参数,需和后台协商,没有定制传@""
*/
- (id)initLoginWithParameter:(PlayParameter *)parameter;
/// 初始化SDK
/// @param parameter 参数
/// @param succed 初始化成功回调
/// @param player 播放视图回调 (流视图异步回调,存在回调多次;无延迟直播无需关注。)
/// @param failed 初始化失败回调
- (id)initSDKWithParameter:(PlayParameter *)parameter
succed:(initSuccedClosure)succed
player:(HDSPlayerViewClosure)player
failed:(initFailedClosure)failed;
始化SDK(新)
方法 | 注释 |
---|---|
(id)initSDKWithParameter: succed: player: failed: | 初始化SDK |
示例代码
/// 初始化SDK
/// @param parameter 参数
/// @param succed 初始化成功回调
/// @param player 播放视图回调 (流视图异步回调,存在回调多次;无延迟直播无需关注。)
/// @param failed 初始化失败回调
- (id)initSDKWithParameter:(PlayParameter *)parameter
succed:(initSuccedClosure)succed
player:(HDSPlayerViewClosure)player
failed:(initFailedClosure)failed;
参数 | 注释 |
---|---|
parameter | 初始化SDK参数,其中 "playerParent","playerFrame" 已废弃删除,新的流视图由 HDSPlayerViewClosure 异步回调,自行处理 |
succed | 初始化SDK成功回调 |
player | 流视图异步回调,存在回调多次;“无延迟直播” 无需关注。 |
failed | 初始化SDK失败回调 |
流视图(callback回调)
注意 |
---|
“新的流视图” 通过 初始化SDK(initSDKWithParameter:)方法中的 player:,通过 callback 返回 “流视图” |
“流视图” (属于UIView 类型),所在 视图区域,视图大小 可根据业务自行调整设置示例代码 |
_requestData = [[RequestData alloc] initSDKWithParameter:parameter succed:^(BOOL succed) {
} player:^(UIView * _Nonnull playerView) {
--> ** playerView ** 即为视频流视图
} failed:^(NSError *error, NSString *reason) {
}];
代理方法
/**
* @brief 登录成功
*/
- (void)loginSucceedPlay;
/**
* @brief 登录失败
*/
-(void)loginFailed:(NSError *)error reason:(NSString *)reason;
/**
* @brief 请求成功
*/
-(void)requestSucceed;
/**
* @brief 登录请求失败
*/
-(void)requestFailed:(NSError *)error reason:(NSString *)reason;
/// 3.18.0 new 错误回调
/// @param model 错误信息
- (void)onError:(HDSOnErrorModel *)model;
3.1.2 集成
导入头文件
#import "CCSDK/RequestData.h"//SDK
声明变量
@property (nonatomic,strong)RequestData * requestData;//sdk
配置参数:PlayParameter的属性如下
/**
* @brief 用户ID
*/
@property(nonatomic, copy)NSString *userId;//用户ID
/**
* @brief 用户ID
*/
@property(nonatomic, copy)NSString *roomId;//用户ID
/**
* @brief 用户名称
*/
@property(nonatomic, copy)NSString *viewerName;//用户名称
/**
* @brief 房间密码
*/
@property(nonatomic, copy)NSString *token;//房间密码
/**
* @brief 回放ID
*/
@property(nonatomic, copy)NSString *recordId;//回放ID
/**
* @brief 用户自定义参数,需和后台协商,没有定制传@""
*/
@property(nonatomic, copy)NSString *viewerCustomua;//用户自定义参数,需和后台协商,没有定制传@"" 长度不能超过40个字符
/**
* json格式字符串,可选,自定义用户信息,该信息会记录在用户访问记录中,用于统计分析使用(长度不能超过200个字符,若直播间启用接口验证则该参数无效)如果不需要的话就不要传值
* 格式如下:
* viewercustominfo: '{"exportInfos": [ {"key": "城市", "value": "北京"}, {"key": "姓名", "value": "哈哈"}]}'
*/
@property(nonatomic, copy)NSString *viewercustominfo;
/**
* @brief 下载文件解压到的目录路径(离线下载相关)
*/
@property(nonatomic, copy)NSString *destination;//下载文件解压到的目录路径(离线下载相关)
/**
* @brief 文档父类窗口
*/
@property(nonatomic,strong)UIView *docParent;//文档父类窗口
/**
* @brief 文档区域
*/
@property(nonatomic,assign)CGRect docFrame;//文档区域
/**
* @brief 屏幕适配方式
* 0:HDSMediaScalingModeNone
* 1:HDSMediaScalingModeAspectFit
* 2:HDSMediaScalingModeAspectFill
* 3:HDSMediaScalingModeFill
*/
@property(assign, nonatomic)NSInteger scalingMode;//屏幕适配方式,含义见上面
/**
* @brief ppt默认底色,不写默认为白色(@"#FFFFFF")
*/
@property(nonatomic, copy) NSString *defaultColor;//ppt默认底色,不写默认为白色(@"#FFFFFF")
/**
* @brief /后台是否继续播放,注意:如果开启后台播放需要打开 xcode->Capabilities->Background Modes->on->Audio,AirPlay,and Picture in Picture
*/
@property(nonatomic,assign)BOOL pauseInBackGround;//后台是否继续播放,注意:如果开启后台播放需要打开 xcode->Capabilities->Background Modes->on->Audio,AirPlay,and Picture in Picture
/**
* @brief PPT适配模式分为四种
* PPT适配模式分为四种,
* 1.拉伸填充,PPT内容全部展示在显示区域,会被拉伸或压缩,不会存在黑边
* 2.等比居中,PPT内容保持原始比例,适应窗口展示在显示区域,会存在黑边
* 3.等比填充,PPT内容保持原始比例,以横向或纵向适应显示区域,另一方向将会超出显示区域,超出部分会被裁减,不会存在黑边
* 4.根据直播间文档显示模式的返回值进行设置(推荐)
*/
@property(assign, nonatomic)NSInteger PPTScalingMode;//PPT适配方式,含义见上面
/**
* @brief PPT是否允许滚动(The New Method)
*/
@property(nonatomic, assign)BOOL pptInteractionEnabled;
/**
* @brief 设置当前的文档模式,
* 1.切换至跟随模式(默认值)值为0,
* 2.切换至自由模式;值为1,
*/
@property(assign, nonatomic)NSInteger DocModeType;//设置当前的文档模式
/**
* @brief 聊天分组id
* 使用聊天分组功能时传入,不使用可以不传
*/
@property(copy, nonatomic)NSString *groupid;
/**
* @brief 是否禁用视频,默认为NO,禁用视频则只播放音频 (在线回放专用)
* 只有账号开启支持音频模式设置才生效,可以在初始化SDK的时候配置,也可以在切换线路调用(changeLineWithPlayParameter)的时候配置
*/
@property(assign, nonatomic)BOOL disableVideo;
/**
* @brief 切换线路
* 在切换线路调用(changeLineWithPlayParameter)的时候配置
*/
@property(assign, nonatomic)NSInteger lineNum;//线路
/**
* 抽奖2.0 抽奖去重, 默认开启YES.(不开启时(NO),收到同一重复抽奖,代理方法会响应多次)
*/
@property(assign, nonatomic)BOOL LotteryRepetition;
/**
* 视频播放状态
* HDSMediaPlaybackStateStopped 播放停止
* HDSMediaPlaybackStatePlaying 开始播放
* HDSMediaPlaybackStatePaused 暂停播放
* HDSMediaPlaybackStateInterrupted 播放间断
* HDSMediaPlaybackStateSeekingForward 播放快进
* HDSMediaPlaybackStateSeekingBackward 播放后退
*/
typedef NS_ENUM(NSUInteger, HDSMediaPlaybackState) {
HDSMediaPlaybackStateStopped,
HDSMediaPlaybackStatePlaying,
HDSMediaPlaybackStatePaused,
HDSMediaPlaybackStateInterrupted,
HDSMediaPlaybackStateSeekingForward,
HDSMediaPlaybackStateSeekingBackward,
};
/**
* 视频加载状态
* HDSMediaLoadStateUnknown 未知状态
* HDSMediaLoadStatePlayable 视频未完成全部缓存,但已缓存的数据可以进行播放
* HDSMediaLoadStatePlaythroughOK 缓冲已经完成
* HDSMediaLoadStateStalled 缓冲已经开始
*/
typedef NS_ENUM(NSUInteger, HDSMediaLoadState) {
HDSMediaLoadStateUnknown,
HDSMediaLoadStatePlayable,
HDSMediaLoadStatePlaythroughOK,
HDSMediaLoadStateStalled,
};
/**
* 视频播放完成原因
* HDSMediaFinishReasonPlaybackEnded 自然播放结束
* HDSMediaFinishReasonUserExited 用户人为结束
* HDSMediaFinishReasonPlaybackError 发生错误崩溃结束
*/
typedef NS_ENUM(NSUInteger, HDSMediaFinishReason) {
HDSMediaFinishReasonPlaybackEnded,
HDSMediaFinishReasonUserExited,
HDSMediaFinishReasonPlaybackError,
};
新增 RemindModel 类 (用户进出直播间代理模型类)
/**
* 用户进出通知
* HDUSER_IN_REMIND 进入直播间
* HDUSER_OUT_REMIND 退出直播间
*/
typedef NS_ENUM(NSUInteger, HDUSER_REMIND) {
HDUSER_IN_REMIND,//进入直播间
HDUSER_OUT_REMIND,//退出直播间
};
/** 用户id */
@property (nonatomic, copy) NSString *userId;
/** 昵称 */
@property (nonatomic, copy) NSString *userName;
/** 角色 */
@property (nonatomic, copy) NSString *userRole;
/** 头像 */
@property (nonatomic, copy) NSString *userAvatar;
/** 分组id */
@property (nonatomic, copy) NSString *groupId;
/** 接收端 1-讲师;2-助教;3-主持人;4-观看端 */
@property (nonatomic, strong) NSArray *clientType;
/** 用户进出通知 */
@property (nonatomic, assign) HDUSER_REMIND remindType;
/** 发送内容前缀 */
@property (nonatomic, copy) NSString *prefixContent;
/** 发送内容后缀 */
@property (nonatomic, copy) NSString *suffixContent;
新增 BanChatModel 类(用户禁言群发消息通知模型类)
/** 用户id */
@property (nonatomic, copy) NSString *userId;
/** 昵称 */
@property (nonatomic, copy) NSString *userName;
/** 角色 */
@property (nonatomic, copy) NSString *userRole;
/** 头像 */
@property (nonatomic, copy) NSString *userAvatar;
/** 分组id */
@property (nonatomic, copy) NSString *groupId;
新增 NewLotteryMessageModel 类 (抽奖2.0 该功能需要单独开启)
/**
* 抽奖2.0 抽奖消息类别
* NEW_LOTTERY_NULL 无抽奖
* NEW_LOTTERY_BEGIN 开始抽奖
* NEW_LOTTERY_CANCEL 取消抽奖
* NEW_LOTTERY_COMPLETE 抽奖结束
* NEW_LOTTERY_EXIT 抽奖异常
*
*/
typedef NS_ENUM(NSUInteger, NEW_LOTTERY) {
NEW_LOTTERY_NULL,//无抽奖
NEW_LOTTERY_BEGIN,//开始抽奖
NEW_LOTTERY_CANCEL,//取消抽奖
NEW_LOTTERY_COMPLETE,//抽奖结束
NEW_LOTTERY_EXIT,//抽奖异常
};
/** 抽奖类型 */
@property (nonatomic, assign) NEW_LOTTERY type;
/** 当前是否有抽奖 */
@property (nonatomic, assign) BOOL haveLottery;
/**
* 抽奖信息 infos
* infos 包含的字段: 注:字段对应的值可能为空
* lotteryStatus (NSInteger 必须) 抽奖状态: 0抽奖创建成功, 1抽奖取消成功, 2抽奖已完成, 3抽奖异常结束
* lotteryId (NSString 必须) 抽奖ID
* collectTemplate (NSArray 必须) 用户信息模板 例:@[@{@"index":index序号,@"title":提示,@"tips":@"提示"}]
* isWinner (BOOL 必须) 是否中奖
* ownUserInfo (NSDictionary 必须) 中奖者信息 例:@{@"userAvatar":头像,@"userName":用户名,@"userId":用户id,@"prizeCode":中奖码}
* prize (NSDictionary 必须) 奖品信息 例:@{@"name":奖品名字}
* userInfos (NSArray 必须) 中奖名单 例:@[@{@"userAvatar":头像,@"userName":用户名,@"userId":用户id,@"prizeCode":中奖码}]
*/
@property (nonnull, strong) NSDictionary *infos;
新增 HDQualityModel 类 (切换线路清晰度)
/** 清晰度 */
@property (nonatomic, copy) NSString * _Nonnull quality;
/** 描述 */
@property (nonatomic, copy) NSString * _Nonnull desc;
新增枚举类型
/**
* 音视频模式
* PLAY_MODE_TYEP_VIDEO 视频
* PLAY_MODE_TYEP_AUDIO 音频
*/
typedef NS_ENUM(NSUInteger, PLAY_MODE_TYEP) {
PLAY_MODE_TYEP_VIDEO,//视频
PLAY_MODE_TYEP_AUDIO,//音频
};
/**
* 是否有音频线路
* HAVE_AUDIO_LINE_TURE 有音频线路
* HAVE_AUDIO_LINE_FALSE 无音频线路
*/
typedef NS_ENUM(NSUInteger, HAVE_AUDIO_LINE) {
HAVE_AUDIO_LINE_TURE,//有音频线路
HAVE_AUDIO_LINE_FALSE,//无音频线路
};
新增枚举类型
/**
* 操作调用状态
* HDOperationCallStatusSuccess 操作成功
* HDOperationCallStatusFailedNotLogin 操作失败未登录
* HDOperationCallStatusFailedInLoading 操作失败加载中
* HDOperationCallStatusFailedAllReadyLoaded 操作失败已加载
*/
typedef NS_ENUM(NSInteger, HDOperationCallStatus) {
HDOperationCallStatusSuccess,//操作成功
HDOperationCallStatusFailedNotLogin,//操作失败未登录
HDOperationCallStatusFailedInLoading,//操作失败加载中
HDOperationCallStatusFailedAllReadyLoaded,//操作失败已加载
};
新增 HDReplayDotModel (回放打点)类
/** 打点时间:单位:S */
@property (nonatomic, assign) NSInteger time;
/** 打点描述 */
@property (nonatomic, copy) NSString * _Nullable desc;
新增枚举类型
/// 申请连麦类型
typedef NS_ENUM(NSInteger, HDSMediaCallType) {
HDSMediaCallTypeAudio, /// 音频连麦
HDSMediaCallTypeAudioVideo, /// 视频连麦
};
/// 连麦错误类型
typedef NS_ENUM(NSInteger, HDSMediaCallError) {
HDSMediaCallErrorInCalling, /// 连麦失败
HDSMediaCallErrorConnectTimeOut, /// 连麦申请超时
HDSMediaCallErrorRoomTypeDidChange, /// 连麦房间类型改变(需要退出重进)
HDSMediaCallErroronMumberLimit, /// 连麦人数已达上限
HDSMediaCallErrorAbilityDown, /// 连麦功能不可用(需要退出重进)
HDSMediaCallErrorPullStreamFailed, /// 拉流失败
};
typedef void(^initSuccedClosure)(BOOL succed); //初始化SDK成功回调
typedef void(^HDSPlayerViewClosure)(UIView * _Nonnull playerView); // 流视图回调
typedef void(^initFailedClosure)(NSError * _Nullable error, NSString * _Nonnull reason); //初始化SDK失败回调
typedef void(^hangupClosure)(BOOL succed); // 挂断回调
/// 连麦房间类型
typedef NS_ENUM(NSInteger, HDSRoomCallType) {
HDSRoomCallTypeAudio, /// 音频连麦房间 (多人连麦情况下只能申请音频连麦)
HDSRoomCallTypeAudioVideo, /// 视频连麦房间 (单人连麦可申请音频或视频连麦)
};
/// 连麦功能不可用原因
typedef NS_ENUM(NSUInteger, HDSMediaCallAbilityDisableReason) {
HDSMediaCallAbilityDisableReasonNone, /// 无
HDSMediaCallAbilityDisableReasonRoomNotOpen, /// 房间未开启
HDSMediaCallAbilityDisableReasonTeacherClose, /// 讲师关闭
HDSMediaCallAbilityDisableReasonLiveEnd, /// 直播结束
HDSMediaCallAbilityDisableReasonLiveBan, /// 直播封禁
HDSMediaCallAbilityDisableReasonNotNetwork, /// 无网络
};
新增 HDSRoomCallInfo (房间连麦信息)类
/// 是否是多人连麦房间
@property (nonatomic, assign) BOOL isMultiMediaCallRoom;
/// 是否开启连麦功能
@property (nonatomic, assign) BOOL isMediaCallFuncEnable;
/// 房间连麦功能未开启原因
@property (nonatomic, assign) HDSMediaCallAbilityDisableReason disableReason;
/// 连麦类型
@property (nonatomic, assign) HDSRoomCallType roomCallType;
新增 HDSStreamUserInfoModel (流用户信息)类
/// 用户ID
@property (nonatomic, copy) NSString * _Nullable userId;
/// 用户名
@property (nonatomic, copy) NSString * _Nonnull userName;
/// 用户角色
@property (nonatomic, assign) NSInteger userRole;
/// 声音是否可用
@property (nonatomic, assign) BOOL isAudioEnable;
/// 视频是否可用
@property (nonatomic, assign) BOOL isVideoEnable;
新增 HDSStreamModel (流信息)类
/// 远端流视图
@property (nonatomic, strong) UIView * _Nonnull hds_remoteView;
/// 流用户信息
@property (nonatomic, strong) HDSStreamUserInfoModel * _Nonnull userInfo;
新增拉远端流回调
typedef void (^pullStreamSuccedClosure)(HDSStreamModel * _Nullable stModel); // 拉远端流成功回调
typedef void (^pullStreamFailedClosure)(HDSMediaCallError error); // 拉远端流失败回调
新增 HDSOnErrorModel (错误信息)类
/// 错误类型
@property (nonatomic, assign) OnErrorType type;
/// 错误信息
@property (nonatomic, copy) NSString * _Nullable message;
开始配置
第一步:实例化参数类
PlayParameter *parameter = [[PlayParameter alloc] init];
//配置PlayParameter里面的属性,如userId,roomId等!
第二步实例化RequestData类
_requestData = [[RequestData alloc] initWithParameter:parameter];
第三步添加代理
_requestData.delegate = self;
添加代理
@interface 您的控制器 ()<RequestDataDelegate>
实现代理
/**
* @brief 请求成功
*/
-(void)requestSucceed {
}
/**
* @brief 登录请求失败
*/
-(void)requestFailed:(NSError *)error reason:(NSString *)reason {
}
/// 3.18.0 new 错误回调
/// @param model 错误信息
- (void)onError:(HDSOnErrorModel *)model;
至此您的项目已经可以运行了,并且已经集成好了视频和文档基本功能;如果不需要文档功能则不配置文档相关属性即可
3.2 观看直播
3.2.1 代理方法(可选)
/**
* @brief 主讲开始推流
*/
- (void)onLiveStatusChangeStart;
/**
* @brief 停止直播,endNormal表示是否异常停止推流,这个参数对观看端影响不大
*/
- (void)onLiveStatusChangeEnd:(BOOL)endNormal;
/**
* @brief 收到踢出消息,停止推流并退出播放(被主播踢出)(change)
* dictionary[@"kick_out_type"] 踢出类型
* dictionary[@"viewerid"] 用户ID
* kick_out_type: 踢出类型
* 10 在允许重复登录前提下,后进入者会登录会踢出先前登录者
* 20 讲师、助教、主持人通过页面踢出按钮踢出用户
*
*/
- (void)onKickOut:(NSDictionary *)dictionary;
/**
* @brief 收到播放直播状态 0.正在直播 1.未开始直播
*/
- (void)getPlayStatue:(NSInteger)status;
/**
* @brief 直播间被禁
*/
- (void)theRoomWasBanned;
/**
* @brief 直播间解禁
*/
- (void)theRoomWasCleared;
/**
* @brief 客户端关闭摄像头
数据源类型 数据源值 数据源类型描述 数据源类型描述值
source_type 0 source_type_desc 数据源类型:默认值,
source_type 10 source_type_desc 数据源类型:摄像头打开
source_type 11 source_type_desc 数据源类型:摄像头关闭
source_type 20 source_type_desc 数据源类型:图片
source_type 30 source_type_desc 数据源类型:插播视频
source_type 40 source_type_desc 数据源类型:区域捕获
source_type 50 source_type_desc 数据源类型:桌面共享
source_type 60 source_type_desc 数据源类型:自定义场景
ps:
source_type 参数 0 值 应用场景:
1. 文档模式下 0 默认值
2. 非文档模式下 0 无意义
3. 低版本客户端 0 无意义
source_type 参数 60 值 应用场景:
当以上场景无法满足要求时,主播可自定义场景,用户不需要关心自定义场景细节内容
*/
- (void)receivedSwitchSource:(NSDictionary *)dic;
/**
* @brief 视频或者文档大窗
* isMain 1为视频为主,0为文档为主"
*/
- (void)onSwitchVideoDoc:(BOOL)isMain;
/**
* @brief 加载视频失败
*/
- (void)play_loadVideoFail;
/**
* @brief 视频状态
* rseult playing/paused/loading/buffing
*/
-(void)videoStateChangeWithString:(NSString *) result;
/**
* @brief 获取直播开始时间和直播时长
* liveDuration 直播持续时间,单位(s),直播未开始返回-1"
* liveStartTime 新增开始直播时间(格式:yyyy-MM-dd HH:mm:ss),如果直播未开始,则返回空字符串
*/
- (void)startTimeAndDurationLiveBroadcast:(NSDictionary *)dataDic;
/**
* @brief 回调已播放时长, 如果未开始,则time为-1
* 触发此方法需要调用getLivePlayedTime
*/
- (void)onLivePlayedTime:(NSDictionary *)dic;
/**
获取已播放时长,调用后会响应onLivePlayedTime方法,调用间隔三秒
*/
- (void)getLivePlayedTime;
3.2.2 主动方法(可选)
/**
* @brief 改变播放器frame
*/
- (void)changePlayerFrame:(CGRect) playerFrame;
/**
* @brief 改变播放器父窗口
*/
- (void)changePlayerParent:(UIView *) playerParent;
/**
* @brief 播放器暂停
*/
- (void)pausePlayer;
/**
* @brief 播放器播放
*/
- (void)startPlayer;
/**
* @brief 播放器关闭并移除
*/
- (void)shutdownPlayer;
/**
* @brief 播放器停止
*/
- (void)stopPlayer;
/**
* @brief 重新加载视频,参数force表示是否强制重新加载视频,
* 一般重新加载视频的时间间隔应该超过3秒,如果强制重新加载视频,时间间隔可以在3S之内
*/
-(void)reloadVideo:(BOOL)force;
/**
* @brief 播放器是否播放
*/
- (BOOL)isPlaying;
/**
* @brief 设置后台是否可播放
*/
- (void)setpauseInBackGround:(BOOL)pauseInBackGround;
/**
* @brief 销毁文档和视频,清除视频和文档的时候需要调用,退出播放页面的时候也需要调用
*/
- (void)requestCancel;
3.3 文档功能
3.3.1 代理方法(可选)
/**
* @brief 获取文档内白板或者文档本身的宽高,来进行屏幕适配用的
*/
- (void)getDocAspectRatioOfWidth:(CGFloat)width height:(CGFloat)height;
/**
* @brief 获取ppt当前页数和总页数 (会多次回调)
*
* 回调当前翻页的页数信息
* 白板docTotalPage一直为0, pageNum从1开始
* 其他文档docTotalPage为正常页数,pageNum从0开始
* @param dictionary 翻页信息
* dictionary :{docId 文档ID
* docName 文档名
* docTotalPage 文档总页数
* pageNum 文档页码}
*/
- (void)onPageChange:(NSDictionary *) dictionary;
/**
* @brief 双击ppt
*/
- (void)doubleCllickPPTView DEPRECATED_MSG_ATTRIBUTE("该方法已废弃");
/**
* @brief 获取所有文档列表
* @param listDic [{ docId //文档ID
docName //文档名称
docTotalPage //文档总页数
iconSrc //图标地址
pages [{ pageIndex //当前页位置
src //当前页地址
title //当前页标题 }]}]
*/
- (void)receivedDocsList:(NSDictionary *)listDic;
/**
* @brief 视频或者文档大窗
* isMain 1为视频为主,0为文档为主"
*/
- (void)onSwitchVideoDoc:(BOOL)isMain;
/**
* @brief 文档加载状态
* index
* 0 文档组件加载成功
* 1 动态文档翻页成功
* 2 非动画文档(白板 图片)文档翻页完成
* 3 文档组件加载失败
* 4 静态文档翻页失败
* 5 动态文档翻页失败
* 6 画板翻页失败
* 7 极速动画翻页加载成功
* 8 极速动画翻页加载失败
* 9 文档组件重载失败
* 10 静态文档翻页超时
* 11 动态文档动画执行成功
* 12 动态文档动画执行超时
* 13 动态文档加载成功
* 14 动态文档加载失败
*/
- (void)docLoadCompleteWithIndex:(NSInteger)index;
文档状态说明及操作
-(void)docLoadCompleteWithIndex:(NSInteger)index;
参数 | 说明 | 操作 |
---|---|---|
0 | 文档组件加载成功 | 无 |
1 | 动态文档翻页成功 | 无 |
2 | 非动画文档(白板 图片)文档翻页完成 | 无 |
3 | 文档组件加载失败(SDK内部已做重试逻辑,但仍失败需要退出重新进入房间) | 退出重进 |
4 | 静态文档翻页失败(展示文档刷新按钮,用户可手动出发文档重载) | 重载翻页 |
5 | 动态文档翻页失败(展示文档刷新按钮,用户可手动出发文档重载) | 重载翻页 |
6 | 画板翻页失败(展示文档刷新按钮,用户可手动出发文档重载) | 重载翻页 |
7 | 极速动画翻页加载成功 | 无 |
8 | 极速动画翻页加载失败(展示文档刷新按钮,用户可手动出发文档重载) | 重载翻页 |
9 | 文档组件重载失败(展示文档刷新按钮,用户可手动出发文档重载) | 重载翻页 |
10 | 静态文档翻页超时(展示文档刷新按钮,用户可手动出发文档重载) | 重载翻页 |
11 | 动态文档动画执行成功 | 无 |
12 | 动态文档动画执行超时(展示文档刷新按钮,用户可手动出发文档重载) | 重载翻页 |
13 | 动态文档加载成功 | 无 |
14 | 动态文档加载失败(展示文档刷新按钮,用户可手动出发文档重载) | 重载翻页 |
3.3.2 主动方法(可选)
/**
* @brief 获取文档区域内白板或者文档本身的宽高比,返回值即为宽高比,做屏幕适配用
*/
- (CGFloat)getDocAspectRatio;
/**
* @brief 切换当前的文档模式
* 1.切换至跟随模式(默认值)值为0,
* 2.切换至自由模式;值为1,
*/
- (void)changeDocMode:(NSInteger)mode;
/**
* @brief 查找并获取当前文档的信息
* @param docId 文档的docId
* @param pageIndex 跳转的页数
*/
- (void)changePageToNumWithDocId:(NSString *)docId pageIndex:(NSInteger)pageIndex;
/**
重新加载文档
*/
- (void)docReload;
/**
改变文档背景颜色
@param hexColor 字符串,传颜色的HEXColor 如:#000000
*/
- (void)changeDocWebColor:(NSString *)hexColor;
/**
* 获取ppt列表(只能在登陆成功后调用)
*/
- (void)getDocsList;
/**
* @brief 主动调用方法 用于调整PPT缩放模式
* @param pptScalingMode PPT缩放模式
* 1 = 拉伸填充:PPT内容全部展示在显示区域,会被拉伸或压缩,不会存在黑边
* 2 = 等比居中:PPT内容保持原始比例,适应窗口展示在显示区域,会存在黑边
* 3 = 等比填充:PPT内容保持原始比例,以横向或纵向适应显示区域,另一方向将会超出显示区域,超出部分会被裁减,不会存在黑边
*/
- (void)changeDocPPTScalingMode:(NSInteger)pptScalingMode;
3.3.3 重载翻页 (主动方法)
方法 | 说明 |
---|---|
(void)reloadPageChange: | 重载翻页 |
示例代码
/// 重载翻页
/// @param closure 操作回调
- (void)reloadPageChange:(void (^)(BOOL result, NSString *message))closure {
if (result == NO) {
// 重载翻页操作失败,错误信息 message
}
}
3.4 房间信息
代理方法(可选)
/**
* @brief 获取房间信息,主要是要获取直播间模版来类型,根据直播间模版类型来确定界面布局
* 房间简介:dic[@"desc"];
* 房间名称:dic[@"name"];
* 房间模版类型:[dic[@"templateType"] integerValue];
* 模版类型为1: 聊天互动: 无 直播文档: 无 直播问答: 无
* 模版类型为2: 聊天互动: 有 直播文档: 无 直播问答: 有
* 模版类型为3: 聊天互动: 有 直播文档: 无 直播问答: 无
* 模版类型为4: 聊天互动: 有 直播文档: 有 直播问答: 无
* 模版类型为5: 聊天互动: 有 直播文档: 有 直播问答: 有
* 模版类型为6: 聊天互动: 无 直播文档: 无 直播问答: 有
*/
-(void)roomInfo:(NSDictionary *)dic;
/**
* @brief 服务器端给自己设置的信息
* viewerId 服务器端给自己设置的UserId
* groupId 分组id
* name 用户名
*/
-(void)setMyViewerInfo:(NSDictionary *) infoDic;
/**
* @brief 房间设置信息
* dic{
"allow_chat" = true;//是否允许聊天
"allow_question" = true;//是否允许问答
"room_base_user_count" = 0;//房间基础在线人数
"source_type" = 0;//对应receivedSwitchSource方法的source_type
}
*ps:当房间类型没有聊天或者问答时,对应的字段默认为true
*/
-(void)roomSettingInfo:(NSDictionary *)dic;
/**
* @brief 服务器端给自己设置的UserId
*/
-(void)setMyViewerId:(NSString *)viewerId;
3.5 聊天功能
代理方法(可选)
/**
* @brief 历史聊天数据 (会多次回调)
* @param chatLogArr [{ chatId //聊天ID
content //聊天内容
groupId //聊天组ID
time //时间
userAvatar //用户头像
userId //用户ID
userName //用户名称
userRole //用户角色 (publisher:主讲,student:学生或观众,host:主持人,unknow:其他没有角色,teacher:助教)}]
*/
- (void)onChatLog:(NSArray *)chatLogArr;
/*
* @brief 收到公聊消息
@param message { groupId //聊天组ID
msg //消息内容
time //发布时间
useravatar //用户头像
userid //用户ID
username //用户名称
userrole //用户角色 (publisher:主讲,student:学生或观众,host:主持人,unknow:其他没有角色,teacher:助教) }
*/
- (void)onPublicChatMessage:(NSDictionary *)message;
/**
* @brief 收到私聊信息
* @param dic {fromuserid //发送者用户ID
* fromusername //发送者用户名
* fromuserrole //发送者角色
* msg //消息内容
* time //发送时间
* touserid //接受者用户ID
* tousername //接受者用户名}
*/
- (void)OnPrivateChat:(NSDictionary *)dic;
/*
* @brief 收到自己的禁言消息,如果你被禁言了,你发出的消息只有你自己能看到,其他人看不到
@param message { groupId //聊天组ID
msg //消息内容
time //发布时间
useravatar //用户头像
userid //用户ID
username //用户名称
userrole //用户角色 (publisher:主讲,student:学生或观众,host:主持人,unknow:其他没有角色,teacher:助教) }
*/
- (void)onSilenceUserChatMessage:(NSDictionary *)message;
/**
* @brief 当主讲全体禁言时,你再发消息,会出发此代理方法,information是禁言提示信息
*/
- (void)information:(NSString *)information;
/**
* @brief 自定义消息
*/
- (void)customMessage:(NSString *)message;
/**
* @brief 收到聊天禁言并删除聊天记录
* viewerId 禁言用户id,是自己的话别删除聊天历史,其他人需要删除该用户的聊天
*/
-(void)onBanDeleteChat:(NSDictionary *) viewerDic;
/**
* @brief 收到聊天禁言
* mode 禁言类型 1:个人禁言 2:全员禁言
*/
-(void)onBanChat:(NSDictionary *) modeDic;
/**
* @brief 收到解除禁言事件
* mode 禁言类型 1:个人禁言 2:全员禁言
*/
-(void)onUnBanChat:(NSDictionary *) modeDic;
/**
* @brief 聊天管理
* status 聊天消息的状态 0 显示 1 不显示
* chatIds 聊天消息的id列列表
*/
-(void)chatLogManage:(NSDictionary *) manageDic;
/**
* @brief 禁言用户提示
* @param model BanChatModel 详情
*/
- (void)HDBanChatBroadcastWithModel:(BanChatModel *)model;
主动方法(可选)
/**
* @brief 发送公聊信息
* @param message 发送的消息内容
*/
- (void)chatMessage:(NSString *)message;
/**
* @brief 发送私聊信息
*/
- (void)privateChatWithTouserid:(NSString *)touserid msg:(NSString *)msg;
/**
* @brief 发送公聊信息
* @param message 发送的消息内容
* completion 发送回调 成功或者失败
*/
- (void)sendChatMessage:(NSString *)message completion:(void (^)(BOOL success))completion;
3.6 问答功能
代理方法(可选)
/**
* @brief 收到提问,用户观看时和主讲的互动问答信息
* @param questionDic { groupId //分组ID
content //问答内容
userName //问答用户名
userId //问答用户ID
time //问答时间
id //问答主键ID
useravatar //用户化身 }
*/
- (void)onQuestionDic:(NSDictionary *)questionDic;
/**
* @brief 收到回答
* @param answerDic {content //回复内容
userName //用户名
questionUserId //问题用户ID
time //回复时间
questionId //问题ID
isPrivate //1 私聊回复 0 公聊回复 }
*/
- (void)onAnswerDic:(NSDictionary *)answerDic;
/**
* @brief 收到历史提问&回答 (会多次回调)
* @param questionArr [{content //问答内容
encryptId //加密ID
groupId //分组ID
isPublish //1 发布的问答 0 未发布的问答
questionUserId //问答用户ID
questionUserName //问答用户名
time //问答时间
triggerTime //问答具体时间}]
* @param answerArr [{answerUserId //回复用户ID
answerUserName //回复名
answerUserRole //回复角色(主讲、助教)
content //回复内容
encryptId //加密ID
groupId //分组ID
isPrivate //1 私聊回复 0 公共回复
time = 135; //回复时间
triggerTime //回复具体时间}]
*/
- (void)onQuestionArr:(NSArray *)questionArr onAnswerArr:(NSArray *)answerArr;
/**
* @brief 发布问答的id
*/
- (void)publish_question:(NSString *)publishId;
主动方法(可选)
/**
* @brief 提问
* @param message 提问内容
*/
- (void)question:(NSString *)message;
3.7 连麦功能
推流质量回调(单人连麦)(代理方法)
方法 | 注释 |
---|---|
(void)onPushStreamQuality: | 推流质量回调 (单人连麦) |
示例代码
/// 推流质量回调 (单人连麦)
/// @param quality 流质量
- (void)onPushStreamQuality:(HDSStreamQuality)quality;
拉流质量回调(单人连麦)(代理方法)
方法 | 注释 |
---|---|
(void)onPullStreamQuality: quality: | 拉流质量回调 (单人连麦) |
示例代码
/// 拉流质量回调 (单人连麦)
/// @param quality 流质量
- (void)onPullStreamQuality:(NSString *)streamID quality:(HDSStreamQuality)quality;
HDSStreamQuality
/// 网络质量 -1为空值
typedef struct {
int rtt; //本机到服务器的往返时延(ms)
int pktLostRate; //发送丢包(0~100)
int quality; //本机上行网络质量(0~3),分别对应优、良、中、差
int rxQuality; //本机下行网络质量(0~3),分别对应优、良、中、差
double akbps; //音频码率(kb/s)
double afps; //音频帧率(网络接收)
double vkbps; //视频码率(kbps)
double vfps; //视频帧率(网络接收)
} HDSStreamQuality;
房间连麦信息
房间连麦状态(代理)
方法 | 说明 |
---|---|
onMediaCallStatusDidChange: | 房间是否允许连麦 |
示例代码
/// 房间是否允许连麦
/// @param callInfo 房间信息
- (void)onMediaCallStatusDidChange:(HDSRoomCallInfo *)callInfo;
HDSRoomCallInfo
参数 | 说明 |
---|---|
isMultiMediaCallRoom | 是否是多人连麦房间( YES 多人连麦 / NO 单人连麦 ) |
isMediaCallFuncEnable | 是否开启连麦功能 ( YES 房间连麦功能开启 / NO 房间连麦功能未开启 ) |
disableReason | 房间连麦功能未开启原因 |
roomCallType | 连麦类型 ( HDSRoomCallType ) |
typedef NS_ENUM(NSInteger, HDSRoomCallType) {
HDSRoomCallTypeAudio, /// 音频连麦房间 (多人连麦情况下只能申请音频连麦)
HDSRoomCallTypeAudioVideo, /// 视频连麦房间 (单人连麦可申请音频或视频连麦)
};
连麦模式切换(多人连麦)(代理)
方法 | 说明 |
---|---|
(void)onMediaCallModeDidChange: | 连麦模式切换 只有多人连麦才会触发 |
示例代码
/// 连麦模式切换 只有多人连麦才会触发
/// @param mode 模式 7 无延迟 / 8 低延迟 / 9 普通
- (void)onMediaCallModeDidChange:(int)mode;
主动发起上麦操作
主动申请上麦(主动)
方法 | 说明 |
---|---|
(void)callInPreviewWithType: succed: failed: | 主动申请上麦 |
示例代码
/// 主动申请上麦
/// @param type 类型
/// @param succedClosure 成功回调 (preview 为自己的预览视图,仅在多人连麦使用)
/// @param failedClosure 失败回调
- (void)callInPreviewWithType:(HDSMediaCallType)type
succed:(void(^)(UIView *preview))succedClosure
failed:(void(^)(HDSMediaCallError error))failedClosure;
参数 | 说明 | |
---|---|---|
type | HDSMediaCallTypeAudio | 音频连麦 |
HDSMediaCallTypeAudioVideo | 视频连麦 | |
succedClosure | preview | 本人的预览视图 |
failedClosure | error | 连麦错误信息 |
主动挂断(下课也需要调用)(主动)
方法 | 说明 |
---|---|
(void)hangup: | 主动挂断 |
示例代码
/// 挂断
/// @param closure 回调
/// 主动挂断连麦,用户主动点击下麦按钮时需要关心finishClosure的返回值,退出直播间、下课等调用hangup时不需要关心callback
- (void)hangup:(hangupClosure)closure;
参数 | 说明 |
---|---|
closure | 挂断回调 |
被挂断(多人连麦)(代理)
方法 | 说明 |
---|---|
(void)onCallWasHangup | 被挂断 |
示例代码
/// 被挂断
- (void)onCallWasHangup;
被邀请上麦操作
被邀请上麦(多人连麦)(代理)
方法 | 说明 |
---|---|
(void)onInviteCall | 邀请上麦 |
示例代码
/// 邀请上麦
- (void)onInviteCall;
同意邀请(多人连麦)(主动)
方法 | 说明 |
---|---|
(void)agreeCallInPreview: failed: | 同意上麦 |
示例代码
/// 同意上麦
/// @param succedClosure 成功回调 (preview 为自己的预览视图,仅在多人连麦使用)
/// @param failedClosure 失败回调
- (void)agreeCallInPreview:(void(^)(UIView *preview))succedClosure
failed:(void(^)(HDSMediaCallError error))failedClosure;
参数 | 说明 |
---|---|
succedClosure | 成功回调 (preview 为自己的预览视图,仅在多人连麦使用) |
failedClosure | 失败回调 |
邀请被取消(多人连麦)(代理)
方法 | 说明 |
---|---|
(void)onInviteCanceled | 邀请被取消 |
示例代码
/// 邀请被取消
- (void)onInviteCanceled;
拒绝邀请(多人连麦)(主动)
方法 | 说明 |
---|---|
(void)rejectCall | 拒接邀请 |
示例代码
/// 拒接邀请
- (void)rejectCall;
远端流相关操作
远端流可用(代理)
方法 | 说明 |
---|---|
(void)onRemoteStreamEnable: | 远端流可用 |
示例代码
/// 远端流可用
/// @param streamModel 流信息
- (void)onRemoteStreamEnable:(HDSStreamModel *)streamModel;
HDSStreamModel
参数 | 说明 |
---|---|
hds_remoteView | 远端流视图 |
userInfo | 用户信息 (HDSStreamUserInfoModel) |
HDSStreamUserInfoModel
方法 | 说明 |
---|---|
userId | 用户ID |
userName | 用户名 |
userRole | 用户角色 (0 :老师) |
isAudioEnable | 声音是否可用 |
isVideoEnable | 视频是否可用 |
拉远端流(主动)
方法 | 说明 |
---|---|
(void)pullRemoteStream: succed: failed: | 拉远端流 |
示例代码
/// 拉远端流
/// @param userId 用户ID
/// @param succedClosure 成功
/// @param failedClosure 失败
- (void)pullRemoteStream:(NSString *)userId
succed:(pullStreamSuccedClosure)succedClosure
failed:(pullStreamFailedClosure)failedClosure;
参数 | 说明 |
---|---|
userId | 用户ID |
succedClosure | 成功回调(HDSStreamModel) |
failedClosure | 错误回调 |
HDSStreamModel
参数 | 说明 |
---|---|
hds_remoteView | 远端流视图 |
userInfo | 用户信息 (HDSStreamUserInfoModel) |
HDSStreamUserInfoModel
方法 | 说明 |
---|---|
userId | 用户ID |
userName | 用户名 |
userRole | 用户角色 (0 :老师) |
isAudioEnable | 声音是否可用 |
isVideoEnable | 视频是否可用 |
远端流不可用(多人连麦)(代理)
方法 | 说明 |
---|---|
(void)onRemoteStreamDisable: | 远端流不可用 |
示例代码
/// 远端流不可用
/// @param streamModel 流信息
- (void)onRemoteStreamDisable:(HDSStreamModel *)streamModel;
参数 | 说明 |
---|---|
streamModel | 流信息 |
HDSStreamModel
参数 | 说明 |
---|---|
hds_remoteView | 远端流视图 |
userInfo | 用户信息 (HDSStreamUserInfoModel) |
HDSStreamUserInfoModel
方法 | 说明 |
---|---|
userId | 用户ID |
userName | 用户名 |
userRole | 用户角色 (0 :老师) |
isAudioEnable | 声音是否可用 |
isVideoEnable | 视频是否可用 |
移除远端流(多人连麦)(主动)
方法 | 说明 |
---|---|
(void)removeRemoteStream: | 移除远端流 |
示例代码
/// 移除远端流
/// @param userId 远端流用户id
- (void)removeRemoteStream:(NSString *)userId;
参数 | 说明 |
---|---|
userId | 远端流不可用的用户ID |
连麦中相关操作
设置本地视频开启 (开始直播之后生效)(多人连麦)(主动)
方法 | 说明 |
---|---|
(BOOL)setLocalVideoEnable: | 设置本地视频开启 (开始直播之后生效) |
示例代码
/// 设置本地视频开启 (开始直播之后生效)
/// @param enable 是否开启 YES 开启/ NO 关闭
/// @return 是否操作成功
- (BOOL)setLocalVideoEnable:(BOOL)enable;
参数 | 说明 |
---|---|
enable | 是否开启 YES 开启/ NO 关闭 |
视频状态改变(多人连麦)(代理)
方法 | 说明 |
---|---|
(void)onVideoStatusDidChange: userId: | 视频状态改变 |
示例代码
/// 视频状态改变
/// @param status 是否可用
/// @param userId 用户id
- (void)onVideoStatusDidChange:(BOOL)status userId:(NSString *)userId;
参数 | 说明 |
---|---|
status | 是否可用 |
userId | 用户id |
注:自己主动操作本地视频状态也会回调此代理
设置本地音频开启(开始直播之后生效)(多人连麦)(主动)
方法 | 说明 |
---|---|
(BOOL)setLocalAudioEnable: | 设置本地音频开启(开始直播之后生效) |
示例代码
/// 设置本地音频开启(开始直播之后生效)
/// @param enable 是否开启 YES 开启/ NO 关闭
/// @return 是否操作成功
- (BOOL)setLocalAudioEnable:(BOOL)enable;
参数 | 说明 |
---|---|
enable | 是否开启 YES 开启/ NO 关闭 |
音频状态改变(多人连麦)(代理)
方法 | 说明 |
---|---|
(void)onAudioStatusDidChange: userId: byTeacher: | 音频状态改变 |
示例代码
/// 音频状态改变
/// @param status 是否可用
/// @param userId 用户id
/// @param byTeacher 是否是老师操作
- (void)onAudioStatusDidChange:(BOOL)status userId:(NSString *)userId byTeacher:(BOOL)byTeacher;
参数 | 说明 |
---|---|
status | 是否可用 |
userId | 用户id |
byTeacher | 是否是老师操作 |
注:自己主动操作本地音频状态也会回调此代理
切换本地摄像头,默认前置(多人连麦)(主动)
方法 | 说明 |
---|---|
(BOOL)switchCamera; | 切换本地摄像头,默认前置 |
示例代码
/// 切换本地摄像头,默认前置
/// @return 是否操作成功
- (BOOL)switchCamera;
连麦异常(代理)
方法 | 说明 |
---|---|
onConnectionException: | 异常挂断 |
示例代码
/// 异常挂断
/// @param error 错误原因
- (void)onConnectionException:(HDSMediaCallError)error;
参数 | 说明 |
---|---|
HDSMediaCallErrorInCalling | 连麦失败 |
HDSMediaCallErrorRoomTypeDidChange | 连麦房间类型改变(需要退出重进) |
HDSMediaCallErroronMumberLimit | 连麦人数已达上限 |
HDSMediaCallErrorAbilityDown | 连麦功能不可用(需要退出重进) |
HDSMediaCallErrorPullStreamFailed | 拉流失败 |
HDSMediaCallErrorConnectTimeOut | 连麦申请超时 |
特别注意多人连麦需要退出房间重新登陆的事件
房间配置事件 | 说明 |
---|---|
OnErrorType_LoginFailed | 登陆失败(需要退出重进) |
initFailedClosure | 初始化SDK失败(需要退出重进) |
OnErrorType_GetPlaySourceFailed | 获取播放源失败(需要退出重进) |
OnErrorType_GetSummaryFailed | 获取摘要失败(需要退出重进) |
连麦事件 | 说明 |
---|---|
HDSMediaCallErrorRoomTypeDidChange | 连麦房间类型改变(需要退出重进) |
HDSMediaCallErrorAbilityDown | 连麦功能不可用(需要退出重进) |
3.8 切换线路和清晰度
代理方法(可选)
/**
* The New Method (3.14.0)
* @brief 是否开启音频模式
* @param hasAudio HAVE_AUDIO_LINE_TURE 有音频 HAVE_AUDIO_LINE_FALSE 无音频
*
* 触发回调条件 1.初始化SDK登录成功后
*/
- (void)HDAudioMode:(HAVE_AUDIO_LINE)hasAudio;
/**
* The New Method (3.14.0)
* @brief 房间所包含的清晰度 (会多次回调)
* @param dict 清晰度数据
* 清晰度数据 key(包含的键值) type(数据类型) description(描述)
* qualityList(清晰度列表) array @[HDQualityModel(清晰度详情),HDQualityModel(清晰度详情)]
* currentQuality(当前清晰度) object HDQualityModel(清晰度详情)
*
* 触发回调条件 1.初始化SDK登录成功后
* 2.主动调用切换清晰度方法
* 3.主动调用切换视频模式回调
*/
- (void)HDReceivedVideoQuality:(NSDictionary *)dict;
/**
* The New Method (3.14.0)
* @brief 房间包含的音视频线路 (会多次回调)
* @param dict 线路数据
* 线路数据 key(包含的键值) type(数据类型) description(描述)
* lineList(线路列表) array @[@"line1",@"line2"]
* indexNum(当前线路下标) integer 0
*
* 触发回调条件 1.初始化SDK登录成功后
* 2.主动调用切换清晰度方法
* 3.主动调用切换线路方法
* 4.主动调用切换音视频模式回调
*/
- (void)HDReceivedVideoAudioLines:(NSDictionary *)dict;
主动方法(可选)
/**
* The New Method (3.14.0)
* @brief 切换播放类型
* @param mode PLAY_MODE_TYEP_VIDEO 视频模式(默认)
* PLAY_MODE_TYEP_AUDIO 音频模式(当前回放包含音频线路)
* @param completion 切换结果
* { success 0 切换成功 -1切换失败 -2 切换频繁
* reason 错误原因 }
*
* 切换播放器类型 切换为音频,回调 - (void)HDReceivedVideoAudioLines:(NSDictionary *)dict;
* 切换为视频,回调 - (void)HDReceivedVideoQuality:(NSDictionary *)dict;
* - (void)HDReceivedVideoAudioLines:(NSDictionary *)dict;
*
*/
- (void)changePlayMode:(PLAY_MODE_TYEP)mode completion:(void (^)(NSDictionary * results))completion;
/**
* The New Method (3.14.0)
* @brief 切换清晰度
* @param quality 清晰度
* @param completion 切换结果
* { success 0 切换成功 -1切换失败 -2 切换频繁
* reason 错误原因 }
*
* 切换清晰度回调 - (void)HDReceivedVideoQuality:(NSDictionary *)dict;
* - (void)HDReceivedVideoAudioLines:(NSDictionary *)dict;
*/
- (void)changeQuality:(NSString *)quality completion:(void (^)(NSDictionary * results))completion;
/**
* The New Method (3.14.0)
* @brief 切换线路
* @param index 选择线路下标
* @param completion 切换结果
* { success 0 切换成功 -1切换失败 -2 切换频繁
* reason 错误原因 }
*
* 切换线路回调方法 - (void)HDReceivedVideoAudioLines:(NSDictionary *)dict;
*/
- (void)changeLine:(NSInteger)index completion:(void (^)(NSDictionary * results))completion;
3.9 答题卡功能
代理方法(可选)
/**
* @brief 开始答题
*/
- (void)start_vote:(NSInteger)count singleSelection:(BOOL)single;
/**
* @brief 结束答题
*/
- (void)stop_vote;
/**
* @brief 答题结果
* @param resultDic {answerCount //参与回答人数
correctOption //正确答案 (单选字符串,多选字符串数组)
statisics[{ //统计数组
count //选择当前选项人数
option //选项序号
percent //正确率 }]
voteCount //题目数量
voteId //题目ID
voteType //题目类型}
*/
- (void)vote_result:(NSDictionary *)resultDic;
/**
* @brief 收到打卡提交结果
* dic{
"success": true,
"data": {
"isRepeat": false//是否重复提交打卡
}
}
*/
-(void)hdReceivedPunchResultWithDict:(NSDictionary *)dic;
/**
* @brief 收到开始打卡
* dic {
"punchId": "punchId",
"expireTime": "2019-10-26 10:00:00",
"remainDuration": 124
"tips" // 没有提示语则不返回该字段 (新增)
}
* 当没有设置时长,即无过期时间时
* {
"punchId": "asasdasdasdasd",
"remainDuration": -1 //其中-1表示剩余无限时间。
}
*/
-(void)hdReceivedStartPunchWithDict:(NSDictionary *)dic;
/**
* @brief 收到结束打卡
* dic{
"punchId": "punchId"
}
*/
-(void)hdReceivedEndPunchWithDict:(NSDictionary *)dic;
主动方法(可选)
/**
* @brief 答单选题
*/
-(void)reply_vote_single:(NSInteger)index;
/**
* @brief 答多选题
@param IndexArray [题目index,题目index] 例:[1,2]
*/
-(void)reply_vote_multiple:(NSMutableArray *)indexArray;
3.10 问卷功能
代理方法(可选)
/**
* @brief 发布问卷
*/
- (void)questionnaire_publish;
/**
* @brief 结束发布问卷
*/
- (void)questionnaire_publish_stop;
/**
* @brief 获取问卷详细内容
* @param detailDic { forcibly //1就是强制答卷,0为非强制答卷
id //问卷主键ID
subjects //包含的项目
submitedAction //1提交后查看答案,0为提交后不查看答案
title //标题 }
*/
- (void)questionnaireDetailInformation:(NSDictionary *)detailDic;
/**
* @brief 获取问卷统计
* @param staticsDic { forcibly //1就是强制答卷,0为非强制答卷
id //问卷主键ID
subjects //包含的项目
submitedAction //1提交后查看答案,0为提交后不查看答案
title //标题 }
*/
- (void)questionnaireStaticsInformation:(NSDictionary *)staticsDic;
/**
* @brief 提交问卷结果(成功,失败)
*/
- (void)commitQuestionnaireResult:(BOOL)success;
/**
* @brief 问卷功能
*/
- (void)questionnaireWithTitle:(NSString *)title url:(NSString *)url;
主动方法(可选)
/**
* @brief 提交问卷结果
* @param dic{subjectsAnswer[{selectedOptionId //选中选项ID
subjectId //题目ID}]}
*/
-(void)commitQuestionnaire:(NSDictionary *)dic;
/**
* @brief 主动请求问卷
*/
-(void)getPublishingQuestionnaire;
3.11 广播功能
代理方法(可选)
/**
* @brief 接收到发送的广播
* @param dic {content //广播内容
userid //发布者ID
username //发布者名字
userrole //发布者角色 }
*/
- (void)broadcast_msg:(NSDictionary *)dic;
/**
* @brief 接收到最后一条广播(直播中途进入,会返回最后一条广播)(会多次回调)
* @param array[{ content //广播内容
publisherId //发布者ID
publisherName //发布者名字
publisherRole //发布者角色
time //发布时间
}]
*/
- (void)broadcastLast_msg:(NSArray *)array;
/**
* @brief 删除广播
* @param dic 删除数据
dic {action //操作 1.删除
id //广播id }
*/
- (void)broadcast_delete:(NSDictionary *)dic;
3.12 签到功能
代理方法(可选)
/**
* @brief 开始签到
*/
- (void)start_rollcall:(NSInteger)duration;
主动方法(可选)
/**
* @brief 签到
*/
-(void)answer_rollcall;
/**
提交打卡
@param punchId 打卡id
*/
- (void)hdCommitPunchWithPunchId:(NSString *)punchId;
/**
查询打卡信息
*/
- (void)hdInquirePunchInformation;
3.13 抽奖功能
代理方法(可选)
/**
* @brief 开始抽奖
*/
- (void)start_lottery;
/**
* @brief 抽奖结果
* remainNum 剩余奖品数
*/
- (void)lottery_resultWithCode:(NSString *)code myself:(BOOL)myself winnerName:(NSString *)winnerName remainNum:(NSInteger)remainNum;
/**
* @brief 退出抽奖
*/
- (void)stop_lottery;
3.14 修改昵称
代理方法(可选)
/**
* @brief 修改昵称
*/
- (void)onChangeNickname:(NSString *)nickNime;
主动方法(可选)
/**
* @brief 修改昵称
* @param nickName 修改后的昵称
*/
- (void)changeNickName:(NSString *)nickName;
3.15 在线人数
代理方法(可选)
/**
* @brief 收到在线人数
*/
- (void)onUserCount:(NSString *)count;
/**
收到老师列表
teachers = (
{
id = "";//老师id
ip = "";//IP地址
name = "";老师昵称
role = teacher;//角色
}
);
*/
-(void)onOnlineTeachers:(NSDictionary *)dic;
主动放法(可选)
/**
获取老师列表
*/
- (void)getOnlineTeachers;
3.16 随堂测功能
代理方法(可选)
/**
* @brief 接收到随堂测
* rseultDic 随堂测内容
resultDic {
isExist //是否存在正在发布的随堂测 1 存在 0 不存在
practice{
id //随堂测ID
isAnswered //是否已答题 true: 已答题, false: 未答题
options //选项数组
({
id //选项ID
index //选项索引
})
publishTime //随堂测发布时间
status //随堂测状态: 1 发布中 2 停止发布 3 已关闭
type //随堂测类型: 0 判断 1 单选 2 多选
submitRecord //如果已答题,返回该学员答题记录,如果未答题,服务端不返回该字段
({
optionId //选项ID
optionIndex //选项索引
})
}
serverTime //分发时间
}
*
*/
-(void)receivePracticeWithDic:(NSDictionary *) resultDic;
/**
* @brief 随堂测提交结果
* rseultDic 提交结果,调用commitPracticeWithPracticeId:(NSString *)practiceId options:(NSArray *)options后执行
*
resultDic {datas {practice //随堂测
{ answerResult //回答是否正确 1 正确 0 错误
id //随堂测ID
isRepeatAnswered //是否重复答题 true: 重复答题, false: 第一次答题
options ({ count //参与人数
id //选项主键ID
index //选项序号
isCorrect //是否正确
percent //选项占比})
submitRecord 如果重复答题,则返回该学员第一次提交的记录,否则,返回该学员当前提交记录
({ optionId //提交记录 提交选项ID
optionIndex //提交选项序号})
type //随堂测类型: 0 判断 1 单选 2 多选}}}
*/
-(void)practiceSubmitResultsWithDic:(NSDictionary *) resultDic;
/**
* @brief 随堂测统计结果
* rseultDic 统计结果,调用getPracticeStatisWithPracticeId:(NSString *)practiceId后执行
resultDic {practice { //随堂测
answerPersonNum //回答该随堂测的人数
correctPersonNum //回答正确的人数
correctRate //正确率
id //随堂测ID
options ({ //选项数组
count //选择该选项的人数
id //选项ID
index //选项序号
isCorrect //是否为正确选项 1 正确 0 错误
percent //选择该选项的百分比})
status //随堂测状态 1 发布中 2 停止发布
type //随堂测类型: 0 判断 1 单选 2 多选}}
*/
-(void)practiceStatisResultsWithDic:(NSDictionary *) resultDic;
/**
* @brief 随堂测排名结果
* rseultDic 排名结果,调用getPracticeRankWithPracticeId:(NSString *)practiceId后执行
ressult{practice { //随堂测
id //随堂测主键ID
ranking ({ //排名
costTime //回答用时
viewerId //用户ID
viewerName //用户名})}}
*/
-(void)practiceRankResultsWithDic:(NSDictionary *) resultDic;
/**
* @brief 停止随堂测
* rseultDic 结果
* resultDic {practiceId //随堂测主键ID}
*/
-(void)practiceStopWithDic:(NSDictionary *) resultDic;
/**
* @brief 关闭随堂测
* rseultDic 结果
* resultDic {practiceId //随堂测主键ID}
*/
-(void)practiceCloseWithDic:(NSDictionary *) resultDic;
/**
* @brief 收到奖杯
* dic 结果
* "type": 1 奖杯 2 其他
* "viewerName": 获奖用户名
* "viewerId": 获奖用户ID
*/
-(void)prize_sendWithDict:(NSDictionary *)dic;
主动方法(可选)
/**
* @brief 提交随堂测
* @param practiceId 随堂测ID
* @param options 选项ID
*/
- (void)commitPracticeWithPracticeId:(NSString *)practiceId options:(NSArray *)options;
/**
* @brief 获取随堂测统计信息(可多次调用)
* @param practiceId 随堂测ID
*/
-(void)getPracticeStatisWithPracticeId:(NSString *)practiceId;
/**
* @brief 获取随堂测排名(可多次调用)
* @param practiceId 随堂测ID
*/
-(void)getPracticeRankWithPracticeId:(NSString *)practiceId;
/**
* @brief 获取随堂测
* @param practiceId 随堂测ID(没有传@"")
*/
-(void)getPracticeInformation:(NSString *)practiceId;
3.17 公告
代理方法(可选)
/**
* @brief 公告
*/
- (void)announcement:(NSString *)str;
/**
* @brief 监听到有公告消息
* @dict {action //action 返回release 取出公告内容,action 返回remove 删除公告
announcement //公告内容}
*/
- (void)on_announcement:(NSDictionary *)dict;
3.18 跑马灯
代理方法(可选)
/**
* @brief 跑马灯
* @param dic action [{ //事件
duration //执行时间
end { //结束位置
alpha //透明度
xpos //x坐标
ypos //y坐标 },
start { //开始位置
alpha //透明度
xpos //x坐标
ypos //y坐标}]
image { //包含图片
height //图片高度
image_url //地址
width //图片宽度}
loop //循环次数 -1 无限循环
text { //文字信息
color //文字颜色
content //文字内容
font_size //字体大小}
type //当前类型 text 文本 image 图片
*/
-(void)receivedMarqueeInfo:(NSDictionary *)dic;
3.19 播放器状态
播放器状态类型
/**
* 视频播放状态
* HDSMediaPlaybackStateStopped 播放停止
* HDSMediaPlaybackStatePlaying 开始播放
* HDSMediaPlaybackStatePaused 暂停播放
* HDSMediaPlaybackStateInterrupted 播放间断
* HDSMediaPlaybackStateSeekingForward 播放快进
* HDSMediaPlaybackStateSeekingBackward 播放后退
*/
typedef NS_ENUM(NSUInteger, HDSMediaPlaybackState) {
HDSMediaPlaybackStateStopped,
HDSMediaPlaybackStatePlaying,
HDSMediaPlaybackStatePaused,
HDSMediaPlaybackStateInterrupted,
HDSMediaPlaybackStateSeekingForward,
HDSMediaPlaybackStateSeekingBackward,
};
/**
* 视频加载状态
* HDSMediaLoadStateUnknown 未知状态
* HDSMediaLoadStatePlayable 视频未完成全部缓冲,但已缓冲的数据可以进行播放
* HDSMediaLoadStatePlaythroughOK 缓冲已经完成
* HDSMediaLoadStateStalled 缓冲已经开始
*/
typedef NS_ENUM(NSUInteger, HDSMediaLoadState) {
HDSMediaLoadStateUnknown,
HDSMediaLoadStatePlayable,
HDSMediaLoadStatePlaythroughOK,
HDSMediaLoadStateStalled,
};
代理方法(可选)
/**
* @brief 视频状态改变
* @param state
* HDSMediaPlaybackStateStopped 播放停止
* HDSMediaPlaybackStatePlaying 开始播放
* HDSMediaPlaybackStatePaused 暂停播放
* HDSMediaPlaybackStateInterrupted 播放间断
* HDSMediaPlaybackStateSeekingForward 播放快进
* HDSMediaPlaybackStateSeekingBackward 播放后退
*/
- (void)HDSMediaPlayBackStateDidChange:(HDSMediaPlaybackState)state;
/**
* @brief 视频加载状态
* @param state 播放状态
* HDSMediaLoadStateUnknown 未知状态
* HDSMediaLoadStatePlayable 视频未完成全部缓存,但已缓存的数据可以进行播放
* HDSMediaLoadStatePlaythroughOK 缓冲已经完成
* HDSMediaLoadStateStalled 缓冲已经开始
*/
- (void)HDSMediaLoadStateDidChange:(HDSMediaLoadState)state;
/**
* @brief 播放器初始化完成 (会多次回调)
*/
- (void)HDMediaPlaybackIsPreparedToPlayDidChange;
3.20 视频缓存速度
代理方法(可选)
/**
* @brief 视频加载速度
* @param speed 视频加载速度字符串
*/
- (void)onBufferSpeed:(NSString *)speed;
3.21 用户进出直播间提醒
代理方法(可选)
/**
* @brief 用户进出直播间提示
* @param model RemindModel 详情
*/
- (void)HDUserRemindWithModel:(RemindModel *)model;
3.22 抽奖2.0功能 (该功能需单独开启)
代理方法(可选)
/**
* @brief 抽奖2.0 抽奖信息回调 (该功能需要单独开启)
* @param model NewLotteryMessageModel 详情
*/
- (void)HDOnLotteryWithModel:(NewLotteryMessageModel *)model;
主动方法 (可选)
/**
* @brief 抽奖2.0 查询抽奖状态
*/
- (void)queryLotteryStatus;
/**
* @brief 抽奖2.0 提交中奖用户信息
* @param collectInfos 用户信息
* collectInfos = @[@{@"index":@(0),@"value":@""}];
* @param lotteryId 中奖订单ID (非必选)
* @param completion 请求结果回调
*/
- (void)commitLottery:(NSArray *)collectInfos lotteryId:(NSString *)lotteryId completion:(void (^)(BOOL success))completion;
3.23 互动功能
互动组件功能配置(代理方法)
方法 | 注释 |
---|---|
(void)onInteractionFunctionConfig: | 互动组件功能配置 |
示例代码
/// 互动功能配置
/// @param configModel 配置信息
- (void)onInteractionFunctionConfig:(HDSInteractionFunctionModel *)configModel;
HDSInteractionFunctionModel
参数 | 类型 | 注释 | 所在类文件 |
---|---|---|---|
likeModel | HDSInteractionLikeModel | 点赞配置 | CCSDK/PlayParameter.h |
giftModel | HDSInteractionGiftModel | 打赏礼物配置 | CCSDK/PlayParameter.h |
HDSInteractionLikeModel
参数 | 注释 | 所在类文件 |
---|---|---|
likeFunctionConfig | 点赞功能配置 0:关闭 1:直播间配置 2:全局配置 | CCSDK/PlayParameter.h |
HDSInteractionFunctionModel
参数 | 类型 | 注释 | 所在类文件 |
---|---|---|---|
giftModel | HDSInteractionGiftModel | 打赏礼物配置 | CCSDK/PlayParameter.h |
HDSInteractionGiftModel
参数 | 注释 | 所在类文件 |
---|---|---|
giftFunctionConfig | 打赏礼物功能配置 0:关闭 1:直播间配置 2:全局配置 | CCSDK/PlayParameter.h |
specialEffects | 打赏礼物特效配置 0:关闭 1:左侧特效 2:全局特效 | CCSDK/PlayParameter.h |
获取互动组件Token(主动方法)
方法 | 注释 |
---|---|
(void)getInteractionTokenWithClosure: tokenClosure: | 获取互动组件Token |
示例代码
/// 获取互动组件 token
/// @param closure 操作回调 (result 操作状态, message 信息)
/// @param tokenClosure token回调 " result == YES 时返回token, result == NO 时返回 @""(空字符串) "
- (void)getInteractionTokenWithClosure:(completeHandler)closure tokenClosure:(interactionTokenClosure)tokenClosure;
4.常见问题
4.1 旋转屏错误
常用的旋转屏方式
第一个方法决定是否支持多方向旋转屏,如果返回NO则后面的两个方法都不会再被调用,而且只会支持默认的UIInterfaceOrientationMaskPortrait方向;
第二个方法直接返回支持的旋转方向,该方法在iPad上的默认返回值是UIInterfaceOrientationMaskAll,iPhone上的默认返回值是UIInterfaceOrientationMaskAllButUpsideDown,官方文档有说明
第三个方法返回最优先显示的屏幕方向,比如同时支持Portrait和Landscape方向,但想优先显示Landscape方向,那软件启动的时候就会先显示Landscape,在手机切换旋转方向的时候仍然可以在Portrait和Landscape之间切换
HD云直播的页面跳转均是采用模态形式跳转
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion NS_AVAILABLE_IOS(5_0);
在每个控制器或者基类控制器设置旋转选项
#pragma mark - 屏幕旋转
- (BOOL)shouldAutorotate{
return NO;//该旋转的页面自己变量控制
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
4.2 Swift实现代理错误
//初始化
let parameter = PlayParameter.init()
/**
*配置各种参数
*/
//守护代理
guard let player = RequestData else {
return}
player.delegate = self
4.3 查看手机日志
首先: 在AppDelegate中写如下代码(仅限CCSDK);
[[SaveLogUtil sharedInstance]isNeedToSaveLog:YES];
第一步:选择Windows下面的Devices and Simulators
第二步:点击Devices and Simulators 会出现手机信息以及测试的INSTALLED APPS, 点击设置(齿轮图标) 会出现三个选项, 选择Download Container...
第三步: 点击Download Container... 下载并保存日志文件,打开文件找到XXLog文件里面就是相关的打印日志
第四步:这里可以看到相关的请求信息和打印日志, 也可以判断错误原因
4.4 编译失败和打包上架打包失败
错误大意为
Failed to verify bitcode in xxxxx
error: Bundle only contains bitcode-marker /var/folders/s5/lnk362pd4cs0lmtn_43ppjzw0000gn/T/XcodeDistPipeline.2TS/Root/Payload/268YK.appxxxxxxxxxx (armv7)
解决办法:
第一步: xcode -> file -> Workspace Settings
第二步: Shared Workspace Settings:
第三步:Build System -> Legacy Build System
4.5 提交问卷的格式
主动提交问卷这个方法参数格式
-(void)commitQuestionnaire:(NSDictionary *)dic
{
subjectsAnswer = (
{
//单选
selectedOptionId = 6DBB147BC4EF99A7;
subjectId = 5DEEA9F9FD1DDFAD;
},
{
//多选
selectedOptionIds = "A2F4436135131236,1A8C59C6F3A774F5";
subjectId = 658A573395F3E00D;
},
{
//问答
answerContent = Qqq;
subjectId = 10F9E9D82094F36C;
}
);
}
4.6 关于api回调所在线程问题
/**
* @brief 文档加载状态(会在子线程回调)
* index
* 0 文档组件初始化完成
* 1 动画文档加载完成
* 2 非动画文档加载完成
* 3文档组件加载失败
* 4文档图片加载失败
* 5文档动画加载失败
* 6画板加载失败
*/
- (void)docLoadCompleteWithIndex:(NSInteger)index;
/**
* @brief 获取ppt当前页数和总页数 (会多次回调) (会在子线程回调)
*
* 回调当前翻页的页数信息
* 白板docTotalPage一直为0, pageNum从1开始
* 其他文档docTotalPage为正常页数,pageNum从0开始
* @param dictionary 翻页信息
*/
- (void)onPageChange:(NSDictionary *) dictionary;
PS:直播、在线回放只有上述api会在子线程回调,其余的api均在主线程进行回调。