更新时间:2023-06-05 02:49:24下载pdf
涂鸦智能为智能摄像机(IPC)提供云存储的服务,用户可以将 IPC 设备录制的视频上传到云端存储起来。
判断设备是否支持云存储能力,支持则继续。
判断设备是否开通云存储服务,根据服务状态继续判断:
如果云存储服务未开通或者已经过期,并且云视频已经被全部删除,就需要先购买云存储服务。云存储服务过期后,已经上传的云视频还会保留一段时间,通常是 7 天。
如果云存储服务在有效期内,先查询有云视频的日期,然后查询指定日期的相关数据,包括云存储事件、时间轴数据、鉴权信息等。之后,用户就可以选择一个云存储事件或者一个时间点开始播放云视频了。
ThingSmartCloudManager
提供了云存储 API 集合,包括判断设备是否支持云存储能力。
接口说明
+ (BOOL)isSupportCloudStorage:(NSString *)devId;
参数说明
参数 | 说明 |
---|---|
devId | 设备 ID |
云存储服务开通需要调用open api接口
参数说明
参数 | 说明 |
---|---|
devId | 设备 ID |
购买过云存储服务后,智能摄像机会把录制的视频上传云端。用户可以通过 SDK 播放已经上传的云视频。云存储相关功能通过 ThingSmartCameraKit
中的 ThingSmartCloudManager
类操作。
类和协议
类名(协议名) | 说明 |
---|---|
ThingSmartCloudManager | 云存储服务状态,视频数据维护和云视频播放 |
ThingSmartCloudManagerDelegate | 云视频播放,视频帧数据回调代理 |
接口说明
初始化 ThingSmartCloudManager
时,需要传入设备 ID。
云视频默认是静音开始播放的,如果您需要在播放时开启声音,可在初始化时,设置静音状态 为 NO
。云视频播放时,视频帧数据和帧头信息都将通过代理方法回调。
- (instancetype)initWithDeviceId:(NSString *)devId;
开启图片加密,设置为 YES
,云存储事件中携带的图片将加密。此时,您需要使用 ThingEncryptImage
组件显示图片。
接口说明
@property (nonatomic, assign) BOOL enableEncryptedImage;
云存储代理接口为 ThingSmartCloudManagerDelegate
,只有一个代理方法,会返回每一帧视频的 YUV 数据和帧信息。如果您想要自行渲染视频,可以将 ThingSmartCloudManager
的 autoRender
属性设置为 NO
(默认为YES
),并在代理方法中查询视频帧的 YUV 数据加以渲染。
接口说明
- (void)cloudManager:(ThingSmartCloudManager *)cloudManager didReceivedFrame:(CMSampleBufferRef)frameBuffer videoFrameInfo:(ThingSmartVideoFrameInfo)frameInfo;
参数说明
参数 | 说明 |
---|---|
cloudManager | 播放云视频的 ThingSmartCloudManager 对象 |
frameBuffer | 视频帧 YUV 数据 |
frameInfo | 视频帧信息 |
在使用云视频播放功能前,还需要先加载云存储的相关数据。云存储数据接口会返回云存储服务当前的状态,以及加载对应的加密秘钥,鉴权信息等。
接口说明
- (void)loadCloudData:(void(^)(ThingSmartCloudState state))complete
参数说明
参数 | 说明 |
---|---|
complete | 加载完成回调,返回当前的云存储服务状态 |
ThingSmartCloudState
枚举
枚举值 | 说明 |
---|---|
ThingSmartCloudStateNoService | 用户未开通云存储服务 |
ThingSmartCloudStateNoData | 用户已开通云存储服务,但是没有回放视频 |
ThingSmartCloudStateValidData | 用户已开通云存储服务,且有回放视频 |
ThingSmartCloudStateExpiredNoData | 用户的云存储服务已过期,且无回放视频 |
ThingSmartCloudStateExpiredData | 用户的云存储服务已过期,但是还有可以查看的回放视频 |
ThingSmartCloudStateLoadFailed | 云存储服务状态加载失败 |
云存储服务过期后,用户已上传的云视频还会预留一段时间,通常是 7 天,具体时长需要参考云存储服务协议。如果在预留期间内没有续费,服务到期后,用户的云视频将会被删除。
在加载云存储数据成功返回后,如果云端有云视频回放数据,可以通过 cloudDays
属性查询有视频回放数据的日期。
接口说明
@property (nonatomic, strong, readonly) NSArray<ThingSmartCloudDayModel *> *cloudDays;
ThingSmartCloudDayModel
模型
字段 | 类型 | 说明 |
---|---|---|
sumDuration | NSInteger | 当天云视频总长度 |
uploadDay | NSString | 日期,格式为 yyyy-MM-dd |
startTime | NSInteger | 当天 00:00:00 的 Unix 时间戳 |
endTime | NSInteger | 当天 23:59:59 的 Unix 时间戳 |
在用户播放云视频前,您需要查询当天的云存储视频片段时间数据。
接口说明
- (void)timeLineWithCloudDay:(ThingSmartCloudDayModel *)cloudDay
success:(void(^)(NSArray<ThingSmartCloudTimePieceModel *> * timePieces))success
failure:(void(^)(NSError * error))failure;
参数说明
参数 | 说明 |
---|---|
cloudDay | 云视频录制日期模型 |
success | 成功回调,返回当天所有视频片段时间数据模型的数组 |
failure | 失败回调,error 表示错误信息 |
ThingSmartCloudTimePieceModel 数据模型
字段 | 类型 | 说明 |
---|---|---|
startTime | NSInteger | 视频开始时间 Unix 时间戳 |
startDate | NSDate | 视频开始时间 |
endTime | NSInteger | 视频结束时间 Unix 时间戳 |
endDate | NSDate | 视频结束时间 |
开启云存储服务后,设备通过侦测报警上报的事件,云存储事件会和云视频关联起来。正常情况下,每一个云存储事件都会有一段对应的云视频。
云存储的 报警事件 和 侦测报警消息 略有不同。两者的触发原因可能是一样的,但是侦测报警消息的删除不会影响到云存储事件。注意,并非所有的侦测报警消息都会触发云视频录制,比如电量警告等。
接口说明
- (void)timeEventsWithCloudDay:(ThingSmartCloudDayModel *)cloudDay
offset:(int)offset
limit:(int)limit
success:(void(^)(NSArray<ThingSmartCloudTimeEventModel *> * timeEvents))success
failure:(void(^)(NSError * error))failure;
参数说明
参数 | 说明 |
---|---|
cloudDay | 云视频录像日期模型 |
offset | 偏移量,0 标示从第一个事件开始 |
limit | 数量限制,-1 标示查询所有事件 |
success | 成功回调,返回事件模型的数组 |
failure | 失败回调,error 表示错误信息 |
ThingSmartCloudTimeEventModel
数据模型
字段 | 类型 | 说明 |
---|---|---|
describe | NSString | 事件描述 |
startTime | NSInteger | 事件开始时间 Unix 时间戳 |
endTime | NSInteger | 事件结束时间 Unix 时间戳 |
snapshotUrl | NSString | 事件发生时,设备抓拍的实时图片 |
云存储事件中携带的实时截图是经过加密的,您需要通过加密图片组件 ThingEncryptImage
展示,详情请参考 加密图片。
播放云视频时,您需要指定开始播放的时间,结束时间,和是否是播放云存储事件。您还可以设置声音开关、本地视频录制、截图等。
ThingSmartCloudTimePieceModel
):
ThingSmartCloudTimePieceModel
中 startTime
和 endTime
之间的一个时间戳。isEvent
传入 NO
。ThingSmartCloudTimeEventModel
):
ThingSmartCloudTimeEventModel
的 startTime
。isEvent
传入 YES
。ThingSmartCloudDayModel
的 endTime
。接口说明
- (void)playCloudVideoWithStartTime:(long)startTime
endTime:(long)endTime
isEvent:(BOOL)isEvent
onResponse:(void(^)(int errCode))responseCallback
onFinished:(void(^)(int errCode))finishedCallback;
参数说明
参数 | 说明 |
---|---|
startTime | 开始播放的时间 |
endTime | 结束时间,会自动连续播放到当天所有视频结束 |
isEvent | 是否播放的是云存储事件 |
responseCallback | 结果回调,errCode 标示错误码,0 表示成功开始播放 |
finishedCallback | 播放结束回调,errCode 标示结束原因,0 表示视频正常播放结束 |
接口说明
- (int)pausePlayCloudVideo;
返回值
类型 | 说明 |
---|---|
int | 错误码,0 表示成功 |
接口说明
- (int)resumePlayCloudVideo;
返回值
类型 | 说明 |
---|---|
int | 错误码,0 表示成功 |
接口说明
- (int)stopPlayCloudVideo;
返回值
类型 | 说明 |
---|---|
int | 错误码,0 表示成功 |
在开始播放调用成功后,可以设置倍数播放。音频不支持倍数播放。
接口说明
- (int)setCloudVideoPlaySpeed:(ThingSmartCameraPlayBackSpeed)speed;
参数说明
参数 | 说明 |
---|---|
speed | 播放倍数,支持 1、2、4 倍数,枚举值 ThingSmartCameraPlayBackSpeed |
示例代码
int result = [self.cloudManager setCloudVideoPlaySpeed:ThingSmartCameraPlayBackSpeed_10TIMES];
Objective C:
- (void)viewDidLoad {
[_cloudManager downloadCloudVideoWithRange:NSMakeRange(startTime, length) filePath:videoPath success:^(NSString *filePath) {
} progress:^(NSUInteger progress) {
} failure:^(NSError *error) {
}];
}
Swift:
func viewDidLoad() {
cloudManager.downloadCloudVideo(with: NSRange(location: startTime, length: length), filePath: videoPath, success: { (filePath) in }, progress: { (progress) in }, failure: { (error) in }
}
接口说明
- (void)downloadCloudVideoWithRange:(NSRange)timeRange
filePath:(NSString *)videoPath
success:(DownloadSuccess)success
progress:(DownloadProgress)progress
failure:(DownloadFailure)failure;
参数说明
参数 | 说明 |
---|---|
timeRange | 待下载的视频的时间范围:
|
videoPath | 保存视频的文件路径,格式为 folderPath/fileName.mp4 |
success | 下载成功回调 |
progress | 下载进度回调,进度以 1 到 100 之间的整数表示 |
failure | 下载失败回调 |
接口说明
- (void)pauseDownloadCloudVideo;
接口说明
- (void)resumeDownloadCloudVideo:(DownloadFailure)failure;
参数说明
参数 | 说明 |
---|---|
failure | 恢复下载失败回调 |
接口说明
- (void)cancelDownloadCloudVideo;
接口说明
- (void)deleteCloudVideoWithRange:(NSRange)timeRange success:(void(^)(void))success failure:(void(^)(NSError *error))failure;
参数说明
参数 | 说明 |
---|---|
timeRange | 待删除的视频的时间范围:
|
success | 成功的回调 |
failure | 失败的回调 |
示例代码
Objective C:
- (void)viewDidLoad {
[_cloudManager deleteCloudVideoWithRange:NSMakeRange(startTime, length) success:^{
} failure:^(NSError *error) {
}];
}
Swift:
func viewDidLoad() {
cloudManager.deleteCloudVideo(with: NSRange(location: startTime, length: length), success: {
}, failure: { error in
})
}
接口说明
- (void)deleteAllDayCloudVideoWithRange:(NSRange)timeRange success:(void(^)(void))success failure:(void(^)(NSError *error))failure;
参数说明
参数 | 说明 |
---|---|
timeRange | 待删除的视频的全天时间范围:
|
success | 成功的回调 |
failure | 失败的回调 |
示例代码
Objective C:
- (void)viewDidLoad {
[_cloudManager deleteAllDayCloudVideoWithRange:NSMakeRange(startTime, length) success:^{
} failure:^(NSError *error) {
}];
}
Swift:
func viewDidLoad() {
cloudManager.deleteAllDayCloudVideo(with: NSRange(location: startTime, length: length), success: {
}, failure: { error in
})
}
ThingSmartCloudManager
会自动渲染云视频,通过 videoView
方法查询云视频渲染视图,并添加到屏幕上。
接口说明
- (UIView<ThingSmartVideoViewType> *)videoView;
返回值
类型 | 说明 |
---|---|
UIView |
云视频渲染视图 |
接口说明
- (void)enableMute:(BOOL)mute success:(void(^)(void))success failure:(void (^)(NSError * error))failure;
参数说明
参数 | 说明 |
---|---|
mute | 是否静音 |
success | 成功回调 |
failure | 失败回调,error 表示错误信息 |
接口说明
- (BOOL)isMuted;
返回值
类型 | 说明 |
---|---|
BOOL | 是否是静音 |
接口说明
- (void)startRecord;
接口说明
- (void)startRecordAtPath:(NSString *)filePath;
参数说明
参数 | 说明 |
---|---|
filePath | 视频录像文件保存的路径 |
接口说明
- (void)startRecordWithRotateDirection:(ThingSmartVideoRotateDirection)direction filePath:(NSString *)filePath;
参数说明
参数 | 说明 |
---|---|
direction | 录制旋转方向 |
filePath | 视频录像文件保存的路径 |
接口说明
- (int)stopRecord;
返回值
类型 | 说明 |
---|---|
int | 错误码,0 表示视频保存成功 |
接口说明
- (UIImage *)snapShoot;
返回值
类型 | 说明 |
---|---|
UIImage | 截图的 UIImage 对象,失败时返回 nil |
接口说明
- (UIImage *)snapShootAtPath:(NSString *)filePath thumbnilPath:(NSString *)thumbnilPath;
参数说明
参数 | 说明 |
---|---|
filePath | 保存截图的文件路径 |
thumbnilPath | 缩略图保存路径,如果不需要缩略图,请设置为 nil |
如果您只需要查询当前截图的 UIImage
对象,则不需要自动保存。此时可以通过 videoView
的 - (UIImage *)screenshot;
方法查询截图。
Objective C:
// self.devId = @"xxxxx";
- (void)viewDidLoad {
if (![ThingSmartCloudManager isSupportCloudStorage:self.devId]) {
//不支持云存储
return;
}
_cloudManager = [[ThingSmartCloudManager alloc] initWithDeviceId:self.devId];
[_cloudManager enableMute:NO success:nil failure:nil];
_cloudManager.delegate = self;
}
- (void)loadData {
__weak typeof(self) weakSelf = self;
[self.cloudManager loadCloudData:^(ThingSmartCloudState state) {
weak_self.cloudStorageDays = weak_self.cloudManager.cloudDays;
weak_self.selectedDay = weak_self.cloudManager.cloudDays.lastObject;
[weakSelf checkCloudState:state];
}];
}
- (void)requestTimelineData {
[self.cloudManager timeLineWithCloudDay:self.selectedDay success:^(NSArray<ThingSmartCloudTimePieceModel *> *timePieces) {
// success
} failure:^(NSError *error) {
// failed
}];
}
-(void)playVideo:(ThingSmartCloudTimePieceModel *)timePiece {
[self.cloudManager playCloudVideoWithStartTime:timePiece.startTime endTime:self.selectedDay.endTime isEvent:NO onResponse:^(int errCode) {
if (errCode == 0) {
// success
}else {
// failed
}
} onFinished:^(int errCode) {
// finished
if (errCode != 0) {
// some error
}
}];
}
- (void)playEvent:(ThingSmartCloudTimeEventModel *)event {
[self.cloudManager playCloudVideoWithStartTime:event.startTime endTime:self.selectedDay.endTime isEvent:YES onResponse:^(int errCode) {
if (errCode == 0) {
// success
}else {
// failed
}
} onFinished:^(int errCode) {
// finished
if (errCode != 0) {
// some error
}
}];
}
- (void)pause {
if ([self.cloudManager pausePlayCloudVideo] != 0) {
// 暂停失败
}
}
- (void)resume {
if ([self.cloudManager resumePlayCloudVideo] != 0) {
// 恢复播放失败
}
}
- (void)stop {
[self.cloudManager stopPlayCloudVideo];
}
- (void)muteAction {
BOOL isMuted = [self.cloudManger isMuted];
[self.cloudManager enableMute:!isMuted success:^{
// success
} failure:^(NSError *error) {
// failed
}];
}
- (void)recordAction {
if (self.isRecording) {
if ([self.cloudManager stopRecord] != 0) {
// 录制失败
}else {
// 录制成功,视频已保存到系统相册
}
self.isRecording = NO;
}else {
[self.cloudManager startRecord];
self.isRecording = YES;
}
}
- (void)snapShoot {
if ([self.cloudManager snapShoot]) {
// 图片已保存到系统相册
}else {
// 截图失败
}
}
Swift:
func viewDidLoad() {
if (!ThingSmartCloudManager.isSupportCloudStorage(devId: self.devId)) {
//不支持云存储
return;
}
let cloudManager = ThingSmartCloudManager(deviceId: self.devId)
cloudManager?.enableMute(false, success: nil, failure: nil)
cloudManager?.delegate = self
}
func loadData() {
self.cloudManager.loadCloudData { [weak self] (state) in
self.cloudStorageDays = self.cloudManager.cloudDays
self.selectedDay = self.cloudManager.cloudDays.last
self.checkCloudState(state)
}
}
func requestTimelineData() {
self.cloudManager.timeLine(withCloudDay: self.selectedDay, success: { (timePieces) in
//success
}) { (error) in
//failed
}
}
func playVideo(_ timePiece: ThingSmartCloudTimePieceModel) {
self.cloudManager.playCloudVideo(withStartTime: timePiece.startTime, endTime:self.selectedDay.endTime , isEvent: false, onResponse: { (code) in
if code == 0 {
//success
} else {
//failed
}
}) { (errCode) in
//finished
if codeCode != 0 {
//some error
}
}
}
func playEvent(_ event: ThingSmartCloudTimeEventModel) {
cloudManager.playCloudVideo(withStartTime: event.startTime, endTime: self.selectedDay.endTime, isEvent: true, onResponse: { (errCode) in
if code == 0 {
//success
} else {
//failed
}
}) { (errCode) in
//finished
if errCode != 0 {
// some error
}
}
}
func pause() {
if self.cloudManager.pausePlayCloudVideo() != 0 {
//暂停失败
}
}
func resume() {
if self.cloudManager.resumePlayCloudVideo() != 0 {
// 恢复播放失败
}
}
func stop() {
self.cloudManager.stopPlayCloudVideo()
}
func muteAction() {
let isMuted = self.cloudManager.isMuted()
self.cloudManager.enableMute(!isMuted, success: {
// success
}) { (error) in
// failed
}
}
func recordAction() {
if self.isRecording {
if self.cloudManager.stopRecord() != 0 {
//录制失败
} else {
//录制成功,视频已保存系统相册
}
self.isRecording = false
} else {
self.cloudManager.startRecord()
self.isRecording = true
}
}
func snapShoot() {
if self.cloudManager.snapShoot() {
// 图片已保存到系统相册
} else {
// 截图失败
}
}
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈