java實(shí)現(xiàn)視頻抽幀以及獲取其他視頻信息
1.在pom.xml文件中導(dǎo)入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.創(chuàng)建工具類FetchVideoFrameUtil,復(fù)制以下代碼文章來源:http://www.zghlxwxcb.cn/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
* 視頻取幀,可設(shè)置間隔秒數(shù)或獲取所有幀數(shù)
*
* @Author shunzi
* @Date 2023/08/16 14:38:12
* @Description
* @Version 1.0
*/
@Slf4j
public class FetchVideoFrameUtil {
// 主函數(shù)
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);
// 根據(jù)FPS,動(dòng)態(tài)計(jì)算抽幀速率。示例為:每秒取一幀
BigDecimal frameNumber = BigDecimal.valueOf(videoFrameRate);
BigDecimal frameDecimal = frameNumber.setScale(0, RoundingMode.HALF_UP);
// TODO 這里來更改抽幀速率,通過乘法運(yùn)算來控制。比如:控制抽幀頻率為2秒一幀,int second = 2 * frameDecimal.intValue()。以此類推
int second = frameDecimal.intValue();
log.info("抽幀頻率:{}", second);
// 視頻時(shí)長
log.info("視頻總時(shí)長:{}", FetchVideoFrameUtil.getVideoTime(new File(videoPath)));
// 視頻總幀數(shù)
log.info("視頻總共幀數(shù):{}", FetchVideoFrameUtil.getVideoFrameTotalLength(new File(videoPath)));
// 開始視頻取幀流程
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("開始視頻取幀流程=====開始時(shí)間" + sdf.format(new Date()));
List<File> files = FetchVideoFrameUtil.fetchPic(new File(videoPath), picPath, second);
System.out.println("結(jié)束視頻取幀流程=====結(jié)束時(shí)間" + 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(); // 調(diào)用視頻文件播放
int i = 0; // 圖片幀數(shù),如需跳過前幾秒,則在下方過濾即可
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 // 視頻文件對(duì)象
* @param picPath // 圖片存放路徑
* @param count // 當(dāng)前取到第幾幀
* @param second // 每隔多少幀取一張,一般高清視頻每秒 20-24 幀,根據(jù)情況配置,如果全部提取,則將second設(shè)為 0 即可
* @param list // 返回文件結(jié)果
*/
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){ // 提取倍數(shù),如每秒取一張,則: second = 20
return;
}
File targetFile = new File(picPath + count + ".jpg");
System.out.println("創(chuàng)建了文件:" + 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();
// 對(duì)截取的幀進(jìn)行等比例縮放
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();
}
}
/**
* 獲取視頻時(shí)長,單位為秒
* @param file
* @return 時(shí)長(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;
}
/**
* 獲取視頻真實(shí)格式
* @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;
}
/**
* 獲取視頻總幀數(shù)長度
* @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,并在原有基礎(chǔ)上做了優(yōu)化文章來源地址http://www.zghlxwxcb.cn/news/detail-652970.html
到了這里,關(guān)于java實(shí)現(xiàn)視頻抽幀以及獲取其他視頻信息的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!