云存储

更新时间:2023-05-08 08:52:21下载pdf

涂鸦智能为智能摄像机(IPC)提供云存储的服务,用户可以将 IPC 设备录制的视频上传到云端存储起来。

云存储流程

  • 如果云存储服务未开通或者已经过期,并且云视频已经被全部删除,就需要先购买云存储服务。云存储服务过期后,已经上传的云视频还会保留一段时间,通常是 7 天。

  • 如果云存储服务在有效期,先查询有云视频的日期,然后查询指定日期的相关数据,包括云存储事件,时间轴数据,鉴权信息等。之后,用户就可以选择一个云存储事件或者一个时间点开始播放云视频了。

    云存储

开通云存储

云存储服务开通需要使用 云存储服务业务包,该组件提供了云存储开通的 H5 页面和订单展示功能。

云视频

购买过云存储服务后,智能摄像机会把录制的视频上传云端。用户可以通过 SDK 播放已经上传的云视频。云存储相关功能通过 TuyaSmartCameraKit 中的 TuyaSmartCloudManager 类操作。

类和协议

类名(协议名) 说明
TuyaSmartCloudManager 云存储服务状态,视频数据维护和云视频播放
TuyaSmartCloudManagerDelegate 云视频播放,视频帧数据回调代理

初始化云存储服务

接口说明

初始化 TuyaSmartCloudManager 时,需要传入设备 ID。

云视频默认是静音开始播放的,如果您需要在播放时开启声音,可在初始化时,设置静音状态为 NO。云视频播放时,视频帧数据和帧头信息都将通过代理方法回调。

- (instancetype)initWithDeviceId:(NSString *)devId;

参数说明

参数 说明
devId 设备 ID

开启云存储事件图片加密

开启图片加密,设置为 YES,云存储事件中携带的图片将加密。此时,您需要使用 TYEncryptImage 组件显示图片。

接口说明

@property (nonatomic, assign) BOOL enableEncryptedImage;

云视频数据代理回调

云存储代理接口为 TuyaSmartCloudManagerDelegate,只有一个代理方法,会返回每一帧视频的 YUV 数据和帧信息。如果您想要自行渲染视频,可以将 TuyaSmartCloudManagerautoRender 属性设置为 NO(默认为YES),并在代理方法中查询视频帧的 YUV 数据加以渲染。

接口说明

- (void)cloudManager:(TuyaSmartCloudManager *)cloudManager didReceivedFrame:(CMSampleBufferRef)frameBuffer videoFrameInfo:(TuyaSmartVideoFrameInfo)frameInfo;

参数说明

参数 说明
cloudManager 播放云视频的 TuyaSmartCloudManager 对象
frameBuffer 视频帧 YUV 数据
frameInfo 视频帧信息

加载云存储数据

在使用云存储播放功能前,还需要先加载云存储的相关数据。云存储数据接口会返回云存储服务当前的状态,以及加载对应的加密秘钥,鉴权信息等。

接口说明

- (void)loadCloudData:(void(^)(TuyaSmartCloudState state))complete

参数说明

参数 说明
complete 加载完成回调,返回当前的云存储服务状态

TuyaSmartCloudState 枚举

枚举值 说明
TuyaSmartCloudStateNoService 用户未开通云存储服务
TuyaSmartCloudStateNoData 用户已开通云存储服务,但是没有回放视频
TuyaSmartCloudStateValidData 用户已开通云存储服务,且有回放视频
TuyaSmartCloudStateExpiredNoData 用户的云存储服务已过期,且无回放视频
TuyaSmartCloudStateExpiredData 用户的云存储服务已过期,但是还有可以查看的回放视频
TuyaSmartCloudStateLoadFailed 云存储服务状态加载失败

云存储服务过期后,用户已上传的云视频还会预留一段时间,通常是 7 天,具体时长需要参考云存储服务协议。如果在预留期间内没有续费,服务到期后,用户的云视频将会被删除。

查询云视频录制日期

在加载云存储数据成功返回后,如果云端有云视频回放数据,可以通过 cloudDays 属性查询有视频回放数据的日期。

接口说明

@property (nonatomic, strong, readonly) NSArray<TuyaSmartCloudDayModel *> *cloudDays;

TuyaSmartCloudDayModel 模型

字段 类型 说明
sumDuration NSInteger 当天云视频总长度
uploadDay NSString 日期,格式为 yyyy-MM-dd
startTime NSInteger 当天 00:00:00 的 Unix 时间戳
endTime NSInteger 当天 23:59:59 的 Unix 时间戳

查询云视频片段列表

在用户播放云视频前,您需要查询当天的视频片段时间数据。

接口说明

- (void)timeLineWithCloudDay:(TuyaSmartCloudDayModel *)cloudDay
                     success:(void(^)(NSArray<TuyaSmartCloudTimePieceModel *> * timePieces))success
                     failure:(void(^)(NSError * error))failure;

参数说明

参数 说明
cloudDay 云视频录制日期模型
success 成功回调,返回当天所有视频片段时间数据模型的数组
failure 失败回调,error 表示错误信息

TuyaSmartCloudTimePieceModel 数据模型

字段 类型 说明
startTime NSInteger 视频开始时间 Unix 时间戳
startDate NSDate 视频开始时间
endTime NSInteger 视频结束时间 Unix 时间戳
endDate NSDate 视频结束时间

查询云存储事件

开启云存储服务后,设备通过侦测报警上报的事件,云存储事件会和云视频关联起来。正常情况下,每一个云存储事件都会有一段对应的云视频。

云存储的 报警事件侦测报警消息 略有不同。两者的触发原因可能是一样的,但是侦测报警消息的删除不会影响到云存储事件。注意,并非所有的侦测报警消息都会触发云视频录制,比如电量警告等。

接口说明

- (void)timeEventsWithCloudDay:(TuyaSmartCloudDayModel *)cloudDay
                        offset:(int)offset
                         limit:(int)limit
                       success:(void(^)(NSArray<TuyaSmartCloudTimeEventModel *> * timeEvents))success
                       failure:(void(^)(NSError * error))failure;

参数说明

参数 说明
cloudDay 云视频录像日期模型
offset 偏移量,0 标示从第一个事件开始
limit 数量限制,-1 标示查询所有事件
success 成功回调,返回事件模型的数组
failure 失败回调,error 表示错误信息

TuyaSmartCloudTimeEventModel 数据模型

字段 类型 说明
describe NSString 事件描述
startTime NSInteger 事件开始时间 Unix 时间戳
endTime NSInteger 事件结束时间 Unix 时间戳
snapshotUrl NSString 事件发生时,设备抓拍的实时图片

云存储事件中携带的实时截图是经过加密的,您需要通过加密图片组件 TYEncryptImage 展示,详情请参考 加密图片

云视频播放

播放云视频时,您需要指定开始播放的时间,结束时间,和是否是播放云存储事件。您还可以设置声音开关、本地视频录制、截图等。

开始播放云视频

  • 如果需要直接播放某个视频片段 (TuyaSmartCloudTimePieceModel):
    • 开始时间传入介于 TuyaSmartCloudTimePieceModelstartTimeendTime 之间的一个时间戳。
    • isEvent 传入 NO
  • 如果需要播放某个云存储事件(TuyaSmartCloudTimeEventModel):
    • 开始时间传入 TuyaSmartCloudTimeEventModelstartTime
    • isEvent 传入 YES
    • 结束时间传入当天的结束时间,也就是 TuyaSmartCloudDayModelendTime

接口说明

- (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 表示成功

下载云存储视频

接口说明

- (void)downloadCloudVideoWithRange:(NSRange)timeRange
                           filePath:(NSString *)videoPath
                            success:(DownloadSuccess)success
                           progress:(DownloadProgress)progress
                            failure:(DownloadFailure)failure;

参数说明

参数 说明
timeRange 待下载的视频的时间范围。
  • 开始时间为 10 位时间戳
  • 长度单位为秒
videoPath 保存视频的文件路径,格式为 folderPath/fileName.mp4
success 下载成功回调
progress 下载进度回调,进度以 1 到 100 之间的整数表示
failure 下载失败回调

示例代码

ObjC

- (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)pauseDownloadCloudVideo;

恢复云存储视频下载

接口说明

- (void)resumeDownloadCloudVideo:(DownloadFailure)failure;

参数说明

参数 说明
failure 恢复下载失败回调

取消云存储视频下载

接口说明

- (void)cancelDownloadCloudVideo;

删除云存储视频

接口说明

- (void)deleteCloudVideoWithRange:(NSRange)timeRange success:(void(^)(void))success failure:(void(^)(NSError *error))failure;

参数说明

参数 说明
timeRange 待删除的视频的时间范围。
  • 开始时间为 10 位时间戳
  • 长度单位为秒
success 成功的回调
failure 失败的回调

示例代码

ObjC

- (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 待删除的视频的全天时间范围。
  • 当天的开始时间用 10 位时间戳表示
  • 长度单位为秒
success 成功的回调
failure 失败的回调

示例代码

ObjC

- (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

    })
}

查询云视频渲染视图

TuyaSmartCloudManager 会自动渲染云视频,通过 videoView 方法查询云视频渲染视图,并添加到屏幕上。

接口说明

- (UIView<TuyaSmartVideoViewType> *)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:(TuyaSmartVideoRotateDirection)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; 方法查询截图。

示例代码

ObjC

// self.devId = @"xxxxx";
- (void)viewDidLoad {
	_cloudManager = [[TuyaSmartCloudManager alloc] initWithDeviceId:self.devId];
    [_cloudManager enableMute:NO success:nil failure:nil];
	_cloudManager.delegate = self;
}

- (void)loadData {
	__weak typeof(self) weakSelf = self;
	[self.cloudManager loadCloudData:^(TuyaSmartCloudState 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<TuyaSmartCloudTimePieceModel *> *timePieces) {
		// success
    } failure:^(NSError *error) {
		// failed
    }];
}

-(void)playVideo:(TuyaSmartCloudTimePieceModel *)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:(TuyaSmartCloudTimeEventModel *)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() {
    let cloudManager = TuyaSmartCloudManager(deviceId: 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: TuyaSmartCloudTimePieceModel) {
    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: TuyaSmartCloudTimeEventModel) {
    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 {
        // 截图失败
    }
}