Appearance
千里眼OpenSDK 苹果使用说明
一、环境准备
Objective-C
Xcode 14.0及以上
使⽤语⾔:Objective-C
iPhone ⼿机系统12.0及以上版本
二、创建应用及配置设置
- SDK以主体QLYOpenSDK+依赖SDK+资源包的⽅式提供出来,QLYOpenSDK.framework为主体;
- framework,⽤户只需要调⽤该包中的API;
- 使⽤的时候将所有包拖⼊⼯程中,ONTPlayer与ONTStreamPlayer需设置成Embed & Sign;
- Xcode中General->Frameworks,Libraries,and Embedded Content设置截图如下:
- 在Build settings 当中,找到 Build Options-Enbale Bitcode 设置为NO;
- 在Build Setting 中 找到 Apple Clang - Language - Modules 配置 图中参数为 Yes;
- 在Build Settings -> Other Linker Flags 中添加-ObjC(注意大小写);
- 在测试环境需要更改配置项 App Transport Security Settings。
三、SDK使用方法
1、初始化配置
在APPDelegate中初始化SDK(必须配置)
Objective-C
/// 初始化SDK(带调试环境,推荐使用)
/// @param appid 开放平台注册获取应用Appid (必传)
/// @param privateKey 开放平台注册获取应用privateKey 家庭版可为空
/// @param env 环境类型 参考<QLYEnvironment>
- (void)initSDKWithAppId:(nonnull NSString *)appid
privateKey:(nullable NSString *)privateKey
env:(QLYEnvironment)env;
///SDK环境
typedef NS_OPTIONS(NSUInteger, QLYEnvironment) {
QLYEnvironmentPro = 0, //生产环境
QLYEnvironmentDev, //测试环境
QLYEnvironmentDebug //调试环境
};
///调用示例
[[QLYSDKManager sharedInstance] initSDKWithAppId:<你在平台申请的AppId> privateKey:<你在平台申请的privateKey> environment:<QLYEnvironment>];
设置开启调试模式(可选)
Objective-C
/// 控制台日志输出控制(默认关闭)
/// @param enable 开关参数 YES 默认为QLYLogLevel_default
- (void)setDebug:(BOOL)enable;
/// 日志等级(配置setDebug接口方法为true后生效)
/// @param level debug类型
/// QLYLogLevelDefault = 0, //QLYOpenSDK基础日志
/// QLYLogLevelInterface = 1 << 0, //接口相关日志
/// QLYLogLevelPlayer = 1 << 1, //播放器相关日志
/// QLYLogLevelAll = QLYLogLevelDefault | QLYLogLevelInterface | QLYLogLevelPlayer //所有日志
- (void)setLogLevel:(QLYLogLevel)level;
/// 调用示例
[[QLYSDKManager sharedInstance] setDebug:YES];
[[QLYSDKManager sharedInstance] setLogLevel:(QLYLogLevelAll)];
app出现signal崩溃需要配置下列参数(推荐appdelegate中)
Objective-C
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//出现signal崩溃必须配置
signal(SIGPIPE, SIG_IGN);
}
2、直播相关
开启会话 (直播前需要建立连接)
Objective-C
/// 建立连接
/// @param deviceId 设备id
/// @param channelId 多目摄像机需传入channelId 不传默认主通道
/// @param completion 回调
- (void)connect:(nonnull NSString *)deviceId
channelId:(nullable NSString *)channelId
completion:(QLYInterFaceCompletionHandler)completion;
///示例代码
[[QLYCameraManager sharedInstance] connect:model.deviceId channelId:@"" completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
if (isSucceeded) {
//建立连接 成功,跳转至直播页面
}else{
// 链接失败,异常处理
}
}];
播放器配置及播放
Objective-C
/// 初始化普通播放器
/// @param deviceId 设备id
/// @param config 配置项模型
- (instancetype)initWithDevice:(NSString *)deviceId
channelId:(NSString *_Nullable)channelId
config:(QLYPlayerConfig *)config;
///QLYPlayerConfig 配置项
typedef NS_ENUM(NSUInteger, QLYPlayType) {
QLYPlayerTypeNormal = 0, //普通播放(告警播放)
QLYPlayerTypeTimeLine = 1, //时间轴 (直播模式)
};
///示例代码
QLYPlayerConfig *playerConfig = [[QLYPlayerConfig alloc]init];
playerConfig.playType = QLYPlayerTypeTimeLine;
QLYPlayer *player = [[QLYPlayer alloc] initWithDevice:cameaInfo.deviceId channelId:@"" config:playerConfig];
player.delegate = self;
[self.view addSubview:player.playerPreview];
/// 准备播放
[self.player prepare];
/// 开始播放
[self.player start];
播放器状态监听回调说明
Objective-C ///常规播放器状态
QLYPlayerStatusError = -1, //错误
QLYPlayerStatusIdle = 0, //初始状态
QLYPlayerStatusPreparing = 1, //准备中
QLYPlayerStatusPrepared = 2, //准备完成
QLYPlayerStatusBuffering = 3, //缓冲中
QLYPlayerStatusBuffered = 4, //缓冲完成
QLYPlayerStatusPlaying = 5, //正在播放
QLYPlayerStatusPaused = 6, //暂停
QLYPlayerStatusStoped = 7, //停止
QLYPlayerStatusCompleted = 8, //完成
/// 播放器当前状态
/// @param playerStatus 播放器状态 参考QLYPlayerStatus
/// @param code 播放器异常状态返回值
- (void)QLYPlayerStatusChanged:(QLYPlayerStatus)playerStatus code:(QLYPlayerErrorCode)code;
暂停播放
Objective-C
/// 暂停播放
- (void)pause;
恢复播放
Objective-C
/// 恢复播放
- (void)resume;
语音通话
- 使⽤该功能必须在直播状态下使⽤,当处于通话状态时例如回后台或离开当前语⾳通话⻚⾯应停⽌语⾳通话。
- 通话结束后若出现直播声⾳⼩,未能恢复的情况下,可以调⽤播放器的switchToLive解决。
Objective-C
/// 开始语音推流 (推荐)
/// QLYPlayerAPIStatusHandled代理方法监听API是否调用成功
/// @param isDuplexTalk 是否
- (void)startAudioTalk:(BOOL)isDuplexTalk;
/// 语音推流结束
/// QLYPlayerAPIStatusHandled代理方法监听API是否调用成功
- (void)stopAudioTalk;
语音状态监听说明
JSON QLYAudioStateAvailable = 0, //可进行通话
QLYAudioStateUnAvailable = 1, //不可进行通话
QLYAudioStateError, //异常主动终止
QLYAudioErrorCodeOther = 1, //其他人在通话
QLYAudioErrorCodePlayer = 2, //播放器报错
/// 当前通话是否可用
/// @param audioState 当前录音状态是否可用 参考QLYAudioState
/// @param code 当QLYAudioState = QLYAudioStateError 状态 使用
- (void)QLYPlayerAudioStateChanged:(QLYAudioState)audioState code:(QLYAudioErrorCode)code;
释放播放器
- 如果在当前播放⻚⾯执⾏了releasePlayer⽅法,需重新initVNPlayer播放器
Objective-C
[self.player releasePlayer];
倍速播放
Objective-C
///倍速播放
///目前支持(0.5 1 2 4 8 16 32)
///gb设备sd卡倍速目前支持(0.5 1 2 4 )
- (void)setPlaySpeed:(float)speed;
播放器静音
Objective-C
- (void)setMute:(BOOL)isMute;
获取当前播放时间
JSON//播放器当前时间 单位s 例如 1616119692.473 (注意:如果播放器时间获取为0,端侧UI最好不遵循此时间)
- (double)getCurrentPlayTime;
切换为直播
JSON/// 回到直播
- (void)switchToLive;
设置告警信息
JSON/// 告警播放配置告警信息 QLYPlayType = QLYPlayerTypeTimeLine 使用
- (void)setEventInfo:(QLYTimeLineEvent *)eventInfo;
高清切换
Objective-C
// 高清标清切换
/// @param deviceId 设备mac
/// @param hdVideoValue 0.关;1.开
/// @param completion 回调
- (void)switchPlaybackQuality:(nonnull NSString *)deviceId
hdVideoValue:(NSInteger)hdVideoValue
completion:(QLYInterFaceCompletionHandler)completion;
///示例代码
[[QLYSDKManager sharedInstance] switchPlaybackQuality:_cameraInfo.deviceId hdVideoValue:(isHD ? 1 : 0) completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
if (isSucceeded) {
// 高清切换成功
} else {
// 高清切换失败
}
}];
屏幕旋转
Objective-C
// 屏幕旋转
/// @param deviceId 设备mac
/// @param imageRotateValue 0.不旋;1.旋转180°
/// @param completion 回调
- (void)rotate:(nonnull NSString *)deviceId
imageRotateValue:(NSInteger)imageRotateValue
completion:(QLYInterFaceCompletionHandler)completion;
///示例代码
[[QLYSDKManager sharedInstance] rotate:_cameraInfo.deviceId imageRotateValue:(isRotate ? 1 : 0) completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
if (isSucceeded) {
// 旋转图像成功
} else {
// 旋转图像失败
}
}];
断开会话
- 在完成对摄像头操作后需要断开会话
Objective-C
[[VNCameraManager sharedInstance] disConnect];
3、视频回看
直播和回放互相切换⽆需重新初始化播放器,直接进⾏ seek ,回放部分初始化与释放阶段与直播类似,这⼀节只概述回放相关的细节,详细示例参⻅demo
获取回放片段
Objective-C
/// 获取云存储timeLineSecion
/// @param deviceId 设备Id Y
/// @param channelId 多目摄像机需传入channelId 不传默认主通道
/// @param startTime 过滤开始时间,单位毫秒 13位时间戳 N
/// @param endTime 过滤结束时间 ,单位毫秒 13位时间戳 N
/// @param shareId 分享id N
/// @param completion 回调 Y response<NSArray<QLYTimeLineSection>>
- (void)getTimelineSectionList:(nonnull NSString *)deviceId
channelId:(nullable NSString *)channelId
startTime:(nullable NSNumber *)startTime
endTime:(nullable NSNumber *)endTime
shareId:(nullable NSString *)shareId
completion:(QLYInterFaceCompletionHandler)completion;
///示例代码
[[QLYSDKManager sharedInstance] getTimelineSectionList:self.cameraInfo.deviceId channelId:@"" startTime:@(startTimeInterval) endTime:endTime? endTime :@(endTimeInterval) shareId:nil completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
if (isSucceeded) {
NSMutableArray * tempArr = [NSMutableArray arrayWithCapacity:0];
if ([response isKindOfClass:[NSArray class]]) {
//获取数据成功
}else{
//返回数据异常
}
}else{
//返回数据异常
}
}];
获取SD卡timeLineSecion(支持SD卡回放的设备可以获取本地回放数据)
Objective-C
/// 通过sd卡获取timelineSection
/// @param deviceId 设备id
/// @param channelId 多目摄像机需传入channelId 不传默认主通道
/// @param startTime 过滤开始时间,单位毫秒 13位时间戳 Y
/// @param endTime 过滤结束时间 ,单位毫秒 13位时间戳 Y
/// @param completion 回调 Y response<NSArray<QLYTimeLineSection>>
- (void)getSdcardTimelineSectionList:(nonnull NSString *)deviceId
channelId:(nullable NSString *)channelId
startTime:(nonnull NSNumber *)startTime
endTime:(nonnull NSNumber *)endTime
completion:(QLYInterFaceCompletionHandler)completion;
///示例代码
NSDate *startTime = [[NSDate date] dateByAddingTimeInterval:-1 * (1 * 3600 * 24)];
NSDate *endTime = [NSDate date];
NSMutableArray * tempArr = [NSMutableArray arrayWithCapacity:0];
[[QLYSDKManager sharedInstance] getSdcardTimelineSectionList:self.cameraInfo.deviceId channelId:@"" startTime:@([startTime timeIntervalSince1970] * 1000) endTime:@([endTime timeIntervalSince1970] * 1000) completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
if (isSucceeded) {
NSMutableArray * tempArr = [NSMutableArray arrayWithCapacity:0];
if ([response isKindOfClass:[NSArray class]]) {
//获取数据成功
}else{
//返回数据异常
}
}else{
//返回数据异常
}
}];
指定时间点开始播放(本地、云存储)
Objective-C
/// 回放到指定时间
/// @param timeInterval 时间戳 单位ms
- (void)seek:(NSTimeInterval)timeInterval;
///示例代码
[self.player seek:seekInterval * 1000];
指定时间段开始播放(本地、云存储)
Objective-C
/// 回放到指定时间段
/// @param startTimeInterval 开始时间 单位ms
/// @param endTimeInterval 结束时间 单位ms
- (void)seek:(NSTimeInterval)startTimeInterval endTime:(NSTimeInterval)endTimeInterval;
///示例代码
[self.player seek:[startTime timeIntervalSince1970] * 1000 endTime:[endTime timeIntervalSince1970] * 1000];
实时预览
JSON/// 获取缩略图(主线程调用)
/// @param deviceId deviceid
/// @param section QLYTimeLineSection
/// @param timeStamp Section中指定时间戳
/// @param size CGSizeMake(width,height)
/// @param completion 回调
- (void)getThumbnail:(nonnull NSString *)deviceId
section:(nonnull QLYTimeLineSection *)section
timeStamp:(nonnull NSString *)timeStamp
size:(CGSize)size
completion:(QLYPlayerThumbnailHandler)completion;
/// 示例代码
[self.player getThumbnail:self.cameraInfo.deviceId section:section timeStamp:[NSString stringWithFormat:@"%lu",(unsigned long)[startTimeDate timeIntervalSince1970] * 1000] size:CGSizeMake(1334, 750) completion:^(BOOL isSucceeded, UIImage * _Nullable image, NSString * _Nullable imgUrl, NSError * _Nullable error) {
if (isSucceeded) {
/// 获取缩略图成功
}else{
///获取缩略图失败
}
}];
根据类型回放
Objective-C
/// 根据类型回放某段时间
/// @param timeInterval 时间戳 单位ms
/// @param dataType 云存储or SD卡
- (void)seek:(NSTimeInterval)timeInterval timelineDataType:(QLYTimeLineDataType)dataType;
typedef NS_ENUM(NSInteger, QLYTimeLineDataType) {
QLYTimeLineDataTypeCloud = 0, //云存储
QLYTimeLineDataTypeSDCard //sd卡
};
///示例代码
[self.player seek:[startTime timeIntervalSince1970] * 1000 timelineDataType:QLYTimeLineDataTypeSDCard];
4、告警视频播放
获取告警列表
Objective-C
/// 获取告警事件列表
/// @param deviceId 设备id Y
/// @param channelId 多目摄像机需传入channelId 不传默认主通道
/// @param startTime 过滤开始时间,单位毫秒 13位时间戳 N
/// @param endTime 过滤结束时间 ,单位毫秒 13位时间戳 N
/// @param isPage 是否分页 (YES 只会返回一页数据 最大100条 要进行分页操作使用最后一条数据的开始时间作为下次分页的endTime;NO 全返回)
/// @param cancelTask 是否取消请求 (只支持isPage为NO 不分页场景)
/// @param shareId 分享设备传入
/// @param generate 是否生成缩略图 默认生成 generate 1 不生成缩略图 0 生成缩略图
/// @param completion 回调 Y response<NSArray<QLYTimeLineEvent>>
- (void)getEventList:(nonnull NSString *)deviceId
channelId:(nullable NSString *)channelId
startTime:(nullable NSNumber *)startTime
endTime:(nullable NSNumber *)endTime
isPage:(BOOL)isPage
cancelTask:(BOOL)cancelTask
shareId:(nullable NSString *)shareId
generate:(nullable NSNumber *)generate
completion:(QLYInterFaceCompletionHandler)completion;
/// 示例代码
[[QLYSDKManager sharedInstance] getEventList:self.cameraInfo.deviceId channelId:@"" startTime:startTime ? startTime : @(startTimeInterval) endTime:endTime? endTime :@(endTimeInterval) isPage:NO cancelTask:YES shareId:nil generate:@(1) completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
__typeof(weakSelf) strongSelf = weakSelf;
if (isSucceeded) {
if ([response isKindOfClass:[NSArray class]]) {
//获取数据成功
}else{
//获取数据异常
}else{
//获取数据异常
}
}];
告警播放器(初始化与释放与直播类似,详见demo)
Objective-C
QLYPlayerConfig *playerConfig = [[QLYPlayerConfig alloc]init];
playerConfig.playType = QLYPlayerTypeNormal;
QLYPlayer *player = [[QLYPlayer alloc] initWithDevice:cameaInfo.deviceId channelId:@"" config:playerConfig];
player.delegate = self;
///告警播放配置
[_player setEventInfo:_event];
[_player prepare];
[_player start];
5、其他功能
获取设备能力集
Objective-C
/// 获取设备能力集
/// @param deviceId 设备mac
/// @param completion 回调 response<QLYCameraAbility>
- (void)getCameraAbilityOfPlatformOpen:(nonnull NSString *)deviceId
completion:(QLYInterFaceCompletionHandler)completion;
///示例代码
[[QLYCameraManager sharedInstance] getCameraAbilityOfPlatformOpen:deviceId completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
if (isSucceeded) {
dispatch_async(dispatch_get_main_queue(), ^{
QLYCameraAbility * ability = response;
//获取能力集成功
});
}else{
//获取能力集失败
}
}];
云台控制
Objective-C
/// 设置PTZ接口(主线程执行)
/// @param deviceId 设备ID
/// @param channelId 多目摄像机需传入channelId 不传默认主通道
/// @param ptzType 设置PTZ类型,@see QLYPTZType
/// @param direction
/// 如果 PTZType == QLYPTZTypeTurnOnce || QLYPTZTypeTurnContinuos 需要指定此参数,上下左右
/// 如果 PTZType == QLYPTZTypeStopTurn || QLYPTZTypeResetPosition 需要指定 QLYPTZDirectReset
/// 如果 PTZType == QLYPTZTypeSetPosition 需要指定 QLYPTZDirectUnKnow
/// @param location pan 水平 tilt 上下 (融合和南向设备,需要direction=QLYPTZDirectAbsolutePositionSetting,且取值范围:-1000000 ~ 1000000)
/// 如果(PTZType == QLYPTZTypeSetPosition)时,需要指定此参数,其它传nil。参数类型如@{@"pan": @(0), @"tilt" :@(-10203)}
/// @param completion 回调 response<NSDictiory> 成功 000000 data@{}
- (void)setPTZPosition:(nonnull NSString *)deviceId
channelId:(nullable NSString *)channelId
ptzType:(QLYPTZType)ptzType
direction:(QLYPTZDirect)direction
location:(nullable NSDictionary *)location
completion:(QLYInterFaceCompletionHandler)completion;
///设置PTZ类型枚举
typedef NS_ENUM(NSInteger, QLYPTZType) {
QLYPTZTypeUnKnow = -1,
QLYPTZTypeTurnOnce = 0, //设置 一次PTZ,需要direction,上下左右
QLYPTZTypeTurnContinuos = 1, //设置 持续PTZ,需要direction,上下左右
QLYPTZTypeStopTurn = 2, //设置 停止持续PTZ direction = QLYPTZDirectReset
QLYPTZTypeResetPosition = 3, //设置 重置PTZ direction = QLYPTZDirectReset
QLYPTZTypeSetPosition = 4 //设置 指定PTZ,需要location
};
///指定PTZ(摄像头方向、焦距、光圈设置)命令
typedef NS_ENUM(NSInteger, QLYPTZDirect) {
QLYPTZDirectUnKnow = -1,
QLYPTZDirectReset = 0, //重置ptz\停止摇头
QLYPTZDirectLeft = 1, //QLYPTZDirectLeft: 左
QLYPTZDirectRight = 2, //QLYPTZDirectRight: 右
QLYPTZDirectUp = 3, //QLYPTZDirectUp: 上
QLYPTZDirectDown = 4, //QLYPTZDirectDown: 下
};
///示例代码(云台重置,其他设置详见demo)
[[QLYSDKManager sharedInstance] setPTZPosition:deviceUUID channelId:@"" ptzType:QLYPTZTypeResetPosition direction:QLYPTZDirectReset location:nil completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
if (isSucceeded) {
//云台重置成功
}else{
//云台重置失败
}
}];
获取wifi列表
Objective-C
/// 获取Wifi列表(一起返回)
/// @param deviceId 设备Id
/// @param completion 回调 NSArray<QLYDeviceWifiInfo>
- (void)getWiFiList:(nonnull NSString *)deviceId
completion:(QLYInterFaceCompletionHandler)completion;
/// 示例代码
[[QLYSDKManager sharedInstance] getWiFiList:_deviceModel.deviceId completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
if (isSucceeded) {
if ([response isKindOfClass:NSArray.class]) {
//获取列表成功
} else {
//获取列表失败
}
} else {
//获取列表失败
}
}];
切换wifi
JSON/// 切换Wifi
/// @param deviceId 设备Id
/// @param wifiInfo 设置的info对象
/// @param completion 回调
- (void)changeDeviceWiFi:(nonnull NSString *)deviceId
wifiInfo:(nonnull QLYDeviceWifiInfo *)wifiInfo
completion:(QLYInterFaceCompletionHandler)completion;
/// 示例代码
[[QLYSDKManager sharedInstance] changeDeviceWiFi:_deviceModel.deviceId wifiInfo:info completion:^(BOOL isSucceeded, id _Nullable response, NSError * _Nullable error) {
if (isSucceeded) {
//切换命令下发成功
} else {
//切换命令下发失败
}
}];
释放OPENSDK
Objective-C
/// 释放SDK
- (void)unInit;
[[QLYSDKManager sharedInstance] unInit];
6、异常情况处理
当需要退回前后台情况 (具体可参考demo)
- 当退回后台场景语⾳通话处于⼯作状态,需要先关闭通话功能
Objective-C
/*
监听前后台
*/
//注册程序进⼊前台通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector (updateForAppEnterForeground) name:
UIApplicationWillEnterForegroundNotification object:nil];
//注册程序进⼊后台通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector (updateForAppEnterBackground) name:
UIApplicationDidEnterBackgroundNotification object:nil];
//进⼊后台操作
[self.player pause];
//进⼊前台操作
//恢复直播
[self.player resume];
//回放指定当前时间(单位ms)
[self.player seek:_currentPlayTime * 1000];