【海康威视】-Java读取监控摄像头实时帧

目录

1、基于JavaCV

1.1、pom依赖

1.2、读取帧Frame

1.3、转换BufferedImage

1.4、完整代码

2、基于Ffmpeg命令

2.1、ffmpeg命令

2.2、读取帧

2.3、转换BufferedImage

2.4、完整代码


1、基于JavaCV

1.1、pom依赖

<dependency><groupId>org.bytedeco</groupId><artifactId>javacv</artifactId><version>1.5.8</version></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>javacpp</artifactId><version>1.5.8</version></dependency><!-- 此版本中主要兼容linux和windows系统,如需兼容其他系统平台,请引入对应依赖即可 --><dependency><groupId>org.bytedeco</groupId><artifactId>opencv</artifactId><version>4.6.0-1.5.8</version><classifier>linux-x86_64</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>opencv</artifactId><version>4.6.0-1.5.8</version><classifier>windows-x86_64</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>openblas</artifactId><version>0.3.21-1.5.8</version><classifier>linux-x86_64</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>openblas</artifactId><version>0.3.21-1.5.8</version><classifier>windows-x86_64</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>ffmpeg</artifactId><version>5.1.2-1.5.8</version><classifier>linux-x86_64</classifier></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>ffmpeg</artifactId><version>5.1.2-1.5.8</version><classifier>windows-x86_64</classifier></dependency>

1.2、读取帧Frame

FFmpegFrameGrabber frameGrabber = null;
        
try {
    frameGrabber = new FFmpegFrameGrabber(rtsp);
    frameGrabber.setOption("rtsp_transport", "tcp");
    frameGrabber.startUnsafe();
    int retry = 0;
    while (this.captureDevice.getStatus()) {
        Frame frame = frameGrabber.grabImage();
        // long frameNumber = frameGrabber.getFrameNumber();
   }
}

1.3、转换BufferedImage

Java2DFrameConverter jfc = new Java2DFrameConverter();
BufferedImage bufferedImage = jfc.getBufferedImage(frame);

1.4、完整代码

由于获取frame 经常 null帧,所以添加了循环。

长时间读取不到,或者rtsp连接断开等,添加断开重连机制。

 
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;import java.awt.image.BufferedImage;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;@Slf4j
public class CaptureThread extends Thread {private String final rtsp ;public CaptureThread(String rtsp) {this.rtsp = rtsp;this.setName("CaptureId-1"); }@Overridepublic void run() { // 开启接收流 log.info("组装后的地址为=" + rtsp);FFmpegFrameGrabber frameGrabber = null;long count = 0;int error = 0;try {frameGrabber = new FFmpegFrameGrabber(rtsp);frameGrabber.setOption("rtsp_transport", "tcp");frameGrabber.startUnsafe();int retry = 0;while (true) {Frame frame = frameGrabber.grabImage();// long frameNumber = frameGrabber.getFrameNumber();if (null == frame) {if (error > 3) {break;}retry++;if (retry >= 10) {log.info("取帧失败,即将重启rtsp=" + rtsp);error++;Thread.sleep(200);//frameGrabber.restart();frameGrabber.releaseUnsafe();frameGrabber.startUnsafe();}continue;}retry = 0;error = 0;doSoftDecode(frame);}} catch (org.bytedeco.javacv.FrameGrabber.Exception ex) {log.error("视频获取失败", (Throwable) ex);} catch (Error error) {log.error("是否能捕获堆栈异常");} catch (Throwable ex) {log.error("帧处理失败", ex);} finally {if (frameGrabber != null) {try {frameGrabber.stop();frameGrabber.close();} catch (org.bytedeco.javacv.FrameGrabber.Exception e) {log.error(e.getMessage(), e);}}}}private void doSoftDecode(Frame frame) throws Exception {long start = System.currentTimeMillis();Java2DFrameConverter jfc = new Java2DFrameConverter();BufferedImage bufferedImage = jfc.getBufferedImage(frame);log.debug("解码耗时=" + (System.currentTimeMillis() - start));// TODO ...}
}

2、基于Ffmpeg命令

2.1、ffmpeg命令

ffmpeg  -rtsp_transport  tcp  -i  %s  -f  image2pipe -vcodec mjpeg  -rtbufsize 20M  -q:v 2 -

  • -rtsp_transport tcp:使用 TCP 协议来传输 RTSP 流,以提高稳定性。
  • -i rtsp://username:password@camera_ip:port/path:指定 RTSP 流的 URL。
  • -f image2pipe:指定输出格式为图片流。
  • -vcodec mjpeg:使用 MJPEG 编解码器处理视频流,保持图像质量。
  • -r 25:设置帧率为 25 帧每秒。
  • -rtbufsize 20M:设置解码器缓冲区大小为 20MB,减少图像丢失和马赛克问题。
  • -q:v 2:设置图像质量,2 是较高的质量值(范围是 1-31,1 是最高质量)。

2.2、读取帧

使用独立线程读取数据流,process所在的ffmpeg 命令将流推送到 inputStream 中。内部线程循环读取。

 Thread pt = new Thread(() -> {
                    try (InputStream errorStream = process.getErrorStream()) {
                        byte[] buffer = new byte[BUFFER_SIZE];
                        int bytesRead;
                        while ((bytesRead = errorStream.read(buffer)) != -1) {
                            log.error("异常" + bytesRead);
                           // System.err.write(buffer, 0, bytesRead);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
                pt.start();

2.3、转换BufferedImage

读取的BufferedImage 也需要异步的处理,否则会造成 pt 线程阻塞。

使用CompletableFuture.supplyAsync 异步的返回结果,结合join()等待任务处理完成。

byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead;
while (running && (bytesRead = inputStream.read(buffer)) != -1) {
   ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, bytesRead);
   BufferedImage image = ImageIO.read(bais);
   if (image != null) {
     // 将图像保存操作移到后台线程中处理
     Boolean flag = CompletableFuture.supplyAsync( () -> saveImg(image)).join();
   }
}

2.4、完整代码


import lombok.extern.slf4j.Slf4j;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;/**** 实际的监控采集帧* @date 2024/7/19*/
@Slf4j
public class CaptureFfmpegThread extends Thread {/**重连延迟时间*/private static final int RECONNECT_DELAY_MS = 5000;/**缓冲区大小*/private static final int BUFFER_SIZE = 5 * 1024 * 1024;private static final String FFMPEG_CMD_TEMPLATE = "ffmpeg -rtsp_transport tcp -i %s -f image2pipe -vcodec mjpeg -rtbufsize 20M -q:v 2 -";/**通过外部控制线程中断,停止采集*/private boolean running;private final String rtspUrl;public CaptureFfmpegThread(String rtsp) {this.setName("CaptureId-1" );this.rtspUrl = rtsp;this.running = true;}@Overridepublic void run() { log.info("组装后的地址为=" + rtspUrl);while (true) {try {String ffmpegCmd = String.format(FFMPEG_CMD_TEMPLATE, rtspUrl);Process process = Runtime.getRuntime().exec(ffmpegCmd);InputStream inputStream = process.getInputStream();// 处理错误流以避免阻塞Thread pt = new Thread(() -> {try (InputStream errorStream = process.getErrorStream()) {byte[] buffer = new byte[BUFFER_SIZE];int bytesRead;while ((bytesRead = errorStream.read(buffer)) != -1) {log.error("异常" + bytesRead);// System.err.write(buffer, 0, bytesRead);}} catch (IOException e) {e.printStackTrace();}});pt.start();byte[] buffer = new byte[BUFFER_SIZE];int bytesRead;while (running && (bytesRead = inputStream.read(buffer)) != -1) {ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, bytesRead);BufferedImage image = ImageIO.read(bais);if (image != null) {// 将图像保存操作移到后台线程中处理Boolean flag = CompletableFuture.supplyAsync( () -> saveImg(image)).join();}}process.waitFor();log.info("FFmpeg process ended for stream: " + rtspUrl + ", attempting to restart...");} catch (IOException | InterruptedException e) {log.info("Error occurred for stream: " + rtspUrl + " - " + e.getMessage());}try {log.info("Waiting before attempting to reconnect stream: " + rtspUrl);TimeUnit.MILLISECONDS.sleep(RECONNECT_DELAY_MS);} catch (InterruptedException e) {log.info("Reconnect delay interrupted for stream: " + rtspUrl + " - " + e.getMessage());} finally {if(!running){break;}}}}private boolean saveImg(BufferedImage image){// TODO ...return true;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/49461.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最优化理论与方法-第十讲割平面法

文章目录 1. 原问题&#xff1a;2. 割平面法程序步骤2.1 第一次迭代2.2 第二次迭代2.3 第三次迭代 1. 原问题&#xff1a; 给定下列约束优化问题&#xff1a; ( P ) min ⁡ 3 x 1 2 2 x 2 2 s t . − 5 x 1 − 2 x 2 3 ≤ 0 , x ∈ X { x ∈ Z n ∣ 8 x 1 8 x 2 ≥ 1 , 0…

mysql的主从复制和读写分离:

mysql的主从复制和读写分离&#xff1a; 主从复制 面试必问&#xff1a;主从复制的原理 主从复制的模式&#xff1a; 1、mysql的默认模式&#xff1a; 异步模式 主库在更新完事务之后会立即把结果返回给从服务器&#xff0c;并不关心从库是否接受到&#xff0c;以及从库是…

共享存储可以解决FusionCompute哪些问题

共享存储在FusionCompute环境中扮演着至关重要的角色&#xff0c;主要通过提供集中的数据访问点来优化和增强虚拟化基础设施的功能。以下是共享存储在FusionCompute中可以解决的一些关键问题&#xff1a; 虚拟机迁移&#xff1a; 共享存储允许虚拟机&#xff08;VM&#xff09;…

【React】package.json 文件详解

文章目录 一、package.json 文件的基本结构二、package.json 文件的关键字段1. name 和 version2. description3. main4. scripts5. dependencies 和 devDependencies6. repository7. keywords8. author 和 license9. bugs 和 homepage 三、package.json 文件的高级配置1. 配置…

分享一个Springer模板关于论文作者和单位信息的修改范例,以及Applied Intelligence期刊latex模板的下载链接

在这篇文章中&#xff0c;我写一些关于解决springer期刊提供的LaTex模板参考文献格式为作者年份时的顺序问题以及如何在正文中将参考文献格式引用成[1]这种数字格式类似的经验&#xff0c;该篇帖子里还分享了一个大佬关于springer模板完整的修改流程&#xff0c;有需要的伙伴可…

全球电脑蓝屏崩溃,为何中国没事?周鸿祎:因 90% 用 360 软件!

2024 年 7 月 19 日&#xff0c;出现了震惊世界的微软蓝屏事件&#xff0c;全球近千万台 Windows 设备集体蓝屏宕机&#xff01; 这次的事件绝对称得上是 “载入史册”&#xff01;甚至百度百科都专门针对这次的事件出了一个词条、央视新闻也专门报道了此事。 这次事件的影响有…

ActiViz实战:二维纹理贴图vtkTexture

文章目录 一、效果预览二、基本概念三、功能特性四、与C++不同五、完整示例代码一、效果预览 二、基本概念 vtkTexture是VTK(Visualization Toolkit)中用于纹理映射的一个类,它允许用户将二维图像(纹理)贴到三维物体的表面上,从而增加场景的真实感和细节。 纹理映射:是一…

PY32F071单片机,主频最高72兆,资源丰富,有USB,DAC,运放

PY32F071 系列单片机是基于32 位 ARM Cortex-M0 内核的微控制器&#xff0c;宽电压工作范围的 MCU。芯片嵌入高达 128 Kbytes flash 和 16 Kbytes SRAM 存储器&#xff0c;最高72 MHz工作频率。芯片支持串行调试 (SWD)。PY32F071单片机提供了包含了HAL和LL两种不同层次的驱动库…

自定义webIpad证件相机(webRTC)

该技术方案可用于各浏览器自定义相机开发 相机UI&#xff08;index.html&#xff09; <!DOCTYPE html> <html lang"zh" prew"-1"><head><meta charset"UTF-8"><meta name"viewport"content"user-sc…

Redis从入门到超神-(六)SpringCache操作缓存

引言 java操作Redis有很多中方案&#xff0c;Jedis&#xff0c;SpringBootDataRedis,Redisson等&#xff0c;本篇文章的目的是使用SpringBootDataRedis整合SpringCache基于Redis实现缓存操作 一、SpringBoot整合Redis实现缓存 SpringBoot提供了整合Redis的方案&#xff0c;我…

Llama 3.1要来啦?!测试性能战胜GPT-4o

哎呀&#xff0c;Meta声称将于今晚发布的Llama 3.1&#xff0c;数小时前就在Hugging Face上泄露出来了&#xff1f;泄露的人很有可能是Meta员工&#xff1f; 还是先来看泄露出来的llama3.1吧。新的Llama 3.1模型包括8B、70B、405B三个版本。 而经过网友测试&#xff0c;该base…

Spark实时(二):StructuredStreaming编程模型

文章目录 StructuredStreaming编程模型 一、基础语义 二、事件时间和延迟数据 三、​​​​​​​​​​​​​​容错语义 StructuredStreaming编程模型 一、基础语义 Structured Streaming处理实时数据思想是将实时数据看成一张没有边界的表&#xff0c;数据源源不断的追…

年化22.8%的单因子分析:基于Alphalens做可转债全市场数据的单因子分析(附python代码+全量数据)

原创文章第597篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 因子分析是量化研究的基本技能之一。通过因子分析&#xff0c;找出有效的因子&#xff0c;通过相关性去重后&#xff0c;就可以通过机器学习、线性回归等方法把因子组合起来&#xf…

Linux基础学习day1

1.Linux系统介绍 1.常见的操作系统 1.Windows&#xff08;NT内核&#xff09;不开源 2.ubantu&#xff08;linux内核&#xff09; 3.ios&#xff08;unix内核&#xff09;不开源 4.鸿蒙&#xff08;兼容linux内核&#xff09; 5.Android&#xff08;linux内核&#xff09…

STM32(七):STM32指南者-通信实验

目录 一、基本概念通讯基本概念1、串行和并行2、同步通讯与异步通讯3、全双工、半双工、单工4、通讯速率 USART基本概念1、串口通讯基本概念2、物理层3、协议层4、指南者的串口USART I2C基本概念SPI基本概念 二、USART串口实验前期准备1、安装安装 USB 转串口驱动_CH3402、野火…

Git之repo sync -l与repo forall -c git checkout用法区别(四十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

微信各平台历史版本含下载地址大全( 安卓 | Windows | MAC )

微信-windows-版本历史 https://github.com/tom-snow/wechat-windows-versions/releases 微信-windows-x86版本历史 https://github.com/tom-snow/wechat-windows-versions-x86/releases 微信安卓版本历史 https://github.com/DJB-Developer/wechat-android-history-version…

Apache DolphinScheduler 3.2.2 版本正式发布!

Apache DolphinScheduler 3.2.2 版本正式发布&#xff01; 近日&#xff0c;Apache DolphinScheduler 发布了 3.2.2 版本。此版本主要基于 3.2.1 版本进行了 bug 修复&#xff0c;新增若干特性&#xff0c;并进行了众多改进和 Bug 修复&#xff0c;以及文档修复等。 &#x1…

OAuth 2.0

OAuth 2.0&#xff08;Open Authorization 2.0&#xff09;是一种开放标准的授权协议&#xff0c;它允许第三方应用程序以安全可控的方式访问受保护的资源&#xff0c;而无需用户将用户名和密码信息与第三方应用程序共享。 一、设计原则 OAuth 2.0的设计旨在解决OAuth 1.0中的…

电路学习——经典运放电路之滞回比较器(施密特触发器)(2024.07.18)

参考链接1: 电子设计教程29&#xff1a;滞回比较器&#xff08;施密特触发器&#xff09; 参考链接2: 滞回比较器电路详细分析 参考链接3: 比较器精髓&#xff1a;施密特触发器&#xff0c;正反馈的妙用 参考链接4: 比较器反馈电阻选多大&#xff1f;理解滞后效应&#xff0c;轻…