开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 102|回复: 1
收起左侧

[技术专题] 海康视频监控专用视频格式解码学习

[复制链接]
发表于 2026-8-1 19:31:53 | 显示全部楼层 |阅读模式   北京市北京市
最近在研究海康威视的视频监控,研究了不少资料,并借助AI,逐渐的搞明白了一些问题。
首先,海康的视频监控系统中下载的视频文件虽然是MP4格式的,但并不能正常用程序解码
搜索了资料才发现海康在标准视频格式的基础上,添加了自定义的一些东西,导致没法直接解码,需要通过海康官方的SDK才能处理
但是官方SDK有很多功能上的不足,对于需要进行视频图像提取并做进一步处理的场景来说,很不友好。
于是自己参考相关资料,利用AI给出的思路,写了一个简单的例程,可以分享给大家,大家可以参考一下,不喜勿喷。

这个例程可以通过纯字节分析的方法,提取海康视频文件的总帧数、I帧(关键帧)数、帧率、视频图像的宽度、高度,
还能够调用FFmpeg对首个关键帧进行解码并生成预览图。
需要注意的是,在使用这个例程之前,需要下载FFmpeg.exe,并修改程序中关于编码器的路径,否则是会报错的。
  
' 【1】解析视频参数,按照{ 0, 0, 1, 186 }
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]
' 调试输出 (“没有发现PACK标记,数据加入历史帧,不处理”, “data_history(long)=” + 到文本 (取字节集长度 (data_history)), “data_history_start=” + 到文本 (data_history_start))

判断 (num = 2)
' 找到1个标志字符,但前半段为上个片段的数据,需要加入前次历史帧数据并完成1帧的处理,处理完成后,后半段数据加入历史缓存,等待处理
' 1.处理头段数据
data_history = data_history + data_array [1]
当前帧.帧头位置 = data_history_start
当前帧.帧长度 = 取字节集长度 (data_history)
处理一帧数据 (data_history, 当前帧.帧类型, 当前帧.时间戳)
加入成员 (帧数据, 当前帧)
data_history = {  }
' 2.处理尾段数据
data_history = data_array [2]
data_history_start = 当前帧.帧头位置 + 当前帧.帧长度
' 调试输出 (data_history_start, 当前帧.帧头位置 + 当前帧.帧长度)
判断 (num > 2)
' 找到多个标志字符,第一片段数据,需要加入前次历史数据完成1帧的处理,中间(除了最后1个)数据逐个加入帧数据并处理,最后1个数据加入历史缓存等待后续处理
' 1.处理头段数据
data_history = data_history + data_array [1]
当前帧.帧头位置 = data_history_start
当前帧.帧长度 = 取字节集长度 (data_history)
处理一帧数据 (data_history, 当前帧.帧类型, 当前帧.时间戳)
加入成员 (帧数据, 当前帧)
data_history = {  }
' 2.处理中段数据
变量循环首 (2, num - 1, 1, i)
' 获取帧头位置
当前帧.帧头位置 = 当前帧.帧头位置 + 当前帧.帧长度
当前帧.帧长度 = 取字节集长度 (data_array [i]) + 4
处理一帧数据 (data_array [i], 当前帧.帧类型, 当前帧.时间戳)
加入成员 (帧数据, 当前帧)
变量循环尾 ()
' 3.处理尾端数据
data_history = data_array [num]
data_history_start = 当前帧.帧头位置 + 当前帧.帧长度



读写位置 = 读写位置 + data_buff_long
' ps = 四舍五入 (读写位置 ÷ long × 100, 0)
. ' 如果真 (ps ≠ ps_h)
' 调试输出 (ps)
' ps_h = ps

判断循环尾 ()
' 结束之前,如果data_history不为空,则处理最后一帧数据
如果真 (data_history ≠ {  })
当前帧.帧头位置 = 当前帧.帧头位置 + 当前帧.帧长度
当前帧.帧长度 = 取字节集长度 (data_history) + 4
处理一帧数据 (data_history, 当前帧.帧类型, 当前帧.时间戳)
加入成员 (帧数据, 当前帧)
data_history = {  }

' 【2】统计帧数
处理列表 [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



变量循环尾 ()
' 【3】计算帧率
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)
' 【4】解码首关键帧图像并得出宽高
移动读写位置 (p, #文件首, 帧数据 [iframe1_id].帧头位置)
data_history = 读入字节集 (p, 帧数据 [iframe1_id].帧长度)
关闭文件 (p)
取视频首关键帧图像 (data_history, id, 处理列表 [id].首关键帧图像, 处理列表 [id].宽度, 处理列表 [id].高度)

取视频基础信息.e

34.45 KB, 下载次数: 1, 下载积分: 精币 -2 枚


签到天数: 8 天

发表于 4 天前 | 显示全部楼层   湖北省武汉市
这个可以
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备2025452707号) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表