截取视频封面所需jar
ffmpeg-4.1-1.4.4-windows-x86.jar
javacpp-1.4.4.jar
ffmpeg-4.1-1.4.4.jar
javacv-1.4.4.jar
opencv-4.0.1-1.4.4.jar
注意: ffmpeg-4.1-1.4.4-windows-x86.jar
是根据不同的环境所选取的,
如果不添加该jar包会报异常
Exception in thread “main” java.lang.NoClassDefFoundError: Could not initialize class org.bytedeco.javacpp.avutil
该jar 包获取路径
https://repo1.maven.org/maven2/org/bytedeco/javacpp-presets/ffmpeg/4.1-1.4.4/
实现代码
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
public class VideoCover {
public static String image_type="jpg";
public static String file_type="mp4";
public static void main(String[] args) {
String videofile="F:/VideoCover/Video/Adhere.mp4";//或网络视频地址
String framefileDir="F:/VideoCover/Img/";
String targetFilePath=fetchFrame(videofile,framefileDir);
System.out.println(targetFilePath);
}
/**
* 获取指定视频的帧并保存为图片至指定目录
* @param videofile 源视频文件路径
* @param framefileDir 截取帧的图片存放路径
* @throws Exception
*/
public static String fetchFrame(String videofile, String framefileDir){
try{
int startIndex=videofile.lastIndexOf('/');
String fileName;
if(startIndex==-1){
fileName=videofile.substring(videofile.lastIndexOf('\\')+1, videofile.lastIndexOf('.'));
}else{
fileName=videofile.substring(startIndex+1, videofile.lastIndexOf('.')+1);
}
String targetFileName=framefileDir+fileName+image_type;
File targetFile=createFile(targetFileName);
FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(videofile);
ff.start();
String rotate_old=ff.getVideoMetadata("rotate");//视频旋转角度,可能是null
int length = ff.getLengthInFrames();
int i = 0;
Frame f = null;
while (i < length) {
// 过滤前5帧,避免出现全黑的图片,依自己情况而定
f = ff.grabFrame();
if ((i > 5) && (f.image != null)) {
break;
}
i++;
}
int owidth = f.imageWidth;
int oheight = f.imageHeight;
// 对截取的帧进行等比例缩放
int width = 800;//生成图片宽度为800px
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);
bi.getGraphics().drawImage(fecthedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH),
0, 0, null);
ImageIO.write(bi, image_type, targetFile);
ff.stop();
//有需要旋转
if(rotate_old!=null && !rotate_old.isEmpty()){
int rotate=Integer.parseInt(rotate_old);
rotatePhonePhoto(targetFileName,rotate);
}
return targetFileName;
}catch(Exception e){
e.printStackTrace();
}
return null;
}
/**
* 创建文件,目录不存在则先创建目录在创建文件
* @param destFileName
* @return
*/
public static File createFile(String destFileName) {
try {
File file = new File(destFileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
return file;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 删除单个文件
* @param sPath
*/
public static void deleteFile(String sPath) {
File file = new File(sPath);
if (file.isFile() && file.exists()) {
file.delete();
}
}
/**
* 旋转照片
* @param fullPath
* @param angel
* @return
*/
public static String rotatePhonePhoto(String fullPath, int angel) {
BufferedImage src;
try {
src = ImageIO.read(new File(fullPath));
int src_width = src.getWidth(null);
int src_height = src.getHeight(null);
int swidth = src_width;
int sheight = src_height;
if (angel == 90 || angel == 270) {
swidth = src_height;
sheight = src_width;
}
Rectangle rect_des = new Rectangle(new Dimension(swidth, sheight));
BufferedImage res = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = res.createGraphics();
g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
g2.drawImage(src, null, null);
ImageIO.write(res,image_type, new File(fullPath));
} catch (Exception e) {
e.printStackTrace();
}
return fullPath;
}
}