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();
        }
    }
}
View Code

即可获取第一帧图片

第二种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

 

 

posted @ 2019-09-05 13:51  zhaoyanhao  阅读(3224)  评论(1编辑  收藏  举报