javacv获取视频第一帧
第一种是用ffmpeg工具,不过还得安装客户端软件,于是放弃了,还有一种是javacv开源工具,所以选择第二种:
第一种:ffmpeg工具
需要安装ffmpeg软件,支持windows和linux,视频安装教程参考:https://www.cnblogs.com/rxbook/p/9652185.html
然后用以下代码:
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter; public class FirstFrameUtil {
protected String ffmpegApp;
public FirstFrameUtil(String ffmpegApp) {
this.ffmpegApp = ffmpegApp;
}
@SuppressWarnings("unused")
/****
* 获取指定时间内的图片
* @param videoFilename:视频路径
* @param thumbFilename:图片保存路径
* @param width:图片长
* @param height:图片宽
* @param hour:指定时
* @param min:指定分
* @param sec:指定秒
* @throws IOException
* @throws InterruptedException
*/
public void getThumb(String videoFilename, String thumbFilename, int hour, int min, float sec) throws IOException, InterruptedException {
ProcessBuilder processBuilder = new ProcessBuilder(ffmpegApp, "-y", "-i", videoFilename, "-vframes", "1", "-ss", hour + ":" + min + ":" + sec, "-f", "mjpeg", "-an",
thumbFilename);
Process process = processBuilder.start();
InputStream stderr = process.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null)
;
process.waitFor();
if (br != null)
br.close();
if (isr != null)
isr.close();
if (stderr != null)
stderr.close();
}
public static void main(String[] args) {
String path = "D:\\config\\ffmpeg-win64\\bin\\ffmpeg.exe"; FirstFrameUtil videoThumbTaker = new FirstFrameUtil(path);
try {
videoThumbTaker.getThumb("D:\\test2.mp4", "D:\\test\\result.png", 0, 0, 1);
File ffmpegFile = new File("D:\\test\\result.png");
FileInputStream input=new FileInputStream(ffmpegFile); System.out.println("over");
} catch (Exception e) {
e.printStackTrace();
}
}
}
即可获取第一帧图片
第二种javacv
直接上代码:(后边有介绍pom文件的引用)
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.javacv.Frame; import javax.imageio.ImageIO; import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException; public class VideoTool { public static void main(String[] args) throws Exception { // randomGrabberFFmpegImage("http://101.132.110.90/group1/M00/00/05/rBN4LFq8p5SAJT0wA5k4vpHKf7Q325.mp4", "D:\\test", "test2");
randomGrabberFFmpegImage("D:\\test2.mp4", "D:\\test", "test2");
//randomGrabberFFmpegImage("C:/Users\\Administrator\\Desktop\\VID_20171229_162251.mp4", "G:\\test", "111");
} public static void randomGrabberFFmpegImage(String filePath, String targerFilePath, String targetFileName)
throws Exception {
//创建视频帧抓取工具
FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
ff.start();
//获取旋转角度信息(90度)
String rotate =ff.getVideoMetadata("rotate");
//帧
Frame f;
//i可以控制获取第几帧
int i = 0;
while (i <5) {
//一帧一帧去抓取视频图片,ff.grabImage();每次抓取下一帧
f =ff.grabImage();
IplImage src = null;
//旋转图像并输出第29帧
if(i==4){
//手机录的视频有旋转角度,需要旋转处理
if(null !=rotate &&rotate.length() > 1) {
OpenCVFrameConverter.ToIplImage converter =new OpenCVFrameConverter.ToIplImage();
src =converter.convert(f);
f =converter.convert(rotate(src, Integer.valueOf(rotate)));
}
//输出第几帧图片
doExecuteFrame(f,targerFilePath,targetFileName+i+i);
}
i++;
}
ff.stop();
} /*
* 旋转角度的
*/
public static IplImage rotate(IplImage src, int angle) {
IplImage img = IplImage.create(src.height(), src.width(), src.depth(), src.nChannels());
opencv_core.cvTranspose(src, img);
opencv_core.cvFlip(img, img, angle);
return img;
} public static void doExecuteFrame(Frame f, String targerFilePath, String targetFileName) { if (null ==f ||null ==f.image) {
return;
}
Java2DFrameConverter converter =new Java2DFrameConverter();
String imageMat ="jpg";
String FileName =targerFilePath + File.separator +targetFileName +"." +imageMat;
BufferedImage bi =converter.getBufferedImage(f);
System.out.println("width:" + bi.getWidth());
System.out.println("height:" + bi.getHeight());
File output =new File(FileName);
try {
ImageIO.write(bi,imageMat,output);
}catch (IOException e) {
e.printStackTrace();
}
} }
如果不判断旋转,把手机视频放上去,截出来的是方向不对,如图左边是旋转过的,右边没有旋转的:
解决图片旋转问题参考:http://blog.csdn.net/z562743237/article/details/54667252,通过一段时间的搜索了解到,如果拍摄的视频中带有旋转(rotate)信息,那么截取出来的图片就会被旋转。通过查询API发现FFmpegFrameGrabber的getVideoMetadata("rotate")方法可以获取到视频的旋转信息。根据获取到的rotate信息对ff.grabImage()得到的Frame进行旋转,但是Frame并没有提供旋转接口。但IpImage对象提供了旋转方法 。
大多数人都是直接引入
javacv-platform
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.3.1</version>
</dependency>
javacv-platform这种方式依赖的jar包300M,太大了,经过精简后pom文件如下:(在用,40兆左右)
<properties>
<javacpp.version>1.3</javacpp.version>
</properties> <dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.3.1</version>
<exclusions>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>flycapture</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>libdc1394</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>libfreenect</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>libfreenect2</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>librealsense</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>videoinput</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>artoolkitplus</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>artoolkitplus</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>flandmark</artifactId>
</exclusion>
</exclusions>
</dependency> <dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.1.0-${javacpp.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.1.0-${javacpp.version}</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg</artifactId>
<version>3.2.1-${javacpp.version}</version>
<classifier>windows-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg</artifactId>
<version>3.2.1-${javacpp.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
</dependencies>
共8个jar
javacv获取视频第一帧的更多相关文章
- Android -- 获取视频第一帧缩略图
干货 从API 8开始,新增了一个类: android.media.ThumbnailUtils这个类提供了3个静态方法一个用来获取视频第一帧得到的Bitmap,2个对图片进行缩略处理. public ...
- Android之使用MediaMetadataRetriever类获取视频第一帧
一.首先,来介绍一下MediaMetadataRetriever类,此类位于android.media包下,这里,先附上可查看此类的API地址:MediaMetadataRetriever类.大家能够 ...
- 关于video标签移动端开发遇到的问题,获取视频第一帧,全屏,自动播放,自适应等问题
最近一直在处理video标签在IOS和Android端的兼容问题,其中遇到不少坑,绝大多数问题已经解决,下面是处理问题经验的总结: 1.获取视频的第一帧作为背景图: 技术:canvas绘图 windo ...
- 通过 ffmpeg 获取视频第一帧(指定时间)图片
最近做一个上传教学视频的方法,上传视频的同时需要上传视频缩略图,为了避免用户上传的缩略图与视频内容不符,经理要求直接从上传的视频中截图视频的某一帧作为缩略图,并给我推荐了FFMPEG.FFMPEG 功 ...
- python cv2获取视频第一帧,并转码
安装Python库 sudo pip install opencv-python 或者sudo pip install opencv-python -i https://pypi.douban.com ...
- Android视频处理 --处理视频第一帧缩略图
从API 8开始,新增了一个类: android.media.ThumbnailUtils这个类提供了3个静态方法一个用来获取视频第一帧得到的Bitmap,2个对图片进行缩略处理. ? 1 publi ...
- 使用javacv 截取视频指定帧节
个人博客 地址:https://www.wenhaofan.com/article/20190407105818 引入依赖 <dependency> <groupId>org. ...
- vue 截取视频第一帧
最近自己写项目,在项目中涉及功能点又截取视频帧的点:需求澄清:移动端封面展示,平台上传图片(多张上传)取第一张上传图片为封面图:如上传视频则截取视频第一帧作为封面图: 实现思路:h5 video标签 ...
- php ffmpeg截取视频第一帧保存为图片的方法
php ffmpeg截取视频第一帧保存为图片的方法 <pre> $xiangmupath = $this->getxiangmupath(); $filename = 'chengs ...
随机推荐
- Flink:动态表上的连续查询
用SQL分析数据流 越来越多的公司在采用流处理技术,并将现有的批处理应用程序迁移到流处理或者为新的应用设计流处理方案.其中许多应用程序专注于分析流数据.分析的数据流来源广泛,如数据库交易,点击,传感器 ...
- kettle 数据库连接失败
kettle 数据库连接失败 测试连接提示缺少驱动. 提示错误信息:Driver class 'oracle.jdbc.driver.OracleDriver' could not be found, ...
- 统计Shell脚本执行时间
统计Shell脚本执行时间,帮助分析改进脚本执行 用 date 相减 #!/bin/bash startTime=`date +%Y%m%d-%H:%M:%S` startTime_s=`date + ...
- c++ rand随机数生成(随机种子设置)
需求:每次初始化不同的随机数 1.默认 //这样用每次都会产生相同数字 #include <stdlib.h> #include <stdio.h> #define N 10 ...
- VC++ DLL 2 静态链接库
这一篇以VS2013为例子介绍怎样编写一个静态链接库和调用. 1.打开VS2013,新建Visual C++ 的win32项目: 新建后工程分支如下: 添加头文件和源文件: 编写头文件和源文件内容: ...
- 学习Github必须要会的知识
目的 托管项目代码 基本概念 仓库Respository 存放项目代码,每个项目对应一个仓库,多个开源项目则有多个仓库. 收藏Star 收藏项目,方便下次查看. 复制克隆项目Fork ...
- hook键盘钩子 带dll
library Key; uses SysUtils, Classes, HookKey_Unit in 'HookKey_Unit.pas'; {$R *.res} exports HookOn,H ...
- webapi 传入参数校验
/// <summary> /// 传入参数校验过滤器 /// </summary> public class ValidateReqModelFilter : ActionF ...
- Rancher安装 - CentOS7(Docker)环境
Rancher安装 - CentOS7(Docker)环境 对于开发和测试环境,我们建议通过运行单个Docker容器来安装Rancher.在此安装场景中,您将在单个Linux主机上安装Docker,然 ...
- mysql自关联和多表连接查询
自关联操作 多表连接查询 inner join 内查询 left join 左查询 right join 右查询 ...