Java之如何截取视频第一帧
作者:上官天夜
这篇文章主要介绍了Java之如何截取视频第一帧问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
Java截取视频第一帧
方法一:使用第三方jar包截取
1、导入依赖
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>0.8</version> </dependency>
2、示例
package com.zemel.video; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; import org.bytedeco.javacpp.opencv_core.IplImage; import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Frame; public class Test { /** * 获取指定视频的帧并保存为图片至指定目录 * @param videofile 源视频文件路径 * @param framefile 截取帧的图片存放路径 * @throws Exception */ public static void fetchFrame(String videofile, String framefile) throws Exception { long start = System.currentTimeMillis(); File targetFile = new File(framefile); FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile); ff.start(); int lenght = ff.getLengthInFrames(); int i = 0; Frame f = null; while (i < lenght) { // 过滤前5帧,避免出现全黑的图片,依自己情况而定 f = ff.grabFrame(); if ((i > 5) && (f.image != null)) { break; } i++; } IplImage img = f.image; int owidth = img.width(); int oheight = img.height(); // 对截取的帧进行等比例缩放 int width = 800; int height = (int) (((double) width / owidth) * oheight); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); ImageIO.write(bi, "jpg", targetFile); //ff.flush(); ff.stop(); System.out.println(System.currentTimeMillis() - start); } public static void main(String[] args) { try { Test.fetchFrame("D:\\biudata\\vedio\\1523598768844GFE2GWDDM8.mp4", "D:\\biudata\\vedio\\test5.jpg"); } catch (Exception e) { e.printStackTrace(); } } }
方法二:使用ffmpeg
1、下载ffmpeg工具(http://ffmpeg.org/)
2、代码
public static boolean processImg(String veido_path, String ffmpeg_path) { File file = new File(veido_path); if (!file.exists()) { System.err.println("路径[" + veido_path + "]对应的视频文件不存在!"); return false; } List<String> commands = new java.util.ArrayList<String>(); commands.add(ffmpeg_path); commands.add("-i"); commands.add(veido_path); commands.add("-y"); commands.add("-f"); commands.add("image2"); commands.add("-ss"); commands.add("8");// 这个参数是设置截取视频多少秒时的画面 // commands.add("-t"); // commands.add("0.001"); commands.add("-s"); commands.add("700x525"); commands.add(veido_path.substring(0, veido_path.lastIndexOf(".")) .replaceFirst("vedio", "file") + ".jpg"); try { ProcessBuilder builder = new ProcessBuilder(); builder.command(commands); builder.start(); System.out.println("截取成功"); return true; } catch (Exception e) { e.printStackTrace(); return false; } } public static void main(String[] args) { processImg("D:\\biudata\\vedio\\15235879054813G0I1783E2.mp4", "F:\\开发工具\\ffmpeg.exe"); }
Java截取视频第一帧返回InputStream,用于视频上传后作为封面
引入maven依赖
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.4.3</version> </dependency>
因为上面的依赖包含的jar包太多,所以我们需要排除一些东西
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.3</version> <exclusions> <exclusion> <groupId>org.bytedeco</groupId> <artifactId>javacpp</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flycapture</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libdc1394</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect2</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>librealsense</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>videoinput</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>tesseract</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>leptonica</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flandmark</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>artoolkitplus</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.4.3</version> <exclusions> <exclusion> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flycapture-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libdc1394-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>libfreenect2-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>librealsense-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>videoinput-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>tesseract-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>leptonica-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>flandmark-platform</artifactId> </exclusion> <exclusion> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>artoolkitplus-platform</artifactId> </exclusion> </exclusions> </dependency>
获取视频帧返回InputStream
public class getImgUtil { // 获取要取得的帧数 private static final int fifthFrame= 5; /** * @param InputStream 需要截取帧的视频的字节输入流 * * @return */ public static InputStream getImg(InputStream is) { FFmpegFrameGrabber grabber; InputStream img=null ; try { grabber = new FFmpegFrameGrabber(is); grabber.start(); // 视频总帧数 int videoLength = grabber.getLengthInFrames(); Frame frame = null; int i = 0; while (i < videoLength) { // 过滤前5帧,因为前5帧可能是全黑的 frame = grabber.grabFrame(); if ((i > fifthFrame) && (frame.image != null)) { break; } i++; } Java2DFrameConverter converter = new Java2DFrameConverter(); // 绘制图片 BufferedImage bi = converter.getBufferedImage(frame); img = bufferedImageToInputStream(bi); grabber.stop(); grabber.close(); } catch (IOException e) { e.printStackTrace(); } return img; } /** * 将BufferedImage转换为InputStream * @param image * @return */ public static InputStream bufferedImageToInputStream(BufferedImage image){ ByteArrayOutputStream os = new ByteArrayOutputStream(); try { ImageIO.write(image, "png", os); InputStream input = new ByteArrayInputStream(os.toByteArray()); return input; } catch (IOException e) { } return null; }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。