Cloud Storage

Last Updated on : 2024-07-26 05:57:56download

Tuya-enabled IP cameras (IPCs) support the cloud storage service that allows users to save video footage on the IPCs to the cloud.

Cloud storage process

  • Determine whether a device supports cloud storage. If so, proceed with the process.

  • Determine whether the cloud storage service is activated. Then, proceed with subsequent steps based on the service status.

    • If the cloud storage service is inactivated or has expired and all cloud-stored video files have been deleted, the cloud storage service must be purchased to enable the cloud storage service. After the cloud storage service expires, the existing cloud-stored video files will be retained for a period, seven days in most cases.

    • If the cloud storage service is within the validity period, get the date when the cloud-stored video files were created, and get the data of the specified date, including cloud storage events, timeline data, and authentication information. Then, a cloud storage event or a time point can be selected to start cloud-stored video playback.

    Cloud Storage

Support for cloud storage

ThingSmartCloudManager provides a collection of cloud storage APIs, including those used to check the support for cloud storage capabilities.

API description

+ (BOOL)isSupportCloudStorage:(NSString *)devId;

Parameters

Parameter Description
devId The device ID.

Get key information

API description

+ (void)fetchSecretKeyWithDevId:(NSString *)devId completion:(ThingFetchSecretKeyCompletion)completion;

Parameters

Parameter Description
devId The device ID.
completion The callback method.

Subscribe to cloud storage

To enable subscription to the cloud storage service, the Cloud Storage UI BizBundle must be integrated. This component provides the H5 pages and order display features for the subscription.

Parameters

Parameter Description
devId The device ID.

Configure cloud storage

After the subscription to the cloud storage service, users can upload video footage on an IPC to the cloud. Then, they can view and play back cloud-stored video footage based on the IPC SDK. Cloud storage is implemented with the class ThingSmartCameraKit in ThingSmartCloudManager.

Classes and protocols

Class name (protocol name) Description
ThingSmartCloudManager Cloud storage service status, video maintenance, and cloud-stored video playback
ThingSmartCloudManagerDelegate Cloud-stored video playback, callback delegate for video frames

Initialize cloud storage

API description

To initialize ThingSmartCloudManager, pass in the device ID.

Cloud-stored video footage is played back in mute mode by default. To enable the audio mode for playback, you can set the mute state to NO during initialization. The IPC delegate provides the callback to return information about video frames and headers during playback.

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

Enable encryption of cloud storage event images

You can set the image encryption state to YES, so the images in cloud storage events will be encrypted. In this case, the component ThingEncryptImage is used to display images.

API description

@property (nonatomic, assign) BOOL enableEncryptedImage;

Delegate callback for cloud-stored video data

The cloud storage delegate ThingSmartCloudManagerDelegate provides only one delegate method to return YUV data and frame data of each video frame. You can render video images with your own method. For this purpose, set the autoRender property of ThingSmartCloudManager to NO (default value: YES), and implement the delegate method to get YUV data of video frames. This way, the IPC SDK does not automatically render video images.

API description

- (void)cloudManager:(ThingSmartCloudManager *)cloudManager didReceivedFrame:(CMSampleBufferRef)frameBuffer videoFrameInfo:(ThingSmartVideoFrameInfo)frameInfo;

Parameters

Parameter Description
cloudManager The object ThingSmartCloudManager to play back cloud-stored video footage.
frameBuffer The YUV data of video frames.
frameInfo The information about video frames.

Load cloud storage data

Before cloud-stored video playback, cloud storage data must be loaded. The returned cloud storage data include the current status of the cloud storage service, encryption key, authentication information, and more.

API description

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

Parameters

Parameter Description
complete The success callback. The current cloud storage service status is returned.

Enum values of ThingSmartCloudState

Enum value Description
ThingSmartCloudStateNoService The cloud storage service is not activated.
ThingSmartCloudStateNoData The cloud storage service is activated, but no video is available for playback.
ThingSmartCloudStateValidData The cloud storage service is activated and videos are available for playback.
ThingSmartCloudStateExpiredNoData The cloud storage service has expired, and no video is available for playback.
ThingSmartCloudStateExpiredData The cloud storage service has expired, but videos are still available for playback.
ThingSmartCloudStateLoadFailed Failed to load cloud storage service status

After the cloud storage service expires, the existing cloud-stored video files will be retained for a period, seven days in most cases. This retention period is subject to the cloud storage service agreement. If the subscription is not renewed within this period, the cloud-stored video footage will be deleted at the end of this period.

Query video recording date

After the cloud storage data is returned, if cloud-stored video footage can be played back, the cloudDays property indicates the date on which cloud-stored video footage can be played back.

API description

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

Fields of ThingSmartCloudDayModel

Field Type Description
sumDuration NSInteger The total length of the cloud-stored video footage on the current date.
uploadDay NSString The date in the format of yyyy-MM-dd.
startTime NSInteger The Unix timestamp to indicate 00:00:00 on the current date.
endTime NSInteger The Unix timestamp to indicate 23:59:59 on the current date.

Query a list of cloud-stored video clips

Before cloud-stored video playback, the time model that indicates the duration of each video clip must be queried.

API description

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

Parameters

Parameter Description
cloudDay The date model that indicates the duration of each cloud-stored video clip.
success The success callback. An array of date models for all video clips on the current date is returned.
failure The failure callback. An error message is returned.

Data model of ThingSmartCloudTimePieceModel

Field Type Description
startTime NSInteger The start Unix timestamp of a video clip.
startDate NSDate The start date of a video clip.
endTime NSInteger The end Unix timestamp of a video clip.
endDate NSDate The end date of a video clip.
aiDetectList NSArray<ThingSmartAICloudTimePieceModel *> * The video clip of the objects identified by AI-based algorithms.

Data model of ThingSmartAICloudTimePieceModel

ThingSmartAICloudTimePieceModel inherits from ThingSmartCloudTimePieceModel.

Field Type Description
startTime NSInteger The start Unix timestamp of a video clip.
startDate NSDate The start date of a video clip.
endTime NSInteger The end Unix timestamp of a video clip.
endDate NSDate The end date of a video clip.
aiCode NSString The ID of an AI event clip.

Query generic cloud storage events

After the subscription to cloud storage, the smart device detects and reports cloud storage events. These events are linked with cloud-stored video recording. Each cloud storage event results in a cloud-stored video clip in most cases.

Alert events are slightly different from detection messages for cloud storage. They might be triggered in similar ways. However, cloud-stored video footage will not be deleted when detection messages are deleted. Not all detection messages trigger cloud-stored video recording, for example, low battery level.

API description

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

Parameters

Parameter Description
cloudDay The date model of cloud-stored video footage.
offset The event from which video recording is started. A value of 0 indicates the first event.
limit The maximum number of events for which video recording is performed. A value of -1 indicates that all events are queried.
success The success callback. An array of event models is returned.
failure The failure callback. An error message is returned.

Data model of ThingSmartCloudTimeEventModel

Field Type Description
describe NSString The description of an event.
startTime NSInteger The start Unix timestamp of an event.
endTime NSInteger The end Unix timestamp of an event.
snapshotUrl NSString The URL of the image captured when an event occurs.

The captured images of cloud storage events are encrypted before they can be displayed by the image encryption component ThingEncryptImage. For more information, see Encrypted Images.

Query AI-based cloud storage settings on device

Checks whether AI-based detection is enabled for a specific device.

API description

- (void)queryAIDetectConfigSuccess:(void (^)(ThingCameraAIDetectConfigModel *model))success
                           failure:(void (^)(NSError *error))failure;

Data model of ThingCameraAIDetectConfigModel

Field Type Description
isAiDevice BOOL Indicates whether the device supports AI-based detection.
switchState NSInteger Indicates whether AI-based detection is enabled for the device. Valid values:
  • 1: enabled
  • 0: disabled
aiItemList NSArray The data of objects supported by AI-based detection.

Data model of ThingCameraAIDetectEventModel

Field Type Description
aiCode NSString The identifier of an AI model.
aiCodeIcon NSString The icon of an AI model.
aiCodeDesc NSString The description of an AI model.
configState NSInteger Indicates whether the current model is enabled.
  • 1: enabled
  • 0: disabled
orderValue NSInteger The sorting value of the current model.

Example

 [self.cloudManager queryAIDetectConfigSuccess:^(ThingCameraAIDetectConfigModel *model) {
            //
} failure:^(NSError *error) {
            //
 }];

Update on/off status of AI-based detection

Enables or disables AI-enabled detection for a specific device.

API description

- (void)enableAIDetect:(BOOL)enable
               success:(void (^)(BOOL result))success
               failure:(void (^)(NSError * error))failure;

Parameters

Parameter Description
enable Specifies whether to enable or disable AI-enabled detection.
success The success callback.
failure The failure callback.

Update type of AI event

API description

- (void)enableAIDetectEventType:(NSString *)aiCode
                         enable:(BOOL)enable
                        success:(void (^)(BOOL result))success
                        failure:(void (^)(NSError *error))failure;

Parameters

Parameter Description
aiCode The ID of an AI event.
enable Specifies whether this type of AI event is available.
success The success callback.
failure The failure callback.

Example

[self.cloudManager enableAIDetect:YES success:^(BOOL result) {
            //
} failure:^(NSError *error) {
            //
 }];

Query AI-based cloud storage events

After AI-based cloud storage is enabled, the device can report events when detection alerts are triggered. AI-based algorithms can be used to accurately identify whether the reported events include the objects specified by users. Currently, the supported objects include humans, pets, vehicles, and packages.

Alert events and detection messages for AI-based cloud storage are handled with the same logic as that for generic cloud storage.

API description

- (void)timeEventsWithCloudDay:(ThingSmartCloudDayModel *)cloudDay
                        offset:(int)offset
                         limit:(int)limit
                       aiCodes:(NSString *)aiCodes
                       success:(void(^)(NSArray<ThingSmartCloudTimeEventModel *> * timeEvents))success
                       failure:(void(^)(NSError * error))failure;

Parameters

Parameter Description
cloudDay The date model of cloud-stored video footage.
offset The event from which video recording is started. A value of 0 indicates the first event.
limit The maximum number of events for which video recording is performed. A value of -1 indicates that all events are queried.
aiCodes The list of AI event IDs. Example: ai_package,ai_human. Set the value to all to query all AI events.
success The success callback. An array of event models is returned.
failure The failure callback. An error message is returned.

Data model of ThingSmartCloudTimeEventModel

Field Type Description
describe NSString The description of an event.
startTime NSInteger The start Unix timestamp of an event.
endTime NSInteger The end Unix timestamp of an event.
snapshotUrl NSString The URL of the image captured when an event occurs.
aiDetectList NSArray<ThingSmartAIEventModel *> * The list of objects identified by AI-based algorithms when an event occurs.

Data model of ThingSmartAIEventModel

Field Type Description
aiCode NSString The ID of an AI event.
startTime NSInteger The start Unix timestamp of an event.
endTime NSInteger The end Unix timestamp of an event.
aiCodeIcon NSString The icon of the object identified by AI-based algorithms.
orderValue NSInteger The sorting value of the object identified by AI-based algorithms.

Example

ThingSmartCloudDayModel *model = [ThingSmartCloudDayModel new];
[self.cloudManager timeEventsWithCloudDay:model offset:1 limit:15 aiCodes:@"all" success:^(NSArray<ThingSmartCloudTimeEventModel *> * timeEvents)) {
            //
} failure:^(NSError *error) {
            //
 }];

The captured images of AI-based cloud storage events are encrypted before they can be displayed by the image encryption component ThingEncryptImage. For more information, see Encrypted Images.

Play back cloud-stored video footage

Before cloud-stored video playback, the start time, end time, and whether a cloud storage event is linked must be specified. Users can also set the audio switch, local video recording, screenshot capturing, and other options.

Start playback

  • Playback of a video clip (ThingSmartCloudTimePieceModel):
    • Set the start time to a timestamp from startTime to endTime of ThingSmartCloudTimePieceModel.
    • Set isEvent to NO.
  • Playback of video footage linked with a cloud storage event (ThingSmartCloudTimeEventModel):
    • Set the start time to startTime of ThingSmartCloudTimeEventModel.
    • Set isEvent to YES.
    • Set the end time to the end time of the current date. It is endTime of ThingSmartCloudDayModel.

API description

- (void)playCloudVideoWithStartTime:(long)startTime
                            endTime:(long)endTime
                            isEvent:(BOOL)isEvent
                         onResponse:(void(^)(int errCode))responseCallback
                         onFinished:(void(^)(int errCode))finishedCallback;

Parameters

Parameter Description
startTime The time from which video footage playback is started.
endTime The time at which video footage playback is stopped. By default, all video clips on the current date will be automatically played back.
isEvent Specifies whether to play back video footage linked with a cloud storage event.
responseCallback The callback that is executed when playback is requested. errCode indicates an error message and 0 indicates that playback is started.
finishedCallback The callback that is executed when playback is finished. errCode indicates an error message and 0 indicates that playback is finished.

Pause playback

API description

- (int)pausePlayCloudVideo;

Return value

Type Description
int An error message is returned or a value of 0 indicates a successful request.

Resume playback

API description

- (int)resumePlayCloudVideo;

Return value

Type Description
int An error message is returned or a value of 0 indicates a successful request.

Stop playback

API description

- (int)stopPlayCloudVideo;

Return value

Type Description
int An error message is returned or a value of 0 indicates a successful request.

Set playback speed

Sets the playback speed after video playing is started. The audio playback speed cannot be set.

API description

- (int)setCloudVideoPlaySpeed:(ThingSmartCameraPlayBackSpeed)speed;

Parameters

Parameter Description
speed The playback speed that supports 1x, 2x, and 4x. You can get an enum value of ThingSmartCameraPlayBackSpeed to set the playback speed.

Example

 int result = [self.cloudManager setCloudVideoPlaySpeed:ThingSmartCameraPlayBackSpeed_10TIMES];

Example

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

Download cloud-stored video footage

Start downloading

API description

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

Parameters

Parameter Description
timeRange The period in which video clips are downloaded.
  • The start time of the period is a 10-digit timestamp.
  • Unit: seconds.
videoPath The file path to save video clips. Format: folderPath/fileName.mp4.
success The success callback.
progress The callback for the download progress indicated by an integer. Valid values: 1 to 100.
failure The failure callback.

Pause video downloading

API description

- (void)pauseDownloadCloudVideo;

Resume video downloading

API description

- (void)resumeDownloadCloudVideo:(DownloadFailure)failure;

Parameters

Parameter Description
failure The failure callback.

Cancel video downloading

API description

- (void)cancelDownloadCloudVideo;

Delete cloud-stored video footage

Delete cloud-stored video footage in specified period

API description

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

Parameters

Parameter Description
timeRange The period in which video footage are deleted.
  • The start time of the period is a 10-digit timestamp.
  • Unit: seconds.
success The success callback.
failure The failure callback.

Example

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

    })
}

Delete all-day cloud-stored video footage

API description

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

Parameters

Parameter Description
timeRange The period of the day on which video clips are deleted.
  • The start time of the period is a 10-digit timestamp.
  • Unit: seconds.
success The success callback.
failure The failure callback.

Example

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

    })
}

Process cloud-stored video effect

Query cloud-stored video rendering views

ThingSmartCloudManager is used to implement automatic rendering of cloud-stored video footage. The videoView method can be called to query cloud-stored video rendering views and add these views to the screen.

API description

- (UIView<ThingSmartVideoViewType> *)videoView;

Return value

Type Description
UIView The video rendering view.

Set mute status

API description

- (void)enableMute:(BOOL)mute success:(void(^)(void))success failure:(void (^)(NSError * error))failure;

Parameters

Parameter Description
mute Specify whether to mute the video.
success The success callback.
failure The failure callback. An error message is returned.

Query mute status

API description

- (BOOL)isMuted;

Return value

Type Description
BOOL Indicates whether the video is muted.

Save cloud-stored video footage

Record and save cloud-stored video footage to system album

API description

- (void)startRecord;

Record cloud-stored videos and save them to a specified directory

API description

- (void)startRecordAtPath:(NSString *)filePath;

Parameters

Parameter Description
filePath The path in which videos are stored.

Record cloud-stored videos in custom direction and save them to specified directory

API description

- (void)startRecordWithRotateDirection:(ThingSmartVideoRotateDirection)direction filePath:(NSString *)filePath;

Parameters

Parameter Description
direction The direction to which the camera faces when videos are recorded.
filePath The path in which videos are stored.

Stop recording and save video files

API description

- (int)stopRecord;

Return value

Type Description
int An error message is returned or a value of 0 indicates that files are saved successfully.

Capture and save video screenshots to system album

API description

- (UIImage *)snapShoot;

Return value

Type Description
UIImage The UIImage object of a video screenshot. If nil is returned, the system failed to save the screenshot.

Capture and save video screenshots to a specific directory

API description

- (UIImage *)snapShootAtPath:(NSString *)filePath thumbnilPath:(NSString *)thumbnilPath;

Parameters

Parameter Description
filePath The path in which screenshots are stored.
thumbnilPath The path to save the thumbnail. Set the value to nil if this parameter is not required.

To query the UIImage object of the current screenshot, the screenshot does not need to be automatically saved. You can call the method - (UIImage *)screenshot; of videoView to query the screenshot.

Example

Objective C:

// self.devId = @"xxxxx";
- (void)viewDidLoad {
     if (![ThingSmartCloudManager isSupportCloudStorage:self.devId]) {
        // Cloud storage is not supported.
        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) {
        // Failed to pause playback.
    }
}

- (void)resume {
    if ([self.cloudManager resumePlayCloudVideo] != 0) {
        // Failed to resume playback.
    }
}

- (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) {
            // Failed to create video footage.
        }else {
            // Video footage is created and saved to a system album.
        }
          self.isRecording = NO;
    }else {
        [self.cloudManager startRecord];
            self.isRecording = YES;
    }
}

- (void)snapShoot {
    if ([self.cloudManager snapShoot]) {
        // A video screenshot is captured and saved to a system album.
    }else {
        // Failed to capture a screenshot.
    }
}

Swift:

func viewDidLoad() {
     if (!ThingSmartCloudManager.isSupportCloudStorage(devId: self.devId)) {
        // Cloud storage is not supported.
        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 {
        // Failed to pause playback.
    }
}

func resume() {
    if self.cloudManager.resumePlayCloudVideo() != 0 {
        // Failed to resume playback.
    }
}

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 {
            // Failed to create video footage.
        } else {
            // Video footage is created and saved to a system album.
        }
        self.isRecording = false
    } else {
        self.cloudManager.startRecord()
        self.isRecording = true
    }
}

func snapShoot() {
    if self.cloudManager.snapShoot() {
        // A video screenshot is captured and saved to a system album.
    } else {
        // Failed to capture a screenshot.
    }
}