JavaCV 进行视频操作

1、JavaCV实现将视频以帧方式抽取

java 复制代码
## JavaCV实现将视频以帧方式抽取

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

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

import static org.bytedeco.javacpp.opencv_core.IplImage;
import static org.bytedeco.javacpp.opencv_core.cvReleaseImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvSaveImage;
import static org.bytedeco.javacpp.opencv_imgproc.cvSmooth;

public class JavaCV {

  // the image's path;
  final static String imagePath = "/home/lance/abc.jpg/";
  // the vedio's path and filename;
  final static String vedioPath = "/home/lance/target-a/";
  final static String vedioName = "origin-a.mp4";


  public static void main(String[] args) throws Exception {
    smooth(imagePath);
    grabberFFmpegImage(vedioPath + vedioName, vedioPath
        , vedioName, 30);
  }

  // the method of compress image;
  public static void smooth(String fileName) {
    IplImage iplImage = cvLoadImage(fileName);
    if (iplImage != null) {
      cvSmooth(iplImage, iplImage);
      cvSaveImage(fileName, iplImage);
      cvReleaseImage(iplImage);
    }
  }

  // grab ffmpegImage from vedio;
  public static void grabberFFmpegImage(String filePath, String fileTargetPath
      , String fileTargetName, int grabSize) throws Exception{
    FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
    ff.start();
    for (int i = 0; i < grabSize; i++){
      Frame frame = ff.grabImage();
      doExecuteFrame(frame, filePath, fileTargetName, i);
    }
    ff.stop();
  }

  // grab frame from vedio;
  public static void doExecuteFrame(Frame frame, String targetFilePath, String targetFileName, int index) {
    if ( frame == null || frame.image == null) {
      return;
    }
    Java2DFrameConverter converter = new Java2DFrameConverter();
    String imageMat = "jpg";
    String fileName = targetFilePath + File.pathSeparator + targetFileName + "_" + index + "." + imageMat;
    BufferedImage bi = converter.getBufferedImage(frame);
    File output = new File(fileName);
    try{
      ImageIO.write(bi, imageMat, output);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

2、javaCV视频取

GitHub路径:

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

pom文件中的Maven配置:

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

实例代码:

java 复制代码
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;
    }
}

3、Java从视频内截取指定时间的图

此例子可用于:视频内截取某一帧作为封面图(可指定时间)、需要视频内某张图用作表情包。。。

java 复制代码
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;

public class VideoUtil {

    public static void main(String[] args) {
        try {
            getImgFromVideo("D:\\ffmpeg\\ffmpeg2016\\bin\\ffmpeg.exe", "d:\\ys\\StoryBrooke.mp4", "d:\\ys\\lain.jpg", 204, 140, 0, 0, 26);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 获取指定时间内的图片
     * @param ffmpegPath (ffmpeg路径)
     * @param videoPath (视频路径)
     * @param imgPath (图片存放路径)
     * @param width (图片宽度)
     * @param height (图片高度)
     * 以下为需要指定的时间
     * @param hour
     * @param min
     * @param sec
     * @return
     */
    public static boolean getImgFromVideo(String ffmpegPath, String videoPath, String imgPath, int width,
            int height, int hour, int min, float sec) {
        try {
            ProcessBuilder processBuilder = new ProcessBuilder(ffmpegPath, "-y",
                    "-i", videoPath, "-vframes", "1", "-ss", hour + ":" + min
                            + ":" + sec, "-f", "mjpeg", "-s", width + "*" + height,
                    "-an", imgPath);

            Process process = processBuilder.start();
            InputStream stderr = process.getErrorStream();
            InputStreamReader isr = new InputStreamReader(stderr);
            BufferedReader br = new BufferedReader(isr);
            while ((br.readLine()) != null);
            process.waitFor();
            if (br != null)
                br.close();
            if (isr != null)
                isr.close();
            if (stderr != null)
                stderr.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

4、Javacv截取视频图片

java 复制代码
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

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

import static org.bytedeco.javacpp.opencv_core.IplImage;
import static org.bytedeco.javacpp.opencv_core.cvReleaseImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvSaveImage;
import static org.bytedeco.javacpp.opencv_imgproc.cvSmooth;

public class JavaCV {

  // the image's path;
  final static String imagePath = "/home/lance/abc.jpg/";
  // the vedio's path and filename;
  final static String vedioPath = "/home/lance/target-a/";
  final static String vedioName = "origin-a.mp4";


  public static void main(String[] args) throws Exception {
    smooth(imagePath);
    grabberFFmpegImage(vedioPath + vedioName, vedioPath
        , vedioName, 30);
  }

  // the method of compress image;
  public static void smooth(String fileName) {
    IplImage iplImage = cvLoadImage(fileName);
    if (iplImage != null) {
      cvSmooth(iplImage, iplImage);
      cvSaveImage(fileName, iplImage);
      cvReleaseImage(iplImage);
    }
  }

  // grab ffmpegImage from vedio;
  public static void grabberFFmpegImage(String filePath, String fileTargetPath
      , String fileTargetName, int grabSize) throws Exception{
    FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
    ff.start();
    for (int i = 0; i < grabSize; i++){
      Frame frame = ff.grabImage();
      doExecuteFrame(frame, filePath, fileTargetName, i);
    }
    ff.stop();
  }

  // grab frame from vedio;
  public static void doExecuteFrame(Frame frame, String targetFilePath, String targetFileName, int index) {
    if ( frame == null || frame.image == null) {
      return;
    }
    Java2DFrameConverter converter = new Java2DFrameConverter();
    String imageMat = "jpg";
    String fileName = targetFilePath + File.pathSeparator + targetFileName + "_" + index + "." + imageMat;
    BufferedImage bi = converter.getBufferedImage(frame);
    File output = new File(fileName);
    try{
      ImageIO.write(bi, imageMat, output);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
相关推荐
Propeller13 分钟前
【Android】View 交互的事件处理机制
android·java
杨杨杨大侠17 分钟前
Atlas Mapper 教程系列 (5/10):集合映射与嵌套对象处理
java·开源·github
ERP老兵_冷溪虎山18 分钟前
Python/JS/Go/Java同步学习(第十三篇)四语言“字符串转码解码“对照表: 财务“小南“纸式转码术处理凭证乱码崩溃(附源码/截图/参数表/避坑指南)
java·后端·python
是2的10次方啊18 分钟前
如何设计10万QPS秒杀系统?缓存+消息队列+分布式锁架构实战
java
心灵宝贝19 分钟前
Tomcat Connectors 1.2.37 源码编译安装教程(mod_jk 详细步骤)
java·tomcat
杨杨杨大侠22 分钟前
Atlas Mapper 教程系列 (6/10):Spring Boot 集成与自动配置
java·开源·github
傻傻虎虎32 分钟前
【Docker】容器端口暴露+镜像生成实战
java·docker·容器
练习时长一年42 分钟前
搭建langchain4j+SpringBoot的Ai项目
java·spring boot·后端
九术沫1 小时前
装饰器模式在Spring中的案例
java·spring·装饰器模式
Rysxt_1 小时前
Spring Boot 集成 Spring AI OpenAI Starter 教程
java·spring boot·后端·ai