近期做一个官网需要将官网上传的视频的某一帧作为封面截图。说实在的,自己也没有做过,但是好在经过不屑努力找到了一些资料,在这里仅供参考。
一、此项目是一个Maven项目,因此只需要将下面的依赖引入即可
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacpp</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv-platform</artifactId> <version>3.4.1-1.4.1</version> </dependency> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>ffmpeg-platform</artifactId> <version>3.4.2-1.4.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency>
二、编写视频处理工具类如下
package com.basic.common.utils; import org.bytedeco.javacv.*; import org.bytedeco.javacv.Frame; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; /** * @author summer * @date 2021-11-02 15:02 */ public class VideoUtils { /** * 获取指定视频的帧并保存为图片 * @param file 源视频文件地址 * @param framefile 截取帧的图片存放地址 * @throws Exception */ public static void fetchPic(File file, String framefile) throws Exception{ FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); ff.start(); int lenght = ff.getLengthInFrames(); File targetFile = new File(framefile); int i = 0; Frame frame = null; while (i < lenght) { // 过滤前5帧,避免出现全黑的图片,依自己情况而定 frame = ff.grabFrame(); if ((i > 5) && (frame.image != null)) { break; } i++; } String imgSuffix = "jpg"; if(framefile.indexOf('.') != -1){ String[] arr = framefile.split("\\."); if(arr.length>=2){ imgSuffix = arr[1]; } } Java2DFrameConverter converter =new Java2DFrameConverter(); BufferedImage srcBi =converter.getBufferedImage(frame); int owidth = srcBi.getWidth(); int oheight = srcBi.getHeight(); // 对截取的帧进行等比例缩放 int width = 800; int height = (int) (((double) width / owidth) * oheight); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH),0, 0, null); try { ImageIO.write(bi, imgSuffix, targetFile); }catch (Exception e) { e.printStackTrace(); } ff.stop(); } /** * 获取视频时长,单位为秒 * @param file 即为视频地址 * @return 时长(秒) */ public static Long getVideoTime(File file){ Long times = 0L; try { FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); ff.start(); times = ff.getLengthInTime()/(1000*1000); ff.stop(); } catch (Exception e) { e.printStackTrace(); } return times; } }
这里需要注意一下,有的小伙伴可能将自己的开发工具设置为了自动导包,在导包的Frame这个可能会导入java.awt下的,这里你需要手动的改成org.bytedeco.javacv下的Frame。一般情况下如果导包出错的话,下面会出现报错现象。
三、创建测试类测试方法
1.测试获取视频截图
@Test public void testPic(){ File file=new File("D:\\testdemo\\testdemo.mp4"); try { VideoUtils.fetchPic(file,"D:\\testdemo\\ok.jpg"); } catch (Exception e) { e.printStackTrace(); } }
我自己拍了一个视频放到了D:\\testdemo下
视频
执行上述方法控制台打印如下则证明成功
控制台打印
这是生成的图片
以上就是截取视频某一帧的方法测试。
2.获取视频的时长
测试方法
public void testTime(){ File file=new File("D:\\testdemo\\testdemo.mp4"); Long videoTime = VideoUtils.getVideoTime(file); System.out.println(videoTime); }
控制台打印如下:
至此,简单方法已经完成。希望能够在以后的项目开发中对大家有所帮助,如果您有什么好的处理方式可以给我评论回复,大家可以一起讨论纯粹的技术。谢谢。