1. 程式人生 > >Java——使用javacv生成視訊縮圖

Java——使用javacv生成視訊縮圖

轉載大佬文章,以備後期再次需要,親測使用有效

新增依賴

在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;
	}
 
}