1. 程式人生 > >使用javacv 截取視頻指定幀節

使用javacv 截取視頻指定幀節

ann ava depth cms web chan != red return


個人博客 地址: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;
	}

}

使用javacv 截取視頻指定幀節