第一种是用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获取视频第一帧的更多相关文章

  1. Android -- 获取视频第一帧缩略图

    干货 从API 8开始,新增了一个类: android.media.ThumbnailUtils这个类提供了3个静态方法一个用来获取视频第一帧得到的Bitmap,2个对图片进行缩略处理. public ...

  2. Android之使用MediaMetadataRetriever类获取视频第一帧

    一.首先,来介绍一下MediaMetadataRetriever类,此类位于android.media包下,这里,先附上可查看此类的API地址:MediaMetadataRetriever类.大家能够 ...

  3. 关于video标签移动端开发遇到的问题,获取视频第一帧,全屏,自动播放,自适应等问题

    最近一直在处理video标签在IOS和Android端的兼容问题,其中遇到不少坑,绝大多数问题已经解决,下面是处理问题经验的总结: 1.获取视频的第一帧作为背景图: 技术:canvas绘图 windo ...

  4. 通过 ffmpeg 获取视频第一帧(指定时间)图片

    最近做一个上传教学视频的方法,上传视频的同时需要上传视频缩略图,为了避免用户上传的缩略图与视频内容不符,经理要求直接从上传的视频中截图视频的某一帧作为缩略图,并给我推荐了FFMPEG.FFMPEG 功 ...

  5. python cv2获取视频第一帧,并转码

    安装Python库 sudo pip install opencv-python 或者sudo pip install opencv-python -i https://pypi.douban.com ...

  6. Android视频处理 --处理视频第一帧缩略图

    从API 8开始,新增了一个类: android.media.ThumbnailUtils这个类提供了3个静态方法一个用来获取视频第一帧得到的Bitmap,2个对图片进行缩略处理. ? 1 publi ...

  7. 使用javacv 截取视频指定帧节

    个人博客 地址:https://www.wenhaofan.com/article/20190407105818 引入依赖 <dependency> <groupId>org. ...

  8. vue 截取视频第一帧

    最近自己写项目,在项目中涉及功能点又截取视频帧的点:需求澄清:移动端封面展示,平台上传图片(多张上传)取第一张上传图片为封面图:如上传视频则截取视频第一帧作为封面图: 实现思路:h5  video标签 ...

  9. php ffmpeg截取视频第一帧保存为图片的方法

    php ffmpeg截取视频第一帧保存为图片的方法 <pre> $xiangmupath = $this->getxiangmupath(); $filename = 'chengs ...

随机推荐

  1. slf4j NoSuchMethodError 错误 ---- 版本冲突

    java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/Stri ...

  2. UVALive 3634 数据结构模拟

    这题真是坑啊,题意不明,其实就是往桟里面压入空的set集合,所以之前的询问大小都是只有0,只有add的时候,才会产生新的占空间的集合 用stack和set直接进行模拟 #include <ios ...

  3. Android自定义View——仿滴滴出行十大司机评选活动说明

    滴滴出行原版图 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 仿图 ? ? ? ? ? ? 1.分 ...

  4. 新iPhone的高售价下,苹果供应商们是该笑还是该哭?

    自新 iPhone发布之日起,世界就从未停止讨论其售价,越来越多的人开始困惑:新 iPhone毫无创新亮点,有什么底气卖到12799RMB呢?整个地球都在期待苹果推出廉价版 iPhone,望眼欲穿地等 ...

  5. Python中Opencv和PIL.Image读取图片的差异对比

    近日,在进行深度学习进行推理的时候,发现不管怎么样都得不出正确的结果,再仔细和正确的代码进行对比了后发现原来是Python中不同的库读取的图片数组是有差异的. image = np.array(Ima ...

  6. RK3399开发板Android镜像烧写之Windows系统映像烧写

    4.1.1 l RKTool  驱动安装(基于迅为iTOP-3399开发板)DriverAssitant_v4.5.zip 文件,打开 驱动安装成功,如下图: 注意事项:1.目前支持的操作系统包括:X ...

  7. SQL基础教程(第2版)第3章 聚合与排序:3-2 对表进行分组

    第3章 聚合与排序:3-2 对表进行分组 ● 使用GROUP BY子句可以像切蛋糕那样将表分割.通过使用聚合函数和GROUP BY子句,可以根据“商品种类”或者“登记日期”等将表分割后再进行汇总.● ...

  8. String 字符串拼接

    字符串拼接有两个方法 第一中 var sad = "happy" var variable = "you"+sad +"" variable ...

  9. spring容器抽象的具体实现

    1.BeanFactory 接口与 ApplicationContext 接口 (1)spring 提供了两种类型的IOC容器实现.BeanFactory 和 ApplicationContext ( ...

  10. Python说文解字_父类的继承

    1. 第一个问题: 我们知道类是可以继承其他类的,在继承的过程中我们不光可以继承父类的方法,还可继承父类的属性,另外还可以在父类的基础上添加自己的东西. 2. 第二个问题: 我们继承父类属性和方法的时 ...