1.1. 音视频功能

除了实时视频直播,存储卡录像播放以外,Camera SDK 还提供了一些额外的音视频能力。

1.1.1. 本地录制

当视频成功开始播放以后(可以是视频直播,也可以是录像回放),可以将当前正在播放的视频录制到手机中。

接口说明

录制视频并保存到手机系统相册

- (void)startRecord;

接口说明

录制视频保存到指定路径

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

参数说明

参数 说明
filePath 保存视频的文件路径

接口说明

停止录制,并保存文件

- (void)stopRecord;

接口说明

视频开始录制的代理回调

- (void)cameraDidStartRecord:(id<TuyaSmartCameraType>)camera;

接口说明

视频停止录制并成功保存视频文件的代理回调

- (void)cameraDidStopRecord:(id<TuyaSmartCameraType>)camera;

调用开始录制和停止录制均有可能会失败,失败后将通过代理方法 -(void)camera:didOccurredErrorAtStep: specificErrorCode:;返回错误信息。

示例代码

ObjC

- (void)startRecord {
    if (self.isRecording) {
        return;
    }
    // 在视频播放中才能开启录制
    if (self.previewing || self.playbacking) {
        [self.camera startRecord];
        self.recording = YES;
    }
}

- (void)stopRecord {
    if (self.isRecording) {
        [self.camera stopRecord];
        self.recording = NO;
    }
}

- (void)cameraDidStartRecord:(id<TuyaSmartCameraType>)camera {
        // 已成功开启视频录制,更新 UI
}

- (void)cameraDidStopRecord:(id<TuyaSmartCameraType>)camera {
        // 视频录制已停止,并且录制的视频成功保存
}

- (void)camera:(id<TuyaSmartCameraType>)camera didOccurredErrorAtStep:(TYCameraErrorCode)errStepCode specificErrorCode:(NSInteger)errorCode {
      // 开启或者停止视频录制失败
    if (errStepCode == TY_ERROR_RECORD_FAILED) {
        self.recording = NO;
    }
}

Swift

func startRecord() {
    if self.isRecording {
        return
    }
    guard self.isPreviewing || self.isPlaybacking else {
        return;
    }
    self.camera.startRecord()
    self.isRecording = true
}

func stopRecord() {
    guard self.isRecording else {
        return
    }
    self.camera.stopRecord()
}

func cameraDidStartRecord(_ camera: TuyaSmartCameraType!) {
    // 已成功开启视频录制,更新 UI
}

func cameraDidStopRecord(_ camera: TuyaSmartCameraType!) {
    // 视频录制已停止,并且录制的视频成功保存
}

func camera(_ camera: TuyaSmartCameraType!, didOccurredErrorAtStep errStepCode: TYCameraErrorCode, specificErrorCode errorCode: Int) {
    // 开启或者停止视频录制失败
    if errStepCode == TY_ERROR_RECORD_FAILED {
        self.isRecording = false
    }
}

在视频录制的过程中,请不要再切换视频清晰度,开关声音及对讲。

1.1.2. 视频截图

同样的,当视频成功开始播放以后(可以是视频直播,也可以是录像回放),可以对当前显示的视频图像截图,Camera SDK 提供三种截图的方式。下面两种方式是TuyaSmartCameraType 对象提供的方法:

接口说明

视频截图,图片保存在手机系统相册

- (UIImage *)snapShoot;

返回值

类型 说明
UIImage 视频截图的 UIImage 对象,返回 nil 表示图片保存失败

接口说明

视频截图,图片保存在指定文件路径

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

参数说明

参数 说明
filePath 保存图片的文件路径
thumbnilPath 保存缩略图的文件路径,如果不需要,可以传入 nil

返回值

类型 说明
UIImage 视频截图的 UIImage 对象,返回 nil 表示图片保存失败

接口说明

还有一种方式,是使用视频渲染视图TuyaSmartVideoType的截图接口,此方法只返回一个 UIImage对象,并不会自动保存图片。

- (UIImage *)screenshot;

返回值

类型 说明
UIImage 视频截图的 UIImage 对象,返回 nil 表示图片保存失败

示例代码

ObjC

- (void)snapShoot {
    // 在播放视频时才可以截图
    if (self.previewing || self.playbacking) {
        if ([self.camera snapShoot]) {
            // 截图已成功保存到手机相册
        }
    }
}

Swift

func snapShoot() {
    guard self.isPreviewing || self.isPlaybacking else {
        return;
    }
    if let _ = self.camera.snapShoot() {
        // 截图已成功保存到手机相册
    }
}

在使用上面的录制/截图方法时,请确保 App 已获得手机相册的访问权限,否则会导致 App 崩溃。

1.1.3. 视频声音

当视频成功开始播放以后(可以是视频直播,也可以是录像回放),可以开启视频声音,默认声音是关闭状态。

接口说明

视频声音开关

- (void)enableMute:(BOOL)mute forPlayMode:(TuyaSmartCameraPlayMode)playMode;

参数说明

参数 说明
mute 是否静音,YES:关闭声音;NO:打开声音
playMode 当前的播放模式

接口说明

视频声音开关结果代理回调

- (void)camera:(id<TuyaSmartCameraType>)camera didReceiveMuteState:(BOOL)isMute playMode:(TuyaSmartCameraPlayMode)playMode;

参数说明

参数 说明
camera 开关声音的 Camera 对象
isMute 当前的静音状态
playMode 当前的播放模式

播放模式切换后(视频直播和录像回放之间切换), Camera SDK 内部不会保留前一个播放模式的静音状态。即如果视频直播打开声音后,切换到了录像回放的模式,声音还是打开的,这时关闭声音,再次切换到视频直播模式,声音还是关闭的。所以切换模式后,需要同步一下期望的声音开关状态。

1.1.4. 实时对讲

在 p2p 连接成功后,可以开启与设备的实时通话功能,在开始对讲前,需要确保 App 已获得手机麦克风的访问权限。

接口说明

开启 App 到摄像机的声音通道

- (void)startTalk;

接口说明

关闭 App 到摄像机的声音通道

- (void)stopTalk;

接口说明

App 到摄像机的声音通道成功开启代理回调

- (void)cameraDidBeginTalk:(id<TuyaSmartCameraType>)camera;

接口说明

App 到摄像机的声音通道成功关闭的代理回调

- (void)cameraDidStopTalk:(id<TuyaSmartCameraType>)camera;

双向对讲

在实时视频直播时,打开视频声音,此时播放的声音即为摄像机实时采集的人声与环境声音,此时打开 App 到摄像机的声音通道,即可实现双向对讲功能。

部分摄像机可能没有扬声器或者拾音器,此类摄像机无法实现双向对讲。

单向对讲

单向对讲功能需要开发者来实现控制。在开启对讲的时候,关闭视频声音,关闭对讲后,再打开视频声音即可。

示例代码

下面以单向对讲为例来展示声音开关与实时对讲接口的用法。

ObjC

- (void)startTalk {
    [self.camera startTalk];
    // 如果不是静音状态,关闭声音
    if (!self.isMuted) {
        [self.camera enableMute:YES forPlayMode:TuyaSmartCameraPlayModePreview];
    }
}

- (void)stopTalk {
    [self.camera stopTalk];
}

- (void)cameraDidBeginTalk:(id<TuyaSmartCameraType>)camera {
        // 对讲已成功开启
}

- (void)cameraDidStopTalk:(id<TuyaSmartCameraType>)camera {
        // 对讲已停止
        // 如果是静音状态,打开声音
    if (self.isMuted) {
        [self.camera enableMute:NO forPlayMode:TuyaSmartCameraPlayModePreview];
    }
}

- (void)camera:(id<TuyaSmartCameraType>)camera didReceiveMuteState:(BOOL)isMute playMode:(TuyaSmartCameraPlayMode)playMode {
        // 收到静音状态的变化,更新 UI
        self.isMuted = isMute;
}

- (void)camera:(id<TuyaSmartCameraType>)camera didOccurredErrorAtStep:(TYCameraErrorCode)errStepCode specificErrorCode:(NSInteger)errorCode {
    if (errStepCode == TY_ERROR_START_TALK_FAILED) {
            // 开启对讲失败,重新打开声音
                if (self.isMuted) {
                [self.camera enableMute:NO forPlayMode:TuyaSmartCameraPlayModePreview];
            }
    }
    else if (errStepCode == TY_ERROR_ENABLE_MUTE_FAILED) {
                // 设置静音状态失败
    }
}

Swift

// 当前在实时视频播放状态
func startTalk() {
    self.camera.startTalk()
    guard self.isMuted else {
        self.camera.enableMute(true, for: .preview)
        return
    }
}

func stopTalk() {
    self.camera.stopTalk()
}

func cameraDidBeginTalk(_ camera: TuyaSmartCameraType!) {
    // 对讲已成功开启
}

func cameraDidStopTalk(_ camera: TuyaSmartCameraType!) {
    // 对讲已停止
    if self.isMuted {
        self.camera.enableMute(false, for: .preview)
    }
}

func camera(_ camera: TuyaSmartCameraType!, didReceiveMuteState isMute: Bool, playMode: TuyaSmartCameraPlayMode) {
    self.isMuted = isMute
    // 收到静音状态的变化,更新 UI
}

func camera(_ camera: TuyaSmartCameraType!, didOccurredErrorAtStep errStepCode: TYCameraErrorCode, specificErrorCode errorCode: Int) {
    if errStepCode == TY_ERROR_START_TALK_FAILED {
        // 开启对讲失败,重新打开声音
        self.camera.enableMute(false, for: .preview)
    }else if errStepCode == TY_ERROR_ENABLE_MUTE_FAILED {
        // 设置静音状态失败
    }
}

1.1.5. 清晰度切换

在实时视频直播时,可以切换清晰度(少数摄像机只支持一种清晰度),目前只有高清和标清两种清晰度,且只有实时视频直播时才支持。存储卡视频录像在录制时只保存了一种清晰度的视频流。

接口说明

获取当前视频图像的清晰度,结果通过代理方法返回

- (void)getHD;

接口说明

切换视频清晰度,YES 是高清,NO 是标清

- (void)enableHD:(BOOL)hd;

参数说明

参数 说明
hd 是否高清,YES:高清;NO:标清

接口说明

视频清晰度状态变化代理回调

- (void)camera:(id<TuyaSmartCameraType>)camera didReceiveDefinitionState:(BOOL)isHd;

参数说明

参数 说明
camera 清晰度变化的 Camera 对象
isHd 当前的清晰度状态,YES:高清,NO:标清

示例代码

ObjC

- (void)changeHD {
        [self.camera enableHD:!self.HD];
}

// 视频分辨率改变的代理方法,实时视频直播或者录像回放刚开始时也会调用
- (void)camera:(id<TuyaSmartCameraType>)camera resolutionDidChangeWidth:(NSInteger)width height:(NSInteger)height {
        // 获取当前的清晰度
    [self.camera getHD];
}

// 清晰度状态代理方法
- (void)camera:(id<TuyaSmartCameraType>)camera didReceiveDefinitionState:(BOOL)isHd {
    self.HD = isHd;
}

- (void)camera:(id<TuyaSmartCameraType>)camera didOccurredErrorAtStep:(TYCameraErrorCode)errStepCode specificErrorCode:(NSInteger)errorCode {
    if (errStepCode == TY_ERROR_ENABLE_HD_FAILED) {
                // 切换视频清晰度失败
    }
}

Swift

func changeHD() {
    self.camera.enableHD(true)
}

// 视频分辨率改变的代理方法,实时视频直播或者录像回放刚开始时也会调用
func camera(_ camera: TuyaSmartCameraType!, resolutionDidChangeWidth width: Int, height: Int) {
    // 获取当前的清晰度
    self.camera.getHD()
}

func camera(_ camera: TuyaSmartCameraType!, didReceiveDefinitionState isHd: Bool) {
    self.isHD = isHd
}

func camera(_ camera: TuyaSmartCameraType!, didOccurredErrorAtStep errStepCode: TYCameraErrorCode, specificErrorCode errorCode: Int) {
    if errStepCode == TY_ERROR_ENABLE_HD_FAILED {
        // 切换视频清晰度失败
    }
}

1.1.6. 裸流数据

Camera SDK 提供访问视频裸流数据的代理回调方法,此方法返回视频帧的 YUV 数据,颜色编码格式为 YUV 420sp,iOS 中,对应于 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange 格式。

接口说明

视频帧裸流数据代理回调

- (void)camera:(id<TuyaSmartCameraType>)camera ty_didReceiveVideoFrame:(CMSampleBufferRef)sampleBuffer frameInfo:(TuyaSmartVideoFrameInfo)frameInfo;

参数说明

参数 说明
camera 接收到视频数据的 Camera 对象
sampleBuffer 视频帧 YUV 数据
frameInfo 视频帧信息

TuyaSmartVideoFrameInfo 结构体

字段 类型 描述
nWidth int 视频图像宽度
nHeight int 视频图像高度
nFrameRate int 视频帧率
nTimeStamp unsigned long long 视频帧时间戳
nDuration unsigned long long 播放报警消息中视频附件时,视频的总长度,单位是毫秒
nProgress unsigned long long 播放报警消息中视频附件时,视频帧的时间点,单位是毫秒

如果你想要自己渲染视频图像,或者需要对视频图像做特殊处理,可以将TuyaSmartCameraType对象的autoRender属性设置为 NO,然后实现此代理方法,此时 Camera SDK 将不会自动渲染视频图像。

可以将sampleBuffer直接强转为CVPixelBufferRef,如果你想要异步处理视频帧数据,请记得先 retain,否则此代理方法执行完成后,视频帧数据将会被释放,异步处理时会发生野指针异常。

示例代码

ObjC

- (void)camera:(id<TuyaSmartCameraType>)camera ty_didReceiveVideoFrame:(CMSampleBufferRef)sampleBuffer frameInfo:(TuyaSmartVideoFrameInfo)frameInfo {
    CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)sampleBuffer;
    // retain pixelbuffer,防止提前释放
    CVPixelBufferRetain(pixelBuffer);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 处理并渲染 pixelBuffer
        // ...
        // 最后别忘了释放
        CVPixelBufferRelease(pixelBuffer);
    });
}

Swift

func camera(_ camera: TuyaSmartCameraType!, ty_didReceiveVideoFrame sampleBuffer: CMSampleBuffer!, frameInfo: TuyaSmartVideoFrameInfo) {
        // 处理并渲染视频数据
}

results matching ""

    No results matching ""