概述

最近在对之前写的一个 Spring Boot 的视频网站项目做功能完善,需要利用 FFmpeg 实现读取视频信息和自动截图的功能,查阅资料后发现网上这部分的内容非常少,于是就有了这篇文章。

视频网站项目地址 GitHub:GitHub - PuZhiweizuishuai/PornTube: A simple video website, use Spring Boot, Vue, vuetifyjs
码云: VideoWeb: 一个简单的视频网站,界面参考了Youtube,后端使用Spring Boot,前端Vue,vuetifyjs。支持自动生成封面图,发送弹幕等功能。

本文将介绍如何利用Javacv实现在视频网站中常见的读取视频信息和自动获取封面图的功能。

javacv 介绍

javacv可以帮助我们在java中很方便的使用 OpenCV 以及 FFmpeg 相关的功能接口
项目地址:GitHub - bytedeco/javacv: Java interface to OpenCV, FFmpeg, and more

引入 javacv

        <dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>${javacv.version}</version></dependency>

读取视频信息

创建 VideoInfo 类

package com.buguagaoshu.porntube.vo;import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;/*** @author Pu Zhiwei {@literal puzhiweipuzhiwei@foxmail.com}* create          2022-06-06 19:15*/
@Getter
@Setter
public class VideoInfo {/*** 总帧数**/private int lengthInFrames;/*** 帧率**/private double frameRate;/*** 时长**/private double duration;/*** 视频编码*/private String videoCode;/*** 音频编码*/private String audioCode;private int width;private int height;private int audioChannel;private String md5;/*** 音频采样率*/private Integer sampleRate;public String toJson() {try {ObjectMapper objectMapper = new ObjectMapper();return objectMapper.writeValueAsString(this);} catch (Exception e) {return "";}}
}

使用 FFmpegFrameGrabber 读取视频信息

 public static VideoInfo getVideoInfo(File file) {VideoInfo videoInfo = new VideoInfo();FFmpegFrameGrabber grabber = null;try {grabber = new FFmpegFrameGrabber(file);// 启动 FFmpeggrabber.start();// 读取视频帧数videoInfo.setLengthInFrames(grabber.getLengthInVideoFrames());// 读取视频帧率videoInfo.setFrameRate(grabber.getVideoFrameRate());// 读取视频秒数videoInfo.setDuration(grabber.getLengthInTime() / 1000000.00);// 读取视频宽度videoInfo.setWidth(grabber.getImageWidth());// 读取视频高度videoInfo.setHeight(grabber.getImageHeight());videoInfo.setAudioChannel(grabber.getAudioChannels());videoInfo.setVideoCode(grabber.getVideoCodecName());videoInfo.setAudioCode(grabber.getAudioCodecName());// String md5 = MD5Util.getMD5ByInputStream(new FileInputStream(file));videoInfo.setSampleRate(grabber.getSampleRate());return videoInfo;} catch (Exception e) {e.printStackTrace();return null;} finally {try {if (grabber != null) {// 此处代码非常重要,如果没有,可能造成 FFmpeg 无法关闭grabber.stop();grabber.release();}} catch (FFmpegFrameGrabber.Exception e) {log.error("getVideoInfo grabber.release failed 获取文件信息失败:{}", e.getMessage());}}}

截图

读取信息没有什么难度,但是在对视频截图的过程中,出现了一些问题,在我查找截图实现的代码时,大多数的代码都是这么写的

    /*** 获取视频缩略图* @param filePath:视频路径* @param mod:视频长度/mod获取第几帧* @throws Exception*/public static String randomGrabberFFmpegImage(String filePath, int mod) {String targetFilePath = "";try{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.parseInt(rotate)));}targetFilePath = getImagePath(filePath, i);doExecuteFrame(f, targetFilePath);break;}i++;}ff.stop();}catch (Exception e){log.error("获取视频缩略图异常:" + e.getMessage());}return targetFilePath;}

这样写本身没有什么问题,但是在获取需要截取帧数的部分,使用的是通过循环来一帧一帧的判断,这样在视频较短的时候没有什么问题,但是如果视频较长,就会出现严重的性能问题。

  while (i < ffLength) {f = ff.grabImage();if(i == index){......break;}i++;}

FFmpeg 的命令行参数有一个 -ss 的参数,使用 -ss 可以快速的帮助我们跳到视频的指定位置,完成操作,不用一帧一帧的判断。

所以现在的问题就是如何在 javacv 中实现 -ss 参数

我在 javacv 的 GitHub Issues 中发现了这个操作,即使用 setTimestamp() 方法,使用 setTimestamp() 方法可以使 FFmpeg 跳转到指定时间,完成截图,于是,最后的截图代码就变成了这样

  /*** 随机获取视频截图* @param videFile 视频文件* @param count 输出截图数量* @return 截图列表* */public static List<FileTableEntity> randomGrabberFFmpegImage(File videFile, int count, long userId) {FFmpegFrameGrabber grabber = null;String path = FileTypeEnum.filePath();try {List<FileTableEntity> images = new ArrayList<>(count);grabber = new FFmpegFrameGrabber(videFile);grabber.start();// 获取视频总帧数// int lengthInVideoFrames = grabber.getLengthInVideoFrames();// 获取视频时长, / 1000000 将单位转换为秒long delayedTime = grabber.getLengthInTime() / 1000000;Random random = new Random();for (int i = 0; i < count; i++) {// 跳转到响应时间grabber.setTimestamp((random.nextInt((int)delayedTime - 1) + 1) * 1000000L);Frame f = grabber.grabImage();Java2DFrameConverter converter = new Java2DFrameConverter();BufferedImage bi = converter.getBufferedImage(f);String imageName = FileTypeEnum.newFilename(SUFFIX);File out = Paths.get(path, imageName).toFile();ImageIO.write(bi, "jpg", out);FileTableEntity fileTable = FileUtils.createFileTableEntity(imageName, SUFFIX, path, f.image.length, "系统生成截图", userId, FileTypeEnum.VIDEO_PHOTO.getCode());images.add(fileTable);}return images;} catch (Exception e) {return null;} finally {try {if (grabber != null) {grabber.stop();grabber.release();}} catch (FFmpegFrameGrabber.Exception e) {log.error("getVideoInfo grabber.release failed 获取文件信息失败:{}", e.getMessage());}}}

这样我们就能快速的实现截图了。

使用JavaCV实现读取视频信息及自动截取封面图相关推荐

  1. h5页面保存img_如何设计H5编辑器中的模版库并实现自动生成封面图

    往期精选 H5编辑器的图片上传和图片库设计方案 如何实现H5编辑器的实时预览和真机扫码预览功能 在线IDE开发入门之从零实现一个在线代码编辑器 基于React+Koa实现一个h5页面可视化编辑器-Do ...

  2. 如何设计H5编辑器中的模版库并实现自动生成封面图

    往期精选 H5编辑器的图片上传和图片库设计方案 如何实现H5编辑器的实时预览和真机扫码预览功能 在线IDE开发入门之从零实现一个在线代码编辑器 基于React+Koa实现一个h5页面可视化编辑器-Do ...

  3. mp4视频获取时长、封面图、编码、转码(mpeg4转h264)工具类

    application.properties server.port=8908 file.uploadfolder=D:/school/ #分片文件临时目录 file.chunkfolder=D:/s ...

  4. .NET读取视频信息、视频截图

    在.NET中处理视频是一件痛苦的事情,.NET并没有提供视频处理的类.于是咱们只能找一些第三方的类库或者自己实现,在项目时间比较赶的情况下,自己实现是不可能的了,而且说不定会留下很多坑.所以一般情况下 ...

  5. 2023-02-21:请用go语言调用ffmpeg,解码mp4文件,输出视频信息和总帧数。

    2023-02-21:请用go语言调用ffmpeg,解码mp4文件,输出视频信息和总帧数. 答案2023-02-21: 使用 github.com/moonfdd/ffmpeg-go 库,这个库比go ...

  6. python ffmpeg 获取视频信息_ffmpeg获取视频信息

    php使用ffmpeg获取视频信息可以获取到视频的分辨率.文件大小.播放时长.编码格式.视频格式.音频编码.音频采样频率.等..... 废话不多说,直接上代码.../** * Name: ffmpeg ...

  7. 基于fastadmin框架,上传视频,自动截取视频封面图

    最近用fastadmin开发了一个项目,需要用到视频的封面图片,客户又不能一一提供视频对应的封面,为减少工作量,需要在后台上传视频后直接生成默认封面图片,也可以自动上传想要的封面图片: 利用fasta ...

  8. Android——Matirx 自动生成火焰图小工具

    最近在研究腾讯的Matirx框架,发现框架在抓取慢方法信息的时候会产出堆栈信息,如下格式: {"machine": "BEST","detail&qu ...

  9. 图片批量合成视频,并自动生成封面和配乐

    制作一个高质量的视频需要付出很多的时间和精力.而其中一个繁琐的过程就是将大量的图片合成为一个视频,并为其添加封面和配乐.但现在有一种神奇的工具可以让你摆脱这些繁琐的操作,轻松地将一个文件夹下的所有图片 ...

最新文章

  1. html数据分析表格api_Python数据分析基本库——Matplotlib(一)
  2. truncate与delete的区别
  3. JavaScript机器学习之KNN算法
  4. activity流程变量使用
  5. 罗马书1:18-32
  6. bigdecimal除法保留4位小数_小猿圈分享-MySQL保留几位小数的4种方法
  7. 总结2-深度学习网络搭建学习
  8. 预培训个人项目(地铁线路规划)
  9. html表单用户名,HTML表单
  10. 如何查看磁盘分区情况
  11. 基于python生成手写的笔记
  12. 子网掩码掩码计算器_Javascript加载掩码
  13. android 自定义Preference CheckBoxPreference ListPreference的用法
  14. 阿里云数据迁移工具解决方案:华为云迁移到阿里云
  15. 奖券数目 有些人很迷信数字,比如带“4”的数字,认为和“死”谐音,就觉得不吉利。 虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求。某抽奖活动的奖券号码是5位数(10000-99999),要求其
  16. linux命令报错,在Linux执行命令报错”Arg list too long”的原因分析 – 运维派
  17. 计算机微格教学教案设计表,微格教学教案设计表模板
  18. CSAPP--BombLab
  19. 【PF4J】PF4J入门指南
  20. 『互联网架构』软件架构-git服务搭建与使用(四)

热门文章

  1. Cisco WLC命令行配置service port
  2. 音视频技术开发周刊 | 291
  3. 没错是你想知道的——人工智能学习方向
  4. 观看宝剑嫂的公益视频后的一些感想整理下来
  5. M8W2 | 每周新产品体验
  6. 常用的客观效果指标和测试方法
  7. 股票自动委托下单html,股票怎么设置自动挂单?股票挂单的方式(2)
  8. 【转】十大ERP“丑闻” 你有多少不知道?
  9. C 语言陷阱和缺陷(一)
  10. 诺基亚7 android 9,诺基亚7 Plus喜迎Android 9更新:带来众多更新