Java——使用javacv生成視訊縮圖
阿新 • • 發佈:2018-11-10
轉載大佬文章,以備後期再次需要,親測使用有效
新增依賴
在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; } }