天津网站建设网页设计公司,中山做网站哪家公司好,深圳网站建设多少钱,域名解析器文章目录 海康威视摄像机和录像机的监控与回放1、海康威视监控设备简介1.1、摄像机二次开发1.1.1#xff1a;协议选择 1.2#xff1a;web集成1.2#xff1a;标准协议对接1.2.1#xff1a;ffmpeg软件转流1.2.2#xff1a;开源监控软件shinobi1.2.2.1 安装使用1.2.2.2 shino… 文章目录 海康威视摄像机和录像机的监控与回放1、海康威视监控设备简介1.1、摄像机二次开发1.1.1协议选择 1.2web集成1.2标准协议对接1.2.1ffmpeg软件转流1.2.2开源监控软件shinobi1.2.2.1 安装使用1.2.2.2 shinobi API使用 1.2.3使用nginx的RTMP模块1windows下实现rtsp流转rtmp和http协议的flv流媒体实现vue播放 1.3海康SDK对接1.3.1springboot集成SDK提供接口调用 2、各种流媒体协议介绍2.1流媒体协议介绍2.1.1RTSP (实时流传输协议)2.1.2RTMP (实时消息协议)2.1.3FLVFlash Video2.1.4HLS (HTTP Live Streaming) 2.2流媒体协议选择与适用场景2.3推流和拉流2.3.1推流2.3.2拉流 海康威视摄像机和录像机的监控与回放
1、海康威视监控设备简介
由于我们项目需要引入监控所有作为一个小白特此研究一下将自己的实操分享发给大家。 海康的监控设备主要是摄像机(IPC)搭配录像机NVR可以实现对监控的预览、回放、布放、告警等功能。
海康威视本身提供了非常多的方式可以进行查看监控和回放 1、比如iVMS-4200客户端、直接在浏览器输入摄像机的ip、萤石云。 2、合作伙伴后台服务(付费的)实现标准协议rtsp、hls、http-flv、rtmp取流
海康威视设备搜索搜素局域网内在线的摄像机设备 海康威视官网工具包
由于我们需要集成到自己的系统中所以需要二次开发后集成到自己的系统中 且不想出钱买海康的后台管理平台所以自己实现。
1.1、摄像机二次开发
主要流程是提供前端支持的协议进行播放主要包括前端解决方案和后端解决方案。 若只是播放回放等功能可以使用海康提供的前端web demo和后端解决方案
1、前端web集成 2、后端集成方案
2.1 标准协议对接可实现预览回放需自己存放数据2.2 海康SDK对接可调用sdk实现预览和调用录像机数据回放
1.1.1协议选择
**需求**想要二次开发在自己的系统浏览器页面实现监控的播放需要集成播放插件。 **问题**随着IE、Chrome、Edge等主流浏览器对flash播放插件的停止更新目前二次开发时应该要摒弃rtmp协议采用HLS、HTTP-FLV、WebRTC、WebSocket来传输直播视频流。各种流媒体协议介绍参考第二章节。浏览器原生不支持rtsp协议取流。 总结如下
RTSP浏览器原生不支持rtsp协议取流需通过下载安装rtsp协议的取流插件实现视频取流业务
HTTP-FLV在播放首屏、播放延迟方面表现较好。但不支持IOS safari
HLS将浏览器缓存视频分片后播放流畅性很好但存在3-4s左右的延时且录像回放功能对存储要求高
RTMPAdobe公司2021年已不再更新和分发Flash不推荐浏览器视频播放采用此协议前端的Video控件标签支持HLS协议播放经测试确实支持m3u8的播放。主要支持,几种视频格式m3u8ogg, mp4, webm。MPEG4 带有 H.264 视频编码和 AAC 音频编码的 MPEG 4 文件
协议选择浏览器原生不支持rtsp协议取流所以需要进行协议转换比如选择HLS协议
1.2web集成
海康开发平台web集成文档 方案中建议一个tab页只启动一个播放插件暂没有尝试播放多个监控待前端测试完成后补充该部分
1.2标准协议对接
可以实现rtmp到flv、hls等协议转换
1.2.1ffmpeg软件转流
1、安装ffmpeg ffmpeg官网 2、使用命令转流 -hls_time 10 代表每个片段的时长10秒 -hls_list_size 决定保留的ts片段个数。0代表全部
ffmpeg -i rtsp://用户名:密码IP地址:554/Streaming/Channels/101 -c copy -hls_time 10 -hls_list_size 0 -hls_flags delete_segmentsprogram_date_time -f hls G:\\yd\\word\\ip\\output.m3u83、播放该G:\yd\word\ip\output.m3u8流媒体文件即可。比如使用ffmpeg自带的播放器ffplay或者vlc播放器
ffplay G:\\yd\\word\\ip\\output.m3u84、优化。生产上可能有多个监控可以使用脚本实现批量转换
#!/bin/bash# 定义摄像头列表
CAMERAS(rtsp://admin:yd2024192.168.2.64:554/Streaming/Channels/101rtsp://admin:yd2024192.168.2.65:554/Streaming/Channels/101# 添加更多摄像头
)# 输出目录
OUTPUT_DIRG:\\yd\\word\\ip# 保留片段数量
RETAIN_COUNT36# 定期清理旧片段
cleanup_old_segments() {for i in ${!CAMERAS[]}; doCAM_ID$((i 1))M3U8_FILE$OUTPUT_DIR/camera_$CAM_ID.m3u8# 获取M3U8文件中的所有TS文件TS_FILES$(grep -oP #EXT-X-KEY:.*\n#EXTINF:[0-9.],\n(.*?)\n $M3U8_FILE | cut -d\n -f3)# 删除多余的TS文件while [ $(echo $TS_FILES | wc -l) -gt $RETAIN_COUNT ]; doOLDEST_TS$(echo $TS_FILES | head -n1)rm $OUTPUT_DIR/$OLDEST_TSTS_FILES$(echo $TS_FILES | tail -n 2)done# 更新M3U8文件sed -i /#EXT-X-ENDLIST/d $M3U8_FILEecho #EXT-X-ENDLIST $M3U8_FILEdone
}# 启动FFmpeg进程
for i in ${!CAMERAS[]}; doCAM_ID$((i 1))OUTPUT_FILE$OUTPUT_DIR/camera_$CAM_ID.m3u8# 启动FFmpeg进程ffmpeg -i ${CAMERAS[$i]} \-c copy -map 0:v:0 -map 0:a:0 -hls_time 10 -hls_list_size 5 \-hls_flags delete_segmentsprogram_date_time \-f hls $OUTPUT_FILE
done# 定期清理旧片段
cleanup_old_segments# 设置定时任务
(crontab -l ; echo */5 * * * * /path/to/cleanup_old_segments.sh) | crontab -1.2.2开源监控软件shinobi
shinobi官网
1.2.2.1 安装使用
1、安装支持docker安装
docker run -d --nameshinobi1 --shm-size2048m -p 8080:8080 registry.gitlab.com/shinobi-systems/shinobi:latest首次登录管理员http://ip:8080/super# 后续登录普通账号http://ip:8080/
2、添加摄像头。每个摄像头默认会生成一个唯一ID默认转为HLS协议
每个监控默认会生成唯一ID 标签指定的分组标签一样的会分到同一个分组 输入监控的URL。 默认的海康威视或者大华等有自己固定的URL格式 比如海康rtsp://用户名:密码IP地址:554/Streaming/Channels/101
3、查看监控 查看监控时若无法播放确保涉摄像头设置中的视频编码格式是H.264海康有些会是H.265导致无法查看黑屏 4、查看Stream流复制stream流地址。
利用shinobi可以播放rtsp流并可以将其转为m3u8的流。复制m3u8地址接口播放下面是用vlc播放器播放的 可以看到监控 4、缺点其stream流的地址会变化有时会导致前面的stream流失效无法查看监控内容。那么有没有方法固定Stream url。肯定是有的可以通过API实现。
stream流URL的格式http://xxx.xxx.xxx.xxx/[API KEY]/hls/[GROUP KEY]/[MONITOR ID]/s.m3u8其实是api key会自动刷新客户端断开连接15分钟就刷新了。我们只需要创建自己的API KEY即可
1.2.2.2 shinobi API使用
shinobi的整个页面都是调用API获取的比如获取监控获取stream流信息等。所以我们可以借助api实现自己的系统和页面达到嵌入自己系统的目的 shinobi API文档
1创建秘钥 创建秘钥并给权限后就可以通过替换url中的key实现获取监控获取stream流信息 比如旧的是默认的http://localhost:8091/35758c68d976c08a4b6a0f25ceab61b5/hls/HFiE3MlIHj/ZRjzDq8WKU/s.m3u8 替换其中的35758c68d976c08a4b6a0f25ceab61b5为自己新建的key即可实现固定URL2获取监控http://xxx.xxx.xxx.xxx/[API KEY]/monitor/[GROUP KEY] 3 获取流
比如HLS流http://xxx.xxx.xxx.xxx/[API KEY]/hls/[GROUP KEY]/[MONITOR ID]/s.m3u84 获取视频 获取视频的前提是摄像头的设置模式是记录
http://xxx.xxx.xxx.xxx/[API KEY]/videos/[GROUP KEY]比如浏览器访问
http://localhost:8091/35758c68d976c08a4b6a0f25ceab61b5/videos/HFiE3MlIHj/ZRjzDq8WKU/2024-09-20T03-00-01.mp4即可浏览器看到视频
1.2.3使用nginx的RTMP模块
nginx默认不带RTMP模块的需要下载和nginx源码一起自行编译。
1windows下实现rtsp流转rtmp和http协议的flv流媒体实现vue播放
1、安裝nginx、ffmpeg 下载nginx下载链接: http://nginx-win.ecsds.eu/download/nginx 1.7.11.3 Gryphon.zip下载完成后解压 将解压后的目录去除空格2、下载/nginx-rtmp-module流媒体转换module此module非默认的需要额外下载 下载地址https://github.com/arut/nginx-rtmp-module/3、下载后解压放到nginx-1.7.11.3-Gryphon目录下并将包名改为nginx-rtmp-module
修改配置文件 nginx-win.conf配置如下
worker_processes 1;events {worker_connections 1024;
}rtmp {server {listen 1935;chunk_size 4096;application live {live on;hls on;hls_path G:/yd/word/nginx-1.7.11.3-Gryphon/hls; # 使用反斜杠或正斜杠hls_fragment 5s;}}
}http {server {listen 880;server_name localhost;location / {root /usr/share/nginx/html;index index.html index.htm;}location /hls/ {types {application/vnd.apple.mpegurl m3u8;video/MP2T ts;}add_header Cache-Control no-cache;alias G:/yd/word/nginx-1.7.11.3-Gryphon/hls/; # 使用反斜杠或正斜杠}}
}
4、启动和停止nginx 启动nginxnginx -c conf/nginx-win.conf 停止taskkill /f /t /im nginx.exe
4、安装ffmpeg实现推流到nginx 你可以使用FFmpeg或其他直播软件推送流到Nginx RTMP服务器
ffmpeg -i rtsp://admin:password192.168.2.64:554/Streaming/Channels/101 -c copy -f flv rtmp://localhost:1935/live/test5、获取flv流播放测试 在客户端你可以使用VLC播放器或其他支持RTMP协议的播放器来观看直播 vlc播放器测试
ffplay拉流播放测试ffplay.exe rtmp://192.168.2.4:1935/live/test 说明推送到rtmp没问题
rtmp协议url rtmp://192.168.2.4:1935/live/test
http协议urlhttp://localhost:880/hls/test.m3u8总结比shinobi有固定的url
1.3海康SDK对接
海康硬件设备对接SDK 区分了不同的操作系统里面有不同代码语言的demo。
1.3.1springboot集成SDK提供接口调用 RestController
RequestMapping(/countryside/alarms)
public class HKSdkController implements Runnable {private final HCNetSDKServiceImpl hcNetSDKService new HCNetSDKServiceImpl();private volatile boolean running true;private Thread listenerThread;Overridepublic void run() {while (running) {// 监听并处理报警数据Alarm.startAlarm();}}
//使用 PostConstruct注解实现程序启动就监听摄像头的告警信息PostConstructpublic void startAlarm() {listenerThread new Thread(this);listenerThread.start();}GetMapping(value /latest, produces MediaType.APPLICATION_JSON_VALUE)Operation(summary 获取最新报警信息)PermitAllpublic ListAlarmData getLatestAlarms() {return AlarmDataHandler.getLatestAlarms();}private static final MapString, Video videoMap new ConcurrentHashMap();GetMapping(/realPlay)PermitAllpublic String realPlay(RequestParam(userID) int userID,RequestParam(channelNo) int channelNo, RequestParam(channelNo) int ipNo) {if (!hcNetSDKService.initializeSDK()) {return 初始化失败;}String ip getIpFromChannelNo(ipNo);// 使用找到的IP地址进行连接String key ip : channelNo;Video video videoMap.get(key);if (video null) {video new Video(userID, channelNo, ip);videoMap.put(key, video);}video.startPreview();return 取流成功;}private String getIpFromChannelNo(int ipNo) {// 这里应该是从数据库或配置文件中获取IP地址// 示例return 192.168.1. channelNo;return 192.168.2.64; // 假设所有摄像头都在同一网段}PostMapping(/stopAlarm)Operation(summary 停止报警监听)PermitAllpublic void stopAlarm() {running false;if (listenerThread ! null) {listenerThread.interrupt();}}
}下面是service进行了HCNETSDK的初始化类似于demo里client中的代码其中的video是demo中的
public class HCNetSDKServiceImpl {private static HCNetSDK hCNetSDK null;private static PlayCtrl playControl null;private static boolean isInitialized false;public boolean initializeSDK() {if (!isInitialized) {if (!createSDKInstance()) {return false;}if (!createPlayInstance()) {return false;}if (osSelect.isLinux()) {loadComponentLibraries();}boolean initSuc hCNetSDK.NET_DVR_Init();if (!initSuc) {return false;}setExceptionCallback();setLogFile();isInitialized true;}return true;}public void cleanup() {if (isInitialized hCNetSDK ! null) {hCNetSDK.NET_DVR_Cleanup();isInitialized false;}}public static HCNetSDK getHCNetSDK() {return hCNetSDK;}private boolean createSDKInstance() {if (hCNetSDK null) {synchronized (HCNetSDK.class) {String strDllPath ;try {if (osSelect.isWindows()) {strDllPath G:\\yd\\code\\gitlab\\crc-digital-countryside-cloud\\crc-module-countryside\\crc-module-countryside-biz\\src\\main\\resources\\META-INF\\lib\\HCNetSDK.dll;} else if (osSelect.isLinux()) {strDllPath System.getProperty(user.dir) /lib/libhcnetsdk.so;}hCNetSDK (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);} catch (Exception ex) {System.out.println(loadLibrary: strDllPath Error: ex.getMessage());return false;}}}return true;}private boolean createPlayInstance() {if (playControl null) {synchronized (PlayCtrl.class) {String strPlayPath ;try {if (osSelect.isWindows()) {strPlayPath G:\\yd\\code\\gitlab\\crc-digital-countryside-cloud\\crc-module-countryside\\crc-module-countryside-biz\\src\\main\\resources\\META-INF\\lib\\PlayCtrl.dll;} else if (osSelect.isLinux()) {strPlayPath System.getProperty(user.dir) /lib/libPlayCtrl.so;}playControl (PlayCtrl) Native.loadLibrary(strPlayPath, PlayCtrl.class);} catch (Exception ex) {System.out.println(loadLibrary: strPlayPath Error: ex.getMessage());return false;}}}return true;}private void loadComponentLibraries() {HCNetSDK.BYTE_ARRAY ptrByteArray1 new HCNetSDK.BYTE_ARRAY(256);HCNetSDK.BYTE_ARRAY ptrByteArray2 new HCNetSDK.BYTE_ARRAY(256);String strPath1 System.getProperty(user.dir) /lib/libcrypto.so.1.1;String strPath2 System.getProperty(user.dir) /lib/libssl.so.1.1;System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());ptrByteArray1.write();hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());ptrByteArray2.write();hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());String strPathCom System.getProperty(user.dir) /lib/;HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());struComPath.write();hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());}private void setExceptionCallback() {FExceptionCallBack_Imp fExceptionCallBack new FExceptionCallBack_Imp();Pointer pUser null;if (!hCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, 0, fExceptionCallBack, pUser)) {System.out.println(设置异常消息回调失败);} else {System.out.println(设置异常消息回调成功);}}private void setLogFile() {hCNetSDK.NET_DVR_SetLogToFile(3, ./sdkLog, false);}static class FExceptionCallBack_Imp implements HCNetSDK.FExceptionCallBack {public void invoke(int dwType, int lUserID, int lHandle, Pointer pUser) {System.out.println(异常事件类型: dwType);return;}}}video核心代码 private int userID;private int channelNo;private String ip;private HCNetSDKServiceImpl hCNetSDKService new HCNetSDKServiceImpl();static FRealDataCallBack fRealDataCallBack;//预览回调函数实现public void startPreview() {if (userID -1) {System.out.println(请先注册);return;}HCNetSDK hcNetSDK hCNetSDKService.getHCNetSDK();HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo new HCNetSDK.NET_DVR_DEVICEINFO_V30();int lUserID hcNetSDK.NET_DVR_Login_V30(ip, (short) 8000, admin, yd2024.., m_strDeviceInfo);if ((lUserID -1) || (lUserID 0xFFFFFFFF)) {System.out.println(登录失败错误码为 hCNetSDK.NET_DVR_GetLastError());return;}HCNetSDK.NET_DVR_PREVIEWINFO strClientInfo new HCNetSDK.NET_DVR_PREVIEWINFO();strClientInfo.read();strClientInfo.hPlayWnd 0; // 窗口句柄从回调取流不显示一般设置为空strClientInfo.lChannel channelNo; // 通道号strClientInfo.dwStreamType 0; // 0-主码流1-子码流2-三码流3-虚拟码流以此类推strClientInfo.dwLinkMode 0; // 连接方式0- TCP方式strClientInfo.bBlocked 1;strClientInfo.byProtoType 0;strClientInfo.write();// 回调函数定义必须是全局的if (fRealDataCallBack null) {fRealDataCallBack new FRealDataCallBack();}// 开启预览lPlay hcNetSDK.NET_DVR_RealPlay_V40(userID, strClientInfo, fRealDataCallBack, null);if (lPlay -1) {int iErr hcNetSDK.NET_DVR_GetLastError();System.out.println(取流失败: iErr);return;}System.out.println(取流成功);// 保存视频到文件 saveVideoToFile();String path .\\savevideo.mp4;Boolean bSaveVideo hcNetSDK.NET_DVR_SaveRealData_V30(lPlay, 0x2, path);if (bSaveVideo false) {int iErr hcNetSDK.NET_DVR_GetLastError();System.out.println(NET_DVR_SaveRealData_V30 failed iErr);return;}System.out.println(NET_DVR_SaveRealData_V30 suss);try {Thread.sleep(10000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}Boolean bStopSaveVideo hcNetSDK.NET_DVR_StopSaveRealData(lPlay);if (bStopSaveVideo false) {int iErr hCNetSDK.NET_DVR_GetLastError();System.out.println(NET_DVR_StopSaveRealData failed iErr);return;}System.out.println(NET_DVR_StopSaveRealData suss);if (lPlay 0) {if (hCNetSDK.NET_DVR_StopRealPlay(lPlay)) {System.out.println(停止预览成功);return;}}//sendVideoData(pBuffer, dwBufSize);}
在这里插入代码片2、各种流媒体协议介绍
常见的流媒体协议包括RTSP、RTMP、HLS、FLV等它们在不同的应用场景中提供了各自的优势和 特性。
2.1流媒体协议介绍 2.1.1RTSP (实时流传输协议)
RTSPReal-Time Streaming ProtocolRTSP本身并不传送数据而仅仅是是媒体播放器能控制多媒体流的传送暂停播放快进快退等。实际媒体数据的传输可以用RTP协议或其他专用协议。 RTSP以客户-服务器方式工作它是一个应用层的多媒体播放控制协议。它和Http协议有些相似但它不像Http而是有状态的而且可以在TCP和UDP上传输。 默认端口554。2.1.2RTMP (实时消息协议)
RTMPReal-Time Messaging Protocol是Adobe开发的用于实时视频和音频流传输的协议。它最初是为Flash Video应用设计的但现已被广泛用于各种直播和点播服务如YouTube、Twitch等
2.1.3FLVFlash Video
格式是一种面向Flash平台的流媒体格式。它被广泛用于Adobe Flash Player的内容播放尤其在早期的互联网视频应用中非常流行。
2.1.4HLS (HTTP Live Streaming)
HLSHTTP Live Streaming是一种通过标准HTTP协议动态传输实时音视频流的技术。它将视频和音频分段并使用HTTP进行传输使得在不同的网络环境下都能提供流畅、质量可适应的流媒体体验。 hls存储的是.ts格式的视频片段可以使用http协议存储成m3u8格式的视频 m3u8文件是动态更新的里面存放了各种的.ts格式的视频片段。获取播放的视频流并不是直接播放.m3u8文件本身而是通过.m3u8文件来索引和播放一系列的TSTransport Stream视频片段。.m3u8文件是一个文本文件它包含了指向这些视频片段的链接列表以及可能的其他元数据如带宽信息。HLS播放器如Hls.js会首先下载.m3u8文件然后根据文件中的列表逐个下载TS片段并将它们拼接起来播放
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXTINF:10.000,
http://username:passwordyourserver.com/path/to/segment0.ts
#EXTINF:10.000,
http://username:passwordyourserver.com/path/to/segment1.ts
...视频文件类型.m3u8
2.2流媒体协议选择与适用场景
在选择流媒体协议时应考虑以下几个因素
传输速度与稳定性对于实时性要求高的场景RTMP与RTSP可能更为合适。 平台支持如果目标是跨平台应用HLS因其基于HTTP的优势而更受欢迎。 压缩效率FLV在Flash平台上的使用历史中表现出色尤其在对压缩效率有较高要求的场景下。 版权保护与防盗链HLS提供较好的版权保护机制适合版权内容的分发。 流媒体协议的实现与设置 开发工具对于开发者来说使用如Python、Node.js、Java等通用编程语言搭配专门的流媒体框架如FFmpeg、Nginx的RTMP模块可以快速搭建流媒体服务。 其中的视频格式是支持的摄像机的视频编码格式注意选择协议时进行摄像机的视频编码格式的设置
2.3推流和拉流 2.3.1推流
将直播的内容推送至服务器的过程其实就是将现场的视频信号传到网络的过程。“推流”对网络要求比较高如果网络不稳定直播效果就会很差观众观看直播时就会发生卡顿等现象观看体验很是糟糕。要想用于推流还必须把音视频数据使用传输协议进行封装变成流数据。常用的流传输协议有 RTSP、RTMP、HLS 等使用 RTMP 传输的延时通常在 1–3 秒对于手机直播这种实时性要求非常高的场景RTMP 也成为手机直播中最常用的流传输协议。最后通过一定的 QoS 算法将音视频流数据推送到网络端并通过 CDN 进行分发。
2.3.2拉流
拉流指服务器已有直播内容用指定地址进行拉取的过程。即是指服务器里面有流媒体视频文件这些视频文件根据不同的网络协议类型如 RTMP、RTSP、HTTP 等被读取的过程称之为拉流我们日常观看视频和直播就是一个拉流的过程。