音视频功能

更新时间:2023-09-19 03:00:53下载pdf

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

本地录制

无论是视频直播,还是录像回放,当视频成功开始播放以后,用户都可以将当前正在播放的视频录制到手机中。

接口说明

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

- (void)startRecord;

接口说明

录制视频保存到指定路径。

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

参数说明

参数 说明
filePath 保存视频的文件路径,视频保存为 MP4 文件,文件路径需要有 .mp4 后缀

接口说明

停止录制,并保存文件。

- (void)stopRecord;

接口说明

视频开始录制的代理回调。

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

接口说明

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

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

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

示例代码

Objective C:

- (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<ThingSmartCameraType>)camera {
        // 已成功开启视频录制,更新 UI
}

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

- (void)camera:(id<ThingSmartCameraType>)camera didOccurredErrorAtStep:(TYCameraErrorCode)errStepCode specificErrorCode:(NSInteger)errorCode {
    // 开启或者停止视频录制失败
    if (errStepCode == Thing_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: ThingSmartCameraType!) {
    // 已成功开启视频录制,更新 UI
}

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

func camera(_ camera: ThingSmartCameraType!, didOccurredErrorAtStep errStepCode: ThingCameraErrorCode, specificErrorCode errorCode: Int) {
    // 开启或者停止视频录制失败
    if errStepCode == Thing_ERROR_RECORD_FAILED {
        self.isRecording = false
    }
}
  • 在视频录制的过程中,请不要再切换视频清晰度,开关声音及对讲。否则,可能会出现录制失败。建议在录制视频时,将切换视频清晰度、开关声音、对讲等设置为不可操作状态。
  • 由于视频播放卡顿、从开始录制时的下一个关键帧保存视频等情况的存在,实际录制保存的视频时长,可能比录制时间少。因此,录制时间仅做参考。

视频截图

同样的,无论是视频直播,还是录像回放,当视频成功开始播放以后,用户可以对当前显示的视频图像截图。IPC SDK 提供三种截图的方式,下面两种方式是 ThingSmartCameraType 对象提供的方法:

接口说明

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

- (UIImage *)snapShoot;

返回值

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

接口说明

视频截图,图片保存在指定文件路径。P2P 1.0 设备不支持此接口。

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

参数说明

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

返回值

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

接口说明

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

- (UIImage *)screenshot;

返回值

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

示例代码

Objective C:

- (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 崩溃。

视频声音

无论是视频直播,还是录像回放,当视频成功开始播放以后,用户都可以开启视频声音,默认声音是关闭状态。

接口说明

视频声音开关。

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

参数说明

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

接口说明

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

- (void)camera:(id<ThingSmartCameraType>)camera didReceiveMuteState:(BOOL)isMute playMode:(ThingSmartCameraPlayMode)playMode;

参数说明

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

接口说明

扬声器和听筒模式的切换,返回值不为 0 表示切换失败。P2P 1.0 设备不支持此接口。

- (int)enableSpeaker:(BOOL)enabled;

参数说明

参数 说明
enabled
  • YES:切换成扬声器播放。
  • NO:切换成听筒播放。

接口说明

获取当前声音播放模式,返回 YES 表示扬声器播放,NO 为听筒播放,P2P 1.0 设备不支持此接口。

- (BOOL)speakerEnabled;

播放模式在视频直播和录像回放之间切换后,IPC SDK 内部不会保留前一个播放模式的静音状态。即如果:

  • 打开视频直播声音后,切换到了录像回放的模式,声音还是打开的。
  • 这时关闭声音,再次切换到视频直播模式,声音还是关闭的。

所以切换播放模式后,您需要同步一下期望的声音开关状态。

视频码率

视频出流成功后,可以获取实时的视频码率。

接口说明

获取实时的视频码率。

- (double)getVideoBitRateKBPS;

实时对讲

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

查询是否支持对讲

设备支持扬声器,代表支持单向对讲。设备同时支持扬声器和拾音器,代表视频有声音,即支持双向对讲。您可通过查询 设备能力,确认设备是否支持扬声器和拾音器。

双向对讲

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

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

单向对讲

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

接口说明

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

- (void)startTalk;

接口说明

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

- (void)stopTalk;

接口说明

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

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

接口说明

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

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

示例代码

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

Objective C:

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

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

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

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

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

- (void)camera:(id<ThingSmartCameraType>)camera didOccurredErrorAtStep:(ThingCameraErrorCode)errStepCode specificErrorCode:(NSInteger)errorCode {
    if (errStepCode == Thing_ERROR_START_TALK_FAILED) {
            // 开启对讲失败,重新打开声音
                if (self.isMuted) {
                [self.camera enableMute:NO forPlayMode:ThingSmartCameraPlayModePreview];
            }
    }
    else if (errStepCode == Thing_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: ThingSmartCameraType!) {
    // 对讲已成功开启
}

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

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

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

切换清晰度

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

接口说明

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

- (void)getHD;

接口说明

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

- (void)enableHD:(BOOL)hd;

参数说明

参数 说明
hd 是否高清:
  • YES:高清。
  • NO:标清。

接口说明

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

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

参数说明

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

以上三个接口在 3.20.0 版本 SDK 中已废弃,但 P2P 1.0 设备可以继续使用。您可以使用以下三个接口替代,但注意 P2P 1.0 设备不支持这些接口。

接口说明

获取视频清晰度。

- (void)getDefinition;

接口说明

设置视频清晰度。

- (void)setDefinition:(ThingSmartCameraDefinition)definition;

接口说明

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

- (void)camera:(id<ThingSmartCameraType>)camera definitionChanged:(ThingSmartCameraDefinition)definition;

ThingSmartCameraDefinition 枚举

描述
ThingSmartCameraDefinitionProflow 省流量
ThingSmartCameraDefinitionStandard 标清
ThingSmartCameraDefinitionHigh 高清
ThingSmartCameraDefinitionSuper 超清
ThingSmartCameraDefinitionSSuper 超超清

不同的清晰度,需要设备端支持,目前普遍设备只支持标清和高清两种清晰度。

示例代码

Objective C:

- (void)changeHD {
        ThingSmartCameraDefinition definition = self.HD ? ThingSmartCameraDefinitionStandard : ThingSmartCameraDefinitionHigh;
        [self.camera setDefinition:definition];
}

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

// 清晰度状态代理方法
- (void)camera:(id<ThingSmartCameraType>)camera definitionChanged:(ThingSmartCameraDefinition)definition {
    self.HD = definition >= ThingSmartCameraDefinitionHigh;
}

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

Swift:

func changeHD() {
    let definition = self.isHD ? ThingSmartCameraDefinition.standard : ThingSmartCameraDefinition.high
    self.camera.setDefinition(definition)
}

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

func camera(_ camera: ThingSmartCameraType!, definitionChanged definition: ThingSmartCameraDefinition) {
        self.isHD = definition.rawValue >= ThingSmartCameraDefinition.high.rawValue
}

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

裸流数据

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

接口说明

视频帧裸流数据代理回调。

- (void)camera:(id<ThingSmartCameraType>)camera thing_didReceiveVideoFrame:(CMSampleBufferRef)sampleBuffer frameInfo:(ThingSmartVideoFrameInfo)frameInfo;

参数说明

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

ThingSmartVideoFrameInfo 结构体

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

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

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

示例代码

Objective C:

- (void)camera:(id<ThingSmartCameraType>)camera thing_didReceiveVideoFrame:(CMSampleBufferRef)sampleBuffer frameInfo:(ThingSmartVideoFrameInfo)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: ThingSmartCameraType!, thing_didReceiveVideoFrame sampleBuffer: CMSampleBuffer!, frameInfo: ThingSmartVideoFrameInfo) {
        // 处理并渲染视频数据
}

智能画框

在视频直播的过程中,如果设备检查到移动物体,智能画框 会在对应的物体上标记一个白色的矩形框。

首先,您需要开启设备的智能画框功能。开启后,设备会随着视频帧发送移动物体的坐标,通过 DP 198ipc_object_outline)来开启设备端的智能画框功能。设备控制接口功能,请参考 设备控制

在设备端智能画框功能开启的前提下,直播视频播放时,您需要打开 IPC SDK 的智能画框功能。SDK 会根据设备发送的移动物体坐标,在视频图像上绘制矩形框。

此处智能画框功能相关 DP 不做详细介绍,您按照设备端约束即可。

打开智能画框功能

接口说明

智能画框功能开关,通常在开始预览 startPreview 或设置清晰度 setDefinition: 后调用。

- (void)setOutLineEnable:(BOOL)enable;

参数说明

参数 说明
enable 是否开启智能画框

智能画框属性设置

通过设置智能画框的属性来控制框的样式,例如框的颜色,画笔宽度,闪烁频率等。

接口说明

智能画框属性设置,结合设备上报的 SEI(Supplemental Enhancement Information)信息,通过传入指定格式的 JSON 字符串来实现。

- (int)setSmartRectFeatures:(NSString *)features;

参数说明

参数 features 为 JSON 格式字符串,格式约定:

{
    "SmartRectFeature":[
        {
            "type":0,
            "index":0,
            "brushWidth":1,
            "flashFps":{
                "drawKeepFrames":2,
                "stopKeepFrames":2
            },
            "rgb":0xFF0000,
            "shape":0
        },
        {
            "type":0,
            "index":1,
            "brushWidth":2,
            "flashFps":{
                "drawKeepFrames":3,
                "stopKeepFrames":2
            },
            "rgb":0x00FF00,
            "shape":1
        }
    ]
}
参数 类型 说明
SmartRectFeature Array 固定标识,支持数组格式(表示多个框的设置),必传
type Int 画框类型
  • 0:智能画框(默认)
  • 1:越线告警框
index Int 框的索引,对应 SEI 信息里面的 od 的每个 ID 值
shape Int 矩形框形状
  • 0:闭合矩形框
  • 1:只画 4 个角
rgb Int 矩形框颜色,由 RGB 格式转化,默认为 0xFC4747,取值范围 0x000000~0xFFFFFF
brushWidth Int 矩形框画笔粗细
  • 0:细
  • 1:中
  • 2:粗
flashFps String 矩形框闪烁频率
  • drawKeepFrames:表示绘制的帧数
  • stopKeepFrames:表示暂停绘制的帧数

SEI 协议定义

与设备侧约定协议,IPC SDK 解析 SEI 上报的信息,在对应的位置结合相应的属性进行画框。

{
    "AGTX":{
        "time":6885,
        "chn":0,
        "key":1,
        "iva":{
            "od":[
                {
                    "obj":{
                        "id":0,
                        "type":1,
                        "twinkle":1,
                        "rect":[
                            0,0,
                            25,25,
                            50,50,
                            80, 80,
                            100,100
                        ],
                        "vel":[0,10],
                        "cat":"PEDESTRIAN"
                    }
                },
                {
                    "obj":{
                        "id":1,
                        "type":1,
                        "twinkle":1,
                        "rect":[
                            0,0,
                            100,100
                        ],
                        "vel":[0,10],
                        "cat":"PEDESTRIAN"
                    }
                }
            ]
        }
    }
}

设备上报解析 iva 下相关参数说明:

参数 说明
id 多个画框数据的索引序号
type 画框类型:
  • 0:智能画框
  • 1:只画 4 个角
twinkle 闪动设置:
  • 0 表示关闭(框一直在)
  • 1 表示开启(SDK 按传入频率闪烁)
rect 每两个数字表示一个点的坐标,所有点按顺时针顺序排列,SDK 会将这些点画成一个封闭的多边形,2 个点即可表示一个矩形框

SEI 协议中的 rect 坐标点通常是 App 通过 设备控制 DP 设置传递给设备的,坐标锚点数据约定协议:

  • 偶数位是横(x)坐标上的百分比分子。

  • 奇数位是纵(y)坐标上的百分比分子。

    数值最大为 100,奇偶成对出现。

视频画面渲染

视频解码后,可通过设置对画面渲染再处理,支持拉伸或缩放,左右或上下镜像,90、180、270 度旋转等。

接口说明

- (int)setDeviceFeatures:(NSDictionary *)features;

参数说明

参数 features 为字典类型,格式约定:

{
    "DecPostProcess":{
        "video":[
            {
                "restype":"4",
                "oldres":"944*1080",
                "newres":"1920*1080"
            },
            {
                "restype":"2",
                "oldres":"944*1080",
                "newres":"1920*1080"
            }
        ],
        "mirror":0,
        "rotation":2
    }
}
参数 说明
DecPostProcess 固定标识,必传
video 视频分辨率,数组,支持多组分辨率设置:
  • restype 为清晰度类型
  • oldres 为设备上报原始视频的大小
  • newres 期望拉伸或缩放后视频大小
mirror 镜像设置
  • 0 不变化
  • 1 左右镜像
  • 2 上下镜像
rotation 旋转角度
  • 0 不旋转
  • 1 旋转 90 度
  • 2 旋转 180 度
  • 3 旋转 270 度

设备能力

ThingSmartCameraAbility类,可以解析设备的配置信息,从而获取设备的一些基础能力。

属性 说明
defaultDefinition 实时视频播放的默认清晰度
videoNum 设备支持的码流数,
  • 值为 1 表示设备只支持一种清晰度,通过defaultDefinition 属性获取,而且无法切换清晰度
  • 值为 2 表示支持标清和高清两种清晰度
isSupportSpeaker 设备是否支持扬声器,如果设备支持扬声器,则可以开启讲话
isSupportPickup 设备是否支持拾音器,如果设备支持拾音器,则 App 端查看视频流时可以开启声音
rowData P2P config 原始数据

接口说明

根据设备数据模型创建设备能力类对象,需要在连接 P2P 之后调用。第一次 P2P 连接后,本地沙盒中会缓存此数据。

+ (instancetype)cameraAbilityWithDeviceModel:(ThingSmartDeviceModel *)deviceModel;