java实现视频抽帧以及获取其他视频信息
1.在pom.xml文件中导入jar包
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.0.2-1.4.3</version>
</dependency>
2.创建工具类FetchVideoFrameUtil,复制以下代码文章来源:https://www.toymoban.com/news/detail-652970.html
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* Created with IDEA
* 视频取帧,可设置间隔秒数或获取所有帧数
*
* @Author shunzi
* @Date 2023/08/16 14:38:12
* @Description
* @Version 1.0
*/
@Slf4j
public class FetchVideoFrameUtil {
// 主函数
public static void main(String[] args){
try {
//批量处理,视频所在文件夹
String videoPath = "C:\\Users\\17386\\Desktop\\video\\normal video.mp4";
//输出图片文件夹
String picPath = "C:\\Users\\17386\\Desktop\\video-image3\\";
// 获取视频FPS
Double videoFrameRate = FetchVideoFrameUtil.getVideoFrameRate(new File(videoPath));
log.info("视频频率:{}", videoFrameRate);
// 根据FPS,动态计算抽帧速率。示例为:每秒取一帧
BigDecimal frameNumber = BigDecimal.valueOf(videoFrameRate);
BigDecimal frameDecimal = frameNumber.setScale(0, RoundingMode.HALF_UP);
// TODO 这里来更改抽帧速率,通过乘法运算来控制。比如:控制抽帧频率为2秒一帧,int second = 2 * frameDecimal.intValue()。以此类推
int second = frameDecimal.intValue();
log.info("抽帧频率:{}", second);
// 视频时长
log.info("视频总时长:{}", FetchVideoFrameUtil.getVideoTime(new File(videoPath)));
// 视频总帧数
log.info("视频总共帧数:{}", FetchVideoFrameUtil.getVideoFrameTotalLength(new File(videoPath)));
// 开始视频取帧流程
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("开始视频取帧流程=====开始时间" + sdf.format(new Date()));
List<File> files = FetchVideoFrameUtil.fetchPic(new File(videoPath), picPath, second);
System.out.println("结束视频取帧流程=====结束时间" + sdf.format(new Date()));
log.info("抽取的图片集合:{}", JSONObject.toJSONString(files));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取指定视频的帧并保存为图片至指定目录
* @param file 源视频文件
* @param picPath 截取帧的图片存放路径
* @throws Exception
*/
public static java.util.List<File> fetchPic(File file, String picPath, int second) throws Exception{
java.util.List<File> list = Lists.newArrayList();
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); // 获取视频文件
int length = FetchVideoFrameUtil.getVideoFrameTotalLength(file);
ff.start(); // 调用视频文件播放
int i = 0; // 图片帧数,如需跳过前几秒,则在下方过滤即可
org.bytedeco.javacv.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,list); // 生成帧图片
count++;
}
i++;
}
ff.stop();
return list;
}
/**
*
* @param frame // 视频文件对象
* @param picPath // 图片存放路径
* @param count // 当前取到第几帧
* @param second // 每隔多少帧取一张,一般高清视频每秒 20-24 帧,根据情况配置,如果全部提取,则将second设为 0 即可
* @param list // 返回文件结果
*/
public static void writeToFile(org.bytedeco.javacv.Frame frame, String picPath, int count, int second, java.util.List<File> list){
if (second == 0) {
// 跳过间隔取帧判断
} else if (count % second != 0){ // 提取倍数,如每秒取一张,则: second = 20
return;
}
File targetFile = new File(picPath + count + ".jpg");
System.out.println("创建了文件:" + picPath + count + ".jpg");
list.add(targetFile);
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;
}
/**
* 获取视频帧率,单位FPS
* @return
*/
public static Double getVideoFrameRate(File file) {
double frameRate = 0.0;
try {
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
ff.start();
frameRate = ff.getVideoFrameRate();
ff.stop();
} catch (FrameGrabber.Exception e) {
throw new RuntimeException(e);
}
return frameRate;
}
/**
* 获取视频真实格式
* @param file
* @return
*/
public static String getVideoRealFormat(File file){
String videoFormat = "";
try {
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
ff.start();
videoFormat = ff.getFormat();
ff.stop();
} catch (FrameGrabber.Exception e) {
throw new RuntimeException(e);
}
return videoFormat;
}
/**
* 获取视频总帧数长度
* @return
*/
public static int getVideoFrameTotalLength(File file) {
int frameCount = 0;
try {
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
ff.start();
org.bytedeco.javacv.Frame frame;
while ((frame = ff.grabImage()) != null) {
frameCount++;
}
ff.stop();
} catch (FrameGrabber.Exception e) {
throw new RuntimeException(e);
}
return frameCount;
}
}
文章引用出处:https://cloud.tencent.com/developer/article/1655887,并在原有基础上做了优化文章来源地址https://www.toymoban.com/news/detail-652970.html
到了这里,关于java实现视频抽帧以及获取其他视频信息的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!