需要引入依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.2</version>
</dependency>
<!-- <dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.0.2-1.4.3</version>
</dependency>-->
工具类
@Slf4j
public class VideoUtils {
// 获取要取得的帧数
private static final int GET_FRAMES_LENGTH = 5;
//截取视频图片格式
private static final String CONTENT_TYPE = "image/jpg";
/**
* zhangsk
* 获取视频第五帧图片,并转换成multipartFile流
* @param filePath 视频路径
* @return
*/
public static MultipartFile getScreenshot(String filePath) {
FFmpegFrameGrabber grabber;
MultipartFile multipartFile = null;
try {
log.info("开始处理视频获取第一帧");
log.info("视频文件地址"+filePath);
grabber = FFmpegFrameGrabber.createDefault(filePath);
// 第一帧图片存储位置(也是视频路径)
String targerFilePath = filePath.substring(0, filePath.lastIndexOf("/"));
log.info("第一帧图片存储位置"+targerFilePath);
// 视频文件名
String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
log.info("视频文件名"+fileName);
// 图片名称
String targetFileName = fileName.substring(0, fileName.lastIndexOf("."));
log.info("图片名称"+targetFileName);
grabber.start();
// 视频总帧数
int videoLength = grabber.getLengthInFrames();
Frame frame = null;
int i = 0;
while (i < videoLength) {
// 过滤前5帧,避免出现全黑的图片,依自己情况而定(每循环一次取一帧)
frame = grabber.grabFrame();
if ((i > GET_FRAMES_LENGTH) && (frame.image != null)) {
break;
}
i++;
}
Java2DFrameConverter converter = new Java2DFrameConverter();
// 绘制图片
BufferedImage bi = converter.getBufferedImage(frame);
// 图片的类型
String imageMat = "jpg";
// 图片的完整路径
String imagePath = targerFilePath + File.separator + targetFileName + "." + imageMat;
// 创建文件
File output = new File(imagePath);
ImageIO.write(bi, imageMat, output);
multipartFile = new MockMultipartFile("file", output.getName(), imageMat, new FileInputStream(output));
grabber.stop();
log.info("获取视频第一帧结束");
return multipartFile;
} catch (IOException e) {
e.printStackTrace();
}
return multipartFile;
}
/**
* zhangsk
* 根据路径采用url链接方式获取视频输入流来处理 推荐使用 推荐使用
* @param path 视频链接地址
* @return
*/
public static MultipartFile grabberVideoFramer(String path ,Integer frameLength) {
if (null == frameLength) {
frameLength = GET_FRAMES_LENGTH;
}
log.info("截取视频第几帧+"+frameLength);
// 视频文件名
String fileName = path.substring(path.lastIndexOf("/") + 1);
log.info("视频文件名"+fileName);
// 图片名称
String targetFileName = fileName.substring(0, fileName.lastIndexOf("."));
log.info("图片名称"+targetFileName);
// Frame对象
Frame frame = null;
MultipartFile multipartFile = null;
// 标识
int flag = 0;
try {
log.info("开始处理视频获取截图");
/*
获取视频文件
*/
URL url =new URL(path);
//利用HttpURLConnection对象,我们可以从网络中获取网页数据.
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.connect();
log.info("建立connect链接");
InputStream inputStream= conn.getInputStream();
FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(inputStream);
fFmpegFrameGrabber.start();
log.info("fFmpegFrameGrabber启动");
// 获取视频总帧数
int ftp = fFmpegFrameGrabber.getLengthInFrames();
log.info("时长 " + ftp / fFmpegFrameGrabber.getFrameRate() / 60);
while (flag <= ftp) {
frame = fFmpegFrameGrabber.grabImage();
/*
对视频的第五帧进行处理
*/
if (frame != null && flag == frameLength) {
log.info("获取第" + flag + "帧");
BufferedImage bufferedImage= FrameToBufferedImage(frame);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", out);
byte[] b = out.toByteArray();
fFmpegFrameGrabber.stop();
multipartFile = new MockMultipartFile("file",targetFileName,CONTENT_TYPE, b);
fFmpegFrameGrabber.close();
log.info("获取视频第一帧结束");
return multipartFile;
}
flag++;
}
} catch (Exception E) {
log.info("视频处理工具里失败:{}",E);
E.printStackTrace();
}
return multipartFile;
}
/**
* 创建缓冲流
* @param frame
* @return
*/
public static BufferedImage FrameToBufferedImage(Frame frame) {
// 创建BufferedImage对象
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bufferedImage = converter.getBufferedImage(frame);
return bufferedImage;
}
/**
*
* 一体化处理视频获取视频第一帧图片方式
* @param fileUrl
* @return
* @throws IOException
*/
public static MultipartFile fetchFrame(String fileUrl) throws IOException {
MultipartFile multipartFile = null;
String picPath = fileUrl.substring(0, fileUrl.indexOf("."));
String videoPic = picPath.concat(".jpg");
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(fileUrl);
ff.start();
int length = ff.getLengthInFrames();
int i = 0;
Frame f = null;
while (i < length) {
f = ff.grabFrame();
if ((i > 5) && (f.image != null)) {
break;
}
i++;
}
int owidth = f.imageWidth;
int oheight = f.imageHeight;
// 对截取的帧进行等比例缩放
int width = 800;
int height = (int) (((double) width / owidth) * oheight);
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage fecthedImage = converter.getBufferedImage(f);
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
ByteArrayOutputStream out = new ByteArrayOutputStream();
bi.getGraphics().drawImage(fecthedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH),
0, 0, null);
ImageIO.write(bi, "jpg", out);
byte[] bytes = out.toByteArray();
multipartFile = new MockMultipartFile("file", bytes);
ff.flush();
ff.stop();
return multipartFile;
}
/**
* zhangsk
* 直接采用视频输入流进行处理
* @param inputStream 视频输入流
* @param fileUrl 视频路径
* @return 返回multipartfile流
* @throws IOException io异常
*/
public static MultipartFile grabberVideoFramer02(InputStream inputStream ,String fileUrl) throws IOException {
log.info("开始处理视频获取截图");
// 视频文件名
String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
log.info("视频文件名"+fileName);
// 图片名称
String targetFileName = fileName.substring(0, fileName.lastIndexOf("."));
log.info("图片名称"+targetFileName);
MultipartFile multipartFile = null;
// 最后获取到的视频的图片缓存
BufferedImage bufferedImage = null;
// Frame对象
Frame frame = null;
// 标识
int flag = 0;
FFmpegFrameGrabber fFmpegFrameGrabber = null;
try {
//获取视频文件
fFmpegFrameGrabber = new FFmpegFrameGrabber(inputStream);
fFmpegFrameGrabber.start();
log.info("fFmpegFrameGrabber启动");
// 获取视频总帧数
int ftp = fFmpegFrameGrabber.getLengthInFrames();
log.info("视频总帧数"+ftp);
//对视屏 帧数处理
while (flag <= ftp) {
frame = fFmpegFrameGrabber.grabImage();
//对视频的第5帧进行处理
if (frame != null && flag == ftp/GET_FRAMES_LENGTH) {
// 图片缓存对象
bufferedImage = FrameToBufferedImage(frame);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", out);
byte[] b = out.toByteArray();
multipartFile = new MockMultipartFile("file",targetFileName,CONTENT_TYPE, b);
log.info("获取到图片multipartFile流"+multipartFile);
return multipartFile;
}
flag++;
}
}finally {
if(fFmpegFrameGrabber != null) {
fFmpegFrameGrabber.stop();
fFmpegFrameGrabber.close();
log.info("视频处理结束");
}
}
log.info("无法获取,出现异常");
return multipartFile;
}
}