我的博客 地址:https://www.wenhaofan.com/article/20190407105818
引入依賴
<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>
代碼案例
package live.autu.ctcms.common.kit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.Ret;
public class VideoFrameUtil {
private static String rootPath = PathKit.getWebRootPath() + "/video/img";// 服務器路徑
private static final String IMAGEMAT = "png"; // 圖片格式
private static final String ROTATE = "rotate";
public static final int MOD = 1;// 第一幀
public static Ret getVideoFirstFrame(String videoPath, String imageName) {
return getVideoFrame(videoPath, imageName, MOD);
}
/**
* 獲取視頻縮略圖
*
* @param lpath
* @param filePath:視頻路徑
* @param mod:視頻長度/mod獲取第幾幀
* @throws Exception
*/
public static Ret getVideoFrame(String filePath, String targetImageName, int mod) {
// 根據視頻路徑生成縮略圖存放路徑
String targetFilePath = null;
try (FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);) {
ff.start();
String rotate = ff.getVideoMetadata(ROTATE);
int ffLength = ff.getLengthInFrames();
Frame f = null;
int i = 0;
int index = mod;
if (i >= ffLength) {
return Ret.fail();
}
for (int j = 0; j <= index; j++) {
f = ff.grabImage();
}
if (null != rotate && rotate.length() > 1) {
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
IplImage src = converter.convert(f);
f = converter.convert(rotate(src, Integer.valueOf(rotate))); // 旋轉圖片
}
targetFilePath = doExecuteFrame(f, targetImageName);
ff.stop();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Ret.ok("targetFilePath",targetFilePath)
.set("relativeFilePath", "/video/img/"+targetImageName); // 返回的是視頻第一幀
}
/**
* 旋轉圖片
*
* @param src
* @param angle
* @return
*/
public static IplImage rotate(IplImage src, int angle) {
IplImage img = IplImage.create(src.height(), src.width(), src.depth(), src.nChannels());
opencv_core.cvTranspose(src, img);
opencv_core.cvFlip(img, img, angle);
return img;
}
/**
* 根據視頻路徑生成縮略圖存放路徑
*
* @param filePath:視頻路徑
* @param index:第幾幀
* @return:縮略圖的存放路徑
*/
private static String getImagePath(String fileName) {
return rootPath+"/" + fileName;
}
/**
* 截取縮略圖
*
* @param f
* @param targerFilePath:封面圖片
* @throws IOException
*/
public static String doExecuteFrame(Frame f, String lpath) throws IOException {
if(!new File(rootPath).exists()) {
new File(rootPath).mkdirs();
}
String targerFilePath = getImagePath(lpath);
if (null == f || null == f.image) {
return null;
}
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bi = converter.getBufferedImage(f);
File output = new File(targerFilePath);
output.createNewFile();
ImageIO.write(bi, IMAGEMAT, output);
return targerFilePath;
}
/**
* 根據視頻長度隨機生成隨機數集合
*
* @param baseNum:基礎數字,此處爲視頻長度
* @param length:隨機數集合長度
* @return:隨機數集合
*/
public static List<Integer> random(int baseNum, int length) {
List<Integer> list = new ArrayList<Integer>(length);
while (list.size() < length) {
Integer next = (int) (Math.random() * baseNum);
if (list.contains(next)) {
continue;
}
list.add(next);
}
Collections.sort(list);
return list;
}
}