javaCV视频取帧测试类,封装完整可直接使用,真香!!

作者 | 陈哈哈
来源 | java开发

前段时间我需要一个视频取帧工具,在网上查询一些单都或多或少有问题,于是自己总结了一下,并已经封装好,分享出来供大家需要时使用。

javaCV视频取帧测试类,封装完整可直接使用,真香!!

GitHub路径:

https://github.com/chenhua0915/FetchVideoFrameUtil.git

 

运行结果截图

javaCV视频取帧测试类,封装完整可直接使用,真香!!

 

pom文件中的Maven配置:

这里需要的jar包特别大需要大概300M,测试使用是没影响的,如果需投入线上则需要拆分出需要的部分。

<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform  视频取帧-->
<dependency>
	<groupId>org.bytedeco</groupId>
	<artifactId>javacv-platform</artifactId>
	<version>1.4.4</version>
</dependency>

 

实例代码:

package com.chenhh.demo;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;


/**
 * Created with IDEA
 * 视频取帧,可设置间隔秒数或获取所有帧数
 *
 * @Author Chensj
 * @Date 2018/4/2 14:29
 * @Description
 * @Version 1.0
 */
public class FetchVideoFrameUtil {

    // 主函数
    public static void main(String[] args){
        try {
            String picPath = "D:\\demo\\pic\\";  // 提取得每帧图片存放位置
            String videoPath = "D:\\demo1.mp4";  // 原视频文件路径
            int second = 0; // 每隔多少帧取一张图,一般高清视频每秒 20-24 帧,根据情况配置,如果全部提取,则将second设为 0 即可
            // 开始视频取帧流程
            FetchVideoFrameUtil.fetchPic(new File(videoPath),picPath,second);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取指定视频的帧并保存为图片至指定目录
     * @param file  源视频文件
     * @param picPath  截取帧的图片存放路径
     * @throws Exception
     */
    public static void fetchPic(File file, String picPath,int second) throws Exception{

        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); // 获取视频文件
        System.out.println(FetchVideoFrameUtil.getVideoTime(file)); // 显示视频长度(秒/s)

        ff.start(); // 调用视频文件播放
        int length = ff.getLengthInAudioFrames(); //视频帧数长度
        System.out.println(ff.getFrameRate());

        int i = 0; // 图片帧数,如需跳过前几秒,则在下方过滤即可
        Frame frame = null;
        int count = 0;
        while (i < length) {
            frame = ff.grabImage(); // 获取该帧图片流
            System.out.print(i + ",");
            if(frame!=null && frame.image!=null) {
                System.out.println(i);
                writeToFile(frame, picPath, count,second); // 生成帧图片
                count++;
            }
            i++;
        }
        ff.stop();
    }

    /**
     *
     * @param frame // 视频文件对象
     * @param picPath // 图片存放路径
     * @param count // 当前取到第几帧
     * @param second // 每隔多少帧取一张,一般高清视频每秒 20-24 帧,根据情况配置,如果全部提取,则将second设为 0 即可
     */
    public static void writeToFile(Frame frame, String picPath, int count, int second){
        if (second == 0) {
            // 跳过间隔取帧判断
        } else if (count % second != 0){ // 提取倍数,如每秒取一张,则: second = 20
           return;
        }
        File targetFile = new File(picPath + count + ".jpg");
        System.out.println("创建了文件:" + picPath + count + ".jpg");
        String imgSuffix = "jpg";

        Java2DFrameConverter converter =new Java2DFrameConverter();
        BufferedImage srcBi =converter.getBufferedImage(frame);
        int owidth = srcBi.getWidth();
        int oheight = srcBi.getHeight();
        // 对截取的帧进行等比例缩放
        int width = 800;
        int height = (int) (((double) width / owidth) * oheight);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH),0, 0, null);
        try {
            ImageIO.write(bi, imgSuffix, targetFile);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取视频时长,单位为秒
     * @param file
     * @return 时长(s)
     */
    public static Long getVideoTime(File file){
        Long times = 0L;
        try {
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
            ff.start();
            times = ff.getLengthInTime()/(1000*1000);
            ff.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return times;
    }
}

 

上一篇:javaCV开发详解之16:使用一张图片推流和一张图片录制成视频文件


下一篇:JavaCV入门指南:帧抓取器(FrameGrabber)的原理与应用