使用javacv获取视频(本地视频文件、视频链接)中的帧,保存成图片或者base64串
POM文件引入依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv-platform</artifactId>
<version>3.4.1-1.4.1</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>3.4.2-1.4.1</version>
</dependency>
提取视频帧
package com.mf.video;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import java.util.List;
/**
* @Author KeXin
* @Date 2021/2/1 下午3:07
**/
public class VideoUtil {
/**
* base64字符串转换成图片
* @param imgStr base64字符串
* @param imgFilePath 图片存放路径
*/
private static void base64ToImage(String imgStr, String imgFilePath) {
try {
byte[] buffer = new BASE64Decoder().decodeBuffer(imgStr);
FileOutputStream out = new FileOutputStream(imgFilePath);
out.write(buffer);
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 将截取的帧生成文件或者生成base64
* @param frame
* @return
*/
private static String getBase64FromFrame(Frame frame) {
String imgFormat = "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 {
ByteArrayOutputStream output = new ByteArrayOutputStream();
// ImageIO工具类提供了将图片写成文件或者outputStream中
// ImageIO.write(bi, imgFormat, targetFile);
ImageIO.write(srcBi, imgFormat, output);
// 这里需要获取图片的base64数据串,所以将图片写到流里面
return new BASE64Encoder().encode(output.toByteArray());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取指定视频的帧并保存为图片至指定目录
*
* @param fileUrl 源视频文件Url路径
* @param stepSecond 每隔几秒取一帧,默认1200s
* @param count 最多获取几帧
* @return 返回截取的帧的Base64串列表
* @throws Exception
*/
public static List<String> fetchPicFromVideo(String fileUrl, Integer stepSecond, Integer count) throws Exception {
List<String> picBase64List = new ArrayList<>();
stepSecond = stepSecond == null ? 1200 : stepSecond;
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(fileUrl);
ff.start();
long timeLength = ff.getLengthInTime();
Frame frame = ff.grabImage();
long startTime = frame.timestamp;
long timestamp = 0;
int second = 0;
int picNum = 0;
while (timestamp <= timeLength) {
timestamp = startTime + second * 1000000L;
ff.setTimestamp(timestamp);
frame = ff.grabImage();
if (frame != null) {
if (frame.image != null) {
picBase64List.add(getBase64FromFrame(frame));
picNum++;
if (count != null && picNum == count) {
break;
}
}
}
second += stepSecond;
}
ff.stop();
return picBase64List;
}
public static void main(String[] args) {
try {
String outputPath = "/Users/kexin/work/projects/learn/MavenUtil/output";
String videoPath = "https:*********165dd278762865.mp4";
List<String> files = VideoUtil.fetchPicFromVideo(videoPath, 600, 8);
// 为了验证base64串的正确性,解码生成图片文件
for (String imgBase64 : files) {
String fileName = String.valueOf(System.currentTimeMillis());
String targetFile = outputPath + File.separator + fileName + ".jpg";
base64ToImage(imgBase64, targetFile);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
还没有评论,来说两句吧...