美文网首页海康
海康威视SDK视频录制及强制I帧操作

海康威视SDK视频录制及强制I帧操作

作者: 木人呆呆 | 来源:发表于2021-12-16 18:37 被阅读0次

    一、NET_DVR_SaveRealData方法

    使用下面方法可以实现视频录像功能。

        private HCNetSDK sdk = HCNetSDK.INSTANCE;
        sdk.NET_DVR_SaveRealData_V30(cameraInfo.getKey(), file.getPath() + "/" + fileName + ".mp4")
    

    该方法有个问题,视频可以录制,但是不能被前端页面直接加载播放,因为视频编码格式问题,虽然可以用FFMPEG工具进行格式转化,但是引入第三方的库,无疑会使代码的维护性降低。

    FFMPEG工具 地址 提取码 zc14
    使用FFmpeg进行转换的方法如下:

    ffmpeg -i  in.mp4  out.mp4
    

    该方法网络上有大量的帖子,我直接放连接过来,可以自行前往学习
    大牛博客地址

    二、NET_DVR_SaveRealData_V30方法

    这个方法是问海康的工程师得到的,跟海康的工程师交流还是挺美好的,工程师很耐心,直到自己的问题得到解答,代码测试通过,所以还是必须给点个赞。

    附上该方法的SDK文档

    NET_DVR_SaveRealData_V30 SDK

    按照SDK文档的说明,第二个参数传2,就可以了

      //预览成功后 调用接口使视频资源保存到文件中
         if (!sdk.NET_DVR_SaveRealData_V30(cameraInfo.getKey(), 2,file.getPath() + "/" + fileName + ".mp4")) {
             log.error("保存视频文件到文件夹失败 错误码为:  " + sdk.NET_DVR_GetLastError());
             logoutHIK(cameraInfo);
             return;
         }
    

    到这里会发现一个问题,官方下载的SDK HCNetSDK.java文件中没有NET_DVR_SaveRealData_V30这个方法,尴尬了。
    这就是官方SDK的坑点,SDK中有,但是HCNetSDK.java文件中没有,好多同学可能都会懵一下,这里可以将SDK中的方法直接复制进HCNetSDK.java文件即可。SDK是按照C语言来描述的,JAVA要做响应的适配改变。

     boolean  NET_DVR_SaveRealData_V30(NativeLong lRealHandle,int STREAM_TYPE,String sFileName);
    

    OK,到此视频已经可以存储,播放也正常,但是你又会发现一个新的问题,就是保存的视频,设定1分钟,但是只有51秒 ,52秒,57秒等,就是没有1分钟的,甚至59秒的都很少,如果要求不那么高还好,到这里就可以结束了,如果要求的高,那就得做出处理了。

    三、强制I帧

    这里面其实是有一个 I帧的定义

    录像数据解码播放必须从I帧开始,而客户端录像的时候开始时间点不一定是I帧,比如帧率25fps、I帧间隔100帧的情况下,每4秒才一个I帧,录像播放可能存在1~4秒的延时,所以录像的时候可以强制设备生成一个I帧。
    NET_DVR_MakeKeyFrame强制主码流生成一个I帧,NET_DVR_MakeKeyFrameSub强制子码流生成一个I帧,z这两个是老的接口。
    后来因为设备不只有主码流和子码流,还有三码流、虚拟码流等,因此增加了NET_DVR_RemoteControl(命令:NET_DVR_MAKE_I_FRAME)接口,兼容前面的两个接口,输入参数NET_DVR_I_FRAME中byStreamType表示码流类型。建议使用该接口。

    可以看到,如果I帧没有到,也是不录视频的,但是I帧一般会慢几秒中,所以视频长度不够自己配置的长度

    需要用到NET_DVR_RemoteControl 这个方法,会发现 HCNetSDK.java文件中并没有NET_DVR_RemoteControl 这个方法,继续添加上。

    附上NET_DVR_RemoteControl 的SDK NET_DVR_RemoteControl SDK

    同样,在 HCNetSDK.java文件中增加这个方法(根据java做了语法转换,如果不好转,请参考原HCNetSDK.java文件中的数据类型)

     boolean NET_DVR_RemoteControl(NativeLong lUserID, int dwCommand, Pointer pointer, int dwInBufferSize);
    

    官方SDK简直了,有些方法没有,就连结构体也没有,都需要自己新增,没办法,谁让咱要用人家的产品么
    lpInBuffer参数对应结构体 NET_DVR_I_FRAME
    看SDK手册 NET_DVR_I_FRAME 结构体的官方文档

    NET_DVR_I_FRAME SDK
    //强制I帧参数结构体。
    public static class NET_DVR_I_FRAME extends Structure{
        public int dwSize;
        public byte[] sStreamID = new byte[32];  //流IDs    SDK 中对  STREAM_ID_LEN进行了定义,赋值32
        public int dwChannel;//通道号
        public byte byStreamType; //码流类型:0-主码流,1-子码流,2-码流3,3-虚拟码流,以此类推
        public byte[] byRes = new byte[63];  //保留,置为0    按照SDK要求进行对应赋值
    }
    
    //新建结构体对象
            HCNetSDK.NET_DVR_I_FRAME netDvrIFrame = new HCNetSDK.NET_DVR_I_FRAME();   //新建结构体对象
            netDvrIFrame.read();
            netDvrIFrame.dwChannel = 1;          //因为上文代码中设置了通道号,按照上文中的设置
            netDvrIFrame.byStreamType = 0;
            netDvrIFrame.dwSize = netDvrIFrame.size();
            netDvrIFrame.write();
    
            if(!sdk.NET_DVR_RemoteControl(cameraInfo.getUserId(),3402,netDvrIFrame.getPointer(),netDvrIFrame.dwSize)){
                log.error("强制I帧 错误码为:  " + sdk.NET_DVR_GetLastError());
            }
    

    在每次录像之前,对I帧进行强制设置,可以及时录像,经过测试基本上按照配置的时间进行录制,比如1分钟就是1分钟,偶尔有59秒的情况,提到的问题已经大大的修复了。经次一轮,对SDK的使用也有了更深的了解。自己踩过的坑,也记录下来,也让别人能很好的使用官方的SDK。

    最后附上程序,欢迎下载传阅,另外还有海康工程师给的有更全结构体的HCNetSDK.java文件
    百度网盘 链接:https://pan.baidu.com/s/1JEKvEnb5wTDtmNqlNsKvLg
    提取码:x4bj

    相关文章

      网友评论

        本文标题:海康威视SDK视频录制及强制I帧操作

        本文链接:https://www.haomeiwen.com/subject/inuvfrtx.html