获取视频处理对象的方式有很多,读取本地文件、读取url、读取摄像头等,而直接读流解析视频的实施方案却难以寻觅。此处有两种方案处理视频流(此处设定场景为用户上传视频,同时两种方式均需服务端安装ffmpeg+opencv):

  1.io流保存本地再读取

      该方案没有太多技术含量,直接借助java.io+opencv-VideoCapture即可实现视频的解帧等操作。

      1)保存本地

        本地保存为求方便,直接使用 apache.commons.io.FileUtils.copyInputStreamToFile(InputStream,File)方法

// MultipartFile videoFile
InputStream videoInputStream = videoFile.getInputStream();
File file = new File(path + getRandomFileName() + ".mp4");
FileUtils.copyInputStreamToFile(videoInputStream,file);

      2)  视频解析

        此处视频解析,可以直接使用整合了ffmpeg的opencv中的VideoCapture对象来操作

VideoCapture = new VideoCapture(file.getPath());

      3) 业务要求

        项目业务要求,取视频前两秒的20帧,转储为Mat矩阵的集合

// 此处的视频操作常量来自 javacv
Double rawFps = videoCapture.get(opencv_highgui.CV_CAP_PROP_FPS);// 帧率
Double validFps = Math.min(10.0,rawFps);// 校验
Double validTimeGap = 1.0 / validFps;
List<Mat> frameList = new ArrayList();
try {
Double currentTime = 0.0;
while (currentTime + EPSILON < timeCount) {//EPSILON为浮点数操作修正值
// 设置视频的位置
videoCapture.set(opencv_highgui.CV_CAP_PROP_POS_MSEC,currentTime * 1000);
Mat frame = new Mat();
capture.read(frame);
frameList.add(frame);
currentTime += validTimeGap;
}
} catch .... finally ..

  2.直接读流

    直接读流的依赖支撑来自 Bytedeco - javacv - FFmpegFrameGrabber 类,在此 向Bytedeco团队致敬

    1)读io,转FFmpegFrameGrabber

InputStream inputStream = videoFile.getInputStream();
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputStream);

    2)业务要求

    FFmpegFrameGrabber与VideoCapture在开闭时有所不同,VideoCapture如果直接构造来初始化不需手动open()即打开,FFmpegFrameGrabber有一专属方法来打开视频解析 - start() 。

grabber.start();
// get each mat
List<Mat> mats = new ArrayList<>();
double fps = grabber.getFrameRate();
double each = Math.ceil(fps / fpsDefine);
double count = fps * timeCount ;
for (int i = 0 ; i < count ; i++) {
double mod = i % each;
Frame frame = grabber.grabImage();
if (mod == 0.0) {
OpenCVFrameConverter.ToMat toMat = new OpenCVFrameConverter.ToMat();
opencv_core.Mat mat = toMat.convert(frame);
if (mat != null) {
Mat matUse = new Mat(mat.clone().address());
mats.add(matUse);
mat.release();
}
}
}

  3.两种方式的异同

    1.bytedeco - ffmpeg 包中整合有Frame - Mat - BufferImage的相关转换方法,实际应用中需注意其与opencv - Mat的转换

    2.二者都依赖ffmpeg+opencv本地方法,而pom依赖又有不同:

    VideoCapture:

        <dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>2.4.13</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.3</version>
</dependency>

    FFmpegFrameGrabber:

        <dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>2.4.13</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.4.3-1.4.3</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.0.2-1.4.3</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.4.3</version>
</dependency>

    3.都需手动对本地资源加以释放:这里包括io流,视频流,Mat矩阵,同时释放的方法又有不同

    VideoCapture:release()

    FFmpegFrameGrabber : stop()

        finally {
try {
inputStream.close();
} catch (IOException e) {
log.error("close InputStream error : " , e);
}
try {
grabber.stop();
} catch (FrameGrabber.Exception e) {
log.error("stop grabber error : " , e);
}
for (Mat mat : mats) {
if (mat != null) {
mat.release();
}
}
}

Java之视频读取IO流解帧实施方案的更多相关文章

  1. Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

    声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ...

  2. Java 持久化操作之 --io流与序列化

    1)File类操作文件的属性 1.File类的常用方法 1. 文件的绝对完整路径:getAbsolutePath() 文件名:getName() 文件相对路径:getPath() 文件的上一级目录:g ...

  3. Java基础12一IO流

    1.IO流的原理 利用数据通道实现程序和数据源之间数据的的读写操作.  2.IO流分类 输入流.输出流.字节流.字符流.节点流.过滤流  3.InputStream 字节输入流 实现类FileInpu ...

  4. 乐字节Java之file、IO流基础知识和操作步骤

    嗨喽,小乐又来了,今天要给大家送上的技术文章是Java重点知识-IO流. 先来看看IO流的思维导图吧. 一. File 在Java中,Everything is Object!所以在文件中,也不例外! ...

  5. Java基础系列8——IO流超详细总结

    该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 在初学Java时,I ...

  6. Java文件处理之IO流

    一.概述 流:代表任何有能力产出数据的数据源对象或者是有能力接受数据的接收端对象 :其作用是为数据源和目的地建立一个输送通道. IO流:是程序中一套用于数据传输的机制.IO流是Input流和Outpu ...

  7. Java基础之详谈IO流

    Java基础知识.IO流详细讲解.你所要的IO这里都有

  8. Java——(九)IO流

    一.流的分类 1.输入流和输出流 按照流的流向来分,可以分为输入流和输出流 输入流:只能从中读取数据,而不能向其写入数据. 输出流:只能向其写入数据,而不能从中读取数据. 此处的输入.输出涉及一个方向 ...

  9. Java的递归、IO流

    .t1 { background-color: #ff8080; width: 1100px; height: 40px } 一.递归 [递归] 1. 在函数自身内部,调用函数本身的方式,称为递归. ...

随机推荐

  1. Winform开发框架中的综合案例Demo

    在实际的系统开发中,我们往往需要一些简单的的案例代码,基于此目的我把Winform开发框架中各种闪光点和不错的功能,有些是我们对功能模块的简单封装,而有些则是引入了一些应用广泛的开源组件进行集成使用, ...

  2. Fiddler抓包和修改WebSocket数据,支持wss

    记录一下用Fiddler对WebSocket收发的数据进行抓包分析和篡改数据,只找到这么一个方法,能用就行吧. 时间:2019-3-29 环境: win7 + Fiddler 5.0 Fiddler抓 ...

  3. 配置Apache虚拟主机

    实验环境 一台最小化安装的CentOS 7.3虚拟机 配置基础环境 1. 安装apache yum install -y httpd 2. 建立虚拟主机的根目录 mkdir /var/wwwroot ...

  4. .NET-记一次架构优化实战与方案-目录

    前言 本系列是根据我公司的某块业务优化进行改写的,为了避免触发法律的红线,我对部分代码做了截取并打码. 因为优化方案是针对现有业务的问题情况进行的,不做任何太过过分吹牛逼.一切以基于现有的业务,优化处 ...

  5. flask 跨域请求

    Flask中,跨域请求主要有两种方式: 1.在响应头信息中添加允许跨域 如下,使用装饰器app.after_request(我这里的web是定义的蓝图),这样在每次请求后,加入header 2.使用第 ...

  6. ajax成功后XML 解析错误:格式不佳

    就是Ajax发送请求后,意图回显数据时会出现这个错误,貌似chrome浏览器不会报用火狐能看到: 可能的原因有两个,就是后台应该返回一个json格式的字符串,但是你返回的是浏览器看不懂的,也就是返回格 ...

  7. 注入技术--LSP劫持注入

    1.原理 简单来说,LSP就是一个dll程序. 应用程序通过winsock2进行网络通信时,会调用ws2_32.dll的导出函数,如connect,accept等. 而后端通过LSP实现这些函数的底层 ...

  8. API的设计与安全

    前后端分离是个浪潮,原来只有APP客户端会考虑这些,现在连Web都要考虑前后端分离 . 这里面不得不谈的就是API的设计和安全性,这些个问题不解决好,将会给服务器安全和性能带来很大威胁 . API的设 ...

  9. js创建并下载文件

    先上代码: function createAndDownloadFile(fileName, content) { var aTag = document.createElement('a'); va ...

  10. MyEclipse 10.X激活方法

    普遍的激活办法请参考: http://blog.csdn.net/miss_kun/article/details/51819206 http://jingyan.baidu.com/article/ ...