|
|

最近在研究海康威视的视频监控,研究了不少资料,并借助AI,逐渐的搞明白了一些问题。
首先,海康的视频监控系统中下载的视频文件虽然是MP4格式的,但并不能正常用程序解码
搜索了资料才发现海康在标准视频格式的基础上,添加了自定义的一些东西,导致没法直接解码,需要通过海康官方的SDK才能处理
但是官方SDK有很多功能上的不足,对于需要进行视频图像提取并做进一步处理的场景来说,很不友好。
于是自己参考相关资料,利用AI给出的思路,写了一个简单的例程,可以分享给大家,大家可以参考一下,不喜勿喷。
这个例程可以通过纯字节分析的方法,提取海康视频文件的总帧数、I帧(关键帧)数、帧率、视频图像的宽度、高度,
还能够调用FFmpeg对首个关键帧进行解码并生成预览图。
需要注意的是,在使用这个例程之前,需要下载FFmpeg.exe,并修改程序中关于编码器的路径,否则是会报错的。
p = 打开文件 (处理列表 [id ].视频路径, #读入, #禁止写 )long = 取文件长度 (p )移到文件首 (p )读写位置 = 1 data_history_start = 1 连续赋值 ({ }, data_buff, data_history )清除数组 (帧数据 ) 判断循环首 (是否在文件尾 (p, 假) = 假) data_buff = 读入字节集 (p, #缓存大小 ) data_buff_long = 取字节集长度 (data_buff ) data_array = 分割字节集 (data_buff, { 0, 0, 1, 186 }, ) num = 取数组成员数 (data_array ) 如果真 (num ≤ 0 ) 到循环尾 ()   判断 (num = 1 )   data_history = data_history + data_array [1 ]    判断 (num = 2 )    data_history = data_history + data_array [1 ]  当前帧.帧头位置 = data_history_start   当前帧.帧长度 = 取字节集长度 (data_history ) 处理一帧数据 (data_history, 当前帧.帧类型, 当前帧.时间戳 ) 加入成员 (帧数据, 当前帧 )  data_history = { }   data_history = data_array [2 ]  data_history_start = 当前帧.帧头位置 + 当前帧.帧长度   判断 (num > 2 )    data_history = data_history + data_array [1 ]  当前帧.帧头位置 = data_history_start   当前帧.帧长度 = 取字节集长度 (data_history ) 处理一帧数据 (data_history, 当前帧.帧类型, 当前帧.时间戳 ) 加入成员 (帧数据, 当前帧 )  data_history = { }   变量循环首 (2, num - 1, 1, i )     当前帧.帧头位置 = 当前帧.帧头位置 + 当前帧.帧长度    当前帧.帧长度 = 取字节集长度 (data_array [i ]) + 4   处理一帧数据 (data_array [i ], 当前帧.帧类型, 当前帧.时间戳 )  加入成员 (帧数据, 当前帧 )  变量循环尾 ()   data_history = data_array [num ]  data_history_start = 当前帧.帧头位置 + 当前帧.帧长度        读写位置 = 读写位置 + data_buff_long  .  判断循环尾 () 如果真 (data_history ≠ { }) 当前帧.帧头位置 = 当前帧.帧头位置 + 当前帧.帧长度  当前帧.帧长度 = 取字节集长度 (data_history ) + 4 处理一帧数据 (data_history, 当前帧.帧类型, 当前帧.时间戳 ) 加入成员 (帧数据, 当前帧 ) data_history = { } 处理列表 [id ].总帧数 = 0 处理列表 [id ].I帧数 = 0 num = 取数组成员数 (帧数据 ) 变量循环首 (1, num, 1, i ) 判断 (帧数据 [i ].帧类型 = 1 )  处理列表 [id ].总帧数 = 处理列表 [id ].总帧数 + 1   处理列表 [id ].I帧数 = 处理列表 [id ].I帧数 + 1  判断 (帧数据 [i ].帧类型 = 2 )  处理列表 [id ].总帧数 = 处理列表 [id ].总帧数 + 1       变量循环尾 () iframe1_id = 0 iframe2_id = 0 变量循环首 (1, num, 1, i ) 如果真 (帧数据 [i ].帧类型 = 1 )  如果真 (iframe1_id = 0 )   iframe1_id = i   到循环尾 ()  如果真 (iframe1_id ≠ 0 且 iframe2_id = 0 )   iframe2_id = i   跳出循环 ()     变量循环尾 ()处理列表 [id ].帧率 = 四舍五入 ( (iframe2_id - iframe1_id ) ÷ (帧数据 [iframe2_id ].时间戳 - 帧数据 [iframe1_id ].时间戳 ), 0 ) 移动读写位置 (p, #文件首, 帧数据 [iframe1_id ].帧头位置 )data_history = 读入字节集 (p, 帧数据 [iframe1_id ].帧长度 )关闭文件 (p )取视频首关键帧图像 (data_history, id, 处理列表 [id ].首关键帧图像, 处理列表 [id ].宽度, 处理列表 [id ].高度 )
|
|