轉載請注明出處:https://blog.csdn.net/l1028386804/article/details/79755510
一、建立項目
1、建立Maven項目
2、添加依賴
在pom.xml中添加依賴配置,具體如下:
<dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
二、具體實作
1、擷取視訊中間的幀作為縮略圖,并傳回縮略圖實際存放位址
package com.lyz.medis.image;
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.FrameGrabber.Exception;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
/**
* 擷取視訊縮略圖
* @author liuyazhuang
*
*/
public class VideoImage {
private static final String IMAGEMAT = "png";
private static final String ROTATE = "rotate";
/**
* 預設截取視訊的中間幀為封面
*/
public static final int MOD = 2;
public static void main(String[] args) throws Exception {
System.out.println(randomGrabberFFmpegImage("C:/lyz/1522372294724_79583.mov", 2));
}
/**
* 擷取視訊縮略圖
* @param filePath:視訊路徑
* @param mod:視訊長度/mod擷取第幾幀
* @throws Exception
*/
public static String randomGrabberFFmpegImage(String filePath, int mod) throws Exception {
String targetFilePath = "";
FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
ff.start();
String rotate = ff.getVideoMetadata(ROTATE);
int ffLength = ff.getLengthInFrames();
Frame f;
int i = 0;
int index = ffLength / mod;
while (i < ffLength) {
f = ff.grabImage();
if(i == index){
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 = getImagePath(filePath, i);
doExecuteFrame(f, targetFilePath);
break;
}
i++;
}
ff.stop();
return targetFilePath;
}
/**
* 根據視訊路徑生成縮略圖存放路徑
* @param filePath:視訊路徑
* @param index:第幾幀
* @return:縮略圖的存放路徑
*/
private static String getImagePath(String filePath, int index){
if(filePath.contains(".") && filePath.lastIndexOf(".") < filePath.length() - 1){
filePath = filePath.substring(0, filePath.lastIndexOf(".")).concat("_").concat(String.valueOf(index)).concat(".").concat(IMAGEMAT);
}
return filePath;
}
/**
* 旋轉圖檔
* @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 f
* @param targerFilePath:封面圖檔
*/
public static void doExecuteFrame(Frame f, String targerFilePath) {
if (null == f || null == f.image) {
return;
}
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bi = converter.getBufferedImage(f);
File output = new File(targerFilePath);
try {
ImageIO.write(bi, IMAGEMAT, output);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 根據視訊長度随機生成随機數集合
* @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;
}
}
2、随機生成多張縮略圖,不傳回縮略圖實際存放位址
package com.lyz.medis.image;
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.FrameGrabber.Exception;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
/**
* 擷取圖檔縮略圖
* @author liuyazhuang
*
*/
public abstract class VideoImageFrame {
public static void main(String[] args) throws Exception {
randomGrabberFFmpegImage("e:/lyz/ffmpeg.mp4", "./target", "screenshot", 5);
}
/**
* 生成圖檔縮略圖
* @param filePath:視訊完整路徑
* @param targerFilePath:縮略圖存放目錄
* @param targetFileName:縮略圖檔案名稱
* @param randomSize:生成随機數的數量
* @throws Exception
*/
public static void randomGrabberFFmpegImage(String filePath, String targerFilePath, String targetFileName, int randomSize) throws Exception {
FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);
ff.start();
String rotate = ff.getVideoMetadata("rotate");
int ffLength = ff.getLengthInFrames();
List<Integer> randomGrab = random(ffLength, randomSize);
int maxRandomGrab = randomGrab.get(randomGrab.size() - 1);
Frame f;
int i = 0;
while (i < ffLength) {
f = ff.grabImage();
if (randomGrab.contains(i)) {
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)));
}
doExecuteFrame(f, targerFilePath, targetFileName, i);
}
if (i >= maxRandomGrab) {
break;
}
i++;
}
ff.stop();
}
/**
* 旋轉圖檔
* @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 f Frame對象
* @param targerFilePath
* @param targetFileName
* @param index
*/
public static void doExecuteFrame(Frame f, String targerFilePath, String targetFileName, int index) {
if (null == f || null == f.image) {
return;
}
Java2DFrameConverter converter = new Java2DFrameConverter();
String imageMat = "png";
String FileName = targerFilePath + File.separator + targetFileName + "_" + index + "." + imageMat;
BufferedImage bi = converter.getBufferedImage(f);
File output = new File(FileName);
try {
ImageIO.write(bi, imageMat, output);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 随機生成随機數集合
* @param baseNum:随機種子
* @param length:随機數集合長度
* @return:随機數集合
*/
public static List<Integer> random(int baseNum, int length) {
List<Integer> list = new ArrayList<>(length);
while (list.size() < length) {
Integer next = (int) (Math.random() * baseNum);
if (list.contains(next)) {
continue;
}
list.add(next);
}
Collections.sort(list);
return list;
}
}