1.需求背景:

相机上传的视频,没有上传封面,需要后台对云存储上的视频,添加封面后,保存封面和视频地址在数据库中。

2. JavaCV 简介

JavaCV是对各种常用计算机视觉库的封装后的一组jar包,其中封装了FFmpeg、OpenCV等计算机视觉编程人员常用库的接口,可以通过其中的Utility类方便的在包括Android在内的Java平台上调用这些接口。其中使用最多的应该就是FFmpeg了。

最开始Javacv是googlecode下面的一个项目,后来迁移到了github,因此JavaCV相关的包名也由com.googlecode.javacv改为org.bytedeco.javacv。项目地址:https://github.com/bytedeco/javacv

3. JavaCV 基本使用指南

从github项目中下载打包好的jar包,其中javacpp.jar 和 javacv.jar是必须的两个包,然后需要什么功能就添加额外的包。例如我需要用到ffmpeg进行视频录制,则需要添加ffmpeg.jar和ffmpeg-android-arm.jar(打包的arm平台so库)。这里很方便的地方是,so库文件都放在了jar文件里面,在集成的时候很简洁明了。

4.javacv的使用

1.4.x、1.3.x版本的精简jar:

  <!--javacv 截取视频封面包--><dependency><groupId>org.bytedeco</groupId><artifactId>javacv</artifactId><version>1.4.3</version><exclusions><exclusion><groupId>org.bytedeco.javacpp-presets</groupId><artifactId>*</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.bytedeco.javacpp-presets</groupId><artifactId>opencv</artifactId><version>3.4.2-1.4.2</version></dependency><dependency><groupId>org.bytedeco.javacpp-presets</groupId><artifactId>opencv</artifactId><version>3.4.2-1.4.2</version><classifier>windows-x86_64</classifier>
<!--            <classifier>linux-x86_64</classifier>--></dependency><!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/ffmpeg --><dependency><groupId>org.bytedeco.javacpp-presets</groupId><artifactId>ffmpeg</artifactId><version>4.0.1-1.4.2</version></dependency><dependency><groupId>org.bytedeco.javacpp-presets</groupId><artifactId>ffmpeg</artifactId><version>4.0.1-1.4.2</version><classifier>windows-x86_64</classifier>
<!--            <classifier>linux-x86_64</classifier>--></dependency><!---->

1.5.x版本后的精简包:

        <!--javacv 截取视频封面包--><dependency><groupId>org.bytedeco</groupId><artifactId>javacv</artifactId><version>1.5.7</version><exclusions><exclusion><groupId>org.bytedeco</groupId><artifactId>*</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>ffmpeg</artifactId><version>5.0-1.5.7</version></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>ffmpeg</artifactId><version>5.0-1.5.7</version>
<!--            <classifier>windows-x86_64</classifier>--><classifier>linux-x86_64</classifier></dependency><!---->

2.实现:

package com.camojojo.device.common.utils;import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import com.camojojo.common.core.utils.AwsFileUtil;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;/*** @author:yuchen* @createTime:2022/7/11 16:07*/@Slf4j
public class VideoUtil {private static final String PATH="/ossRoot/";public static void main(String[] args) {getVideoPic();}public static String getVideoPic() {String url = "https://xxx/xxxx.mp4";String value = "1111123";String dir = value +"/";String fileName = FileUtil.getName(url);// 100.mp4String targetFileName = "thumb_"+fileName.substring(0, fileName.lastIndexOf("."))+".jpg";File filePath = new File(PATH+dir);if (!filePath.exists()) {boolean mkdirs = filePath.mkdirs();if(mkdirs){log.info("文件夹创建成功:{}",filePath.getAbsolutePath());}}String outPath = PATH+dir+targetFileName;File outFile = getScreenshot(url, outPath);if(outFile != null){String fileName1 = AwsFileUtil.uploadS3Us(outFile, imei, targetFileName);System.out.println(fileName1);boolean delete = outFile.delete();if(delete){log.info("删除本地临时文件成功");}return fileName1;}return "";}/*** 获取视频封面图* @param filePath 视频地址* @return map*/private static File getScreenshot(String filePath, String imagePath) {log.info("截取视频截图开始:Video={}",filePath);filePath = filePath.replaceAll("\\\\","/");File output = null;FFmpegFrameGrabber grabber = null;try{grabber  = FFmpegFrameGrabber.createDefault(filePath);grabber.start();//设置视频截取帧(建议从5帧开始,防止全是黑屏)Frame frame = null;for (int j = 0; j < 5; j++) {frame =  grabber.grabImage();}//视频旋转度String rotate = grabber.getVideoMetadata("rotate");Java2DFrameConverter converter = new Java2DFrameConverter();//绘制图片BufferedImage bi = converter.getBufferedImage(frame);if (rotate != null) {// 旋转图片bi = rotate(bi, Integer.parseInt(rotate));}//创建文件output = new File(imagePath);ImgUtil.write(bi, output);log.info("截取视频截图成功");}catch (Exception e){log.error("获取视频封面图,Error:",e);}finally {if(grabber!=null){try { grabber.stop(); } catch (Exception ignored) { }}}return output;}/*** @Description  根据视频旋转度来调整图片* @param src ""* @param angel 视频旋转度* @return  BufferedImage*/private static BufferedImage rotate(BufferedImage src, int angel) {int src_width = src.getWidth(null);int src_height = src.getHeight(null);int type = src.getColorModel().getTransparency();Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);BufferedImage bi = new BufferedImage(rect_des.width, rect_des.height, type);Graphics2D g2 = bi.createGraphics();g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);g2.drawImage(src, 0, 0, null);g2.dispose();return bi;}/*** @Description: 计算图片旋转大小* @param src ""* @param angel ""* @return  Rectangle*/private static Rectangle calcRotatedSize(Rectangle src, int angel) {if (angel >= 90) {if (angel / 90 % 2 == 1) {int temp = src.height;src.height = src.width;src.width = temp;}angel = angel % 90;}double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;double angel_dalta_width = Math.atan((double) src.height / src.width);double angel_dalta_height = Math.atan((double) src.width / src.height);int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));int des_width = src.width + len_dalta_width * 2;int des_height = src.height + len_dalta_height * 2;return new java.awt.Rectangle(new Dimension(des_width, des_height));}}

5.使用Docker部署后,截屏异常

在另一个Docker部署的服务中使用该方法,发现一调用,服务就挂。

最后发现原因是由于那个Docker容器使用的是阉割版的JDK镜像:openjdk:8-jre-alpine ,虽然该镜像能使打包的体积更小,但是容易出现此类的问题,需要换成更完整的JDK镜像。

后面换成: openjdk:8-jre ,就没问题了。

javacv版本1.4.x ,会出现物理内存溢出溢出,网上说是旧版本源码bug,升级到1.5.x版本就修复了,今天升级了,运行一段时间再看。

特此记录。

javacv截取视频截图-1.5.7版本精简包相关推荐

  1. 基于javacv的视频截图、转码、提取音频

    目录 目标 全量依赖 最小依赖 截图配置类 转码配置类 提取音频配置类 源视频处理结果类 核心类 怎么使用 目标 将所有格式的视频转码为H5能播放的mp4格式,也可以截取任意一帧图片 全量依赖 < ...

  2. javacv音视频截图,音频抽取汇总

    概述: java 使用 javacv 视频截帧, 跳到指定帧截图, 从视频中抽取音频, 音频分割为多段 1 依赖: <dependency><groupId>org.byted ...

  3. java截取视频片段_使用javacv 截取视频指定帧节

    个人博客 地址:https://www.wenhaofan.com/article/20190407105818 引入依赖 org.bytedeco javacv 1.4.3 org.bytedeco ...

  4. 利用 javacv 截取视频帧制作封面及获取视频播放时长

    一.Maven依赖 <dependency><groupId>org.bytedeco</groupId><artifactId>javacv</ ...

  5. 视频截图方法 javacv

    第一步 导入依赖 <dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platf ...

  6. php ffmpeg截图,php ffmpeg截取视频第一帧保存为图片的方法

    php ffmpeg截取视频第一帧保存为图片的方法 $xiangmupath = $this->getxiangmupath(); $filename = 'chengshi'; $cmd = ...

  7. java如何截取视频文件_Java获取视频时长及截取帧截图详解

    前言 只是最近碰到有这方面的项目需求,所以简单 Mark 下本文.下面的示例是参考过他人分享的文章,之后本人再自行实践.调整和测试过的,希望对有这方面需求的人有所帮助. 示例 添加依赖 org.byt ...

  8. java使用ffmpeg截取视频某个时间点的截图

    1.软件安装 mac brew install ffmpeg 安装后路径:"/usr/local/Cellar/ffmpeg/4.0.1/bin ffmpeg –version 查看版本 l ...

  9. php截取视频第一帧为图片,把视频变成一帧一帧的图片(ae怎么把视频变成单帧) 视频截图视频画面每帧图片截取...

    AE怎么把视频变成单帧?这是小编今天要与大家讨论及解决的一个问题.在视频后期处理中,有时为实现某个场景效果,需要把视频中的某帧变成静态帧图片:或者需要视频截图视频画面每帧图片截取出来,把视频变成一帧一 ...

  10. java结合ffmpeg实现多个视频截图,按时长平均分割截取固定数量

    java结合ffmpeg实现多个视频截图,按时长平均分割截取固定数量 本工具简单介绍 使用方式 效果展示 工具源码 本工具简单介绍 先强调下,本工具可以直接上手使用. 本来ffmpeg就可以支持很多功 ...

最新文章

  1. Java 中文转拼音
  2. ORACLE纯SQL实现多行合并一行
  3. CSDN Github Markdown编辑常用功能符号补充
  4. hdu 2059(dp)
  5. JQ获取CKeditor的值
  6. AliOS Things网络适配框架 - SAL
  7. gms签名不一致_第三方稳定不掉ios软件企业签名怎么买
  8. Vmware虚拟机不能使用键盘的解决方法
  9. 距离一个优秀程序员,你还差多少?
  10. (16)机器学习_ROC曲线绘制
  11. linux环境安装ffmepg,Linux centOS下安装FFmpeg
  12. 2019eclipse 中文汉化包 安装教程
  13. [AngularJS面面观] 15. 依赖注入 --- 初识注入器(Injector)
  14. python获取股票分时数据_AkShare-股票数据-分时数据
  15. 这些免费、可商用的图片素材网站,绝对不能错过
  16. aspose合并单元格
  17. nintendo掌机
  18. 山东省非计算机专业,山东省高校非计算机专业教学考试(选择、判断含答案)2...
  19. vue 使用swper组件
  20. 毕业设计之基于Qt数字音频处理软件设计

热门文章

  1. 思科cisco模拟器路由器的基础配置
  2. Cherno OpenGL 教程
  3. ManualResetEvent类的用法
  4. 【软考网络工程师】华为路由器交换机配置
  5. SWF转GIF完美解决方案
  6. 清除Conficker蠕虫病毒详细步骤
  7. alexa/alexa-avs-sample-app Windows 安装教程
  8. mysql管理员_mysql怎么获得管理员权限??麻烦告诉我
  9. MSG数据(EUMETSAT)和GOES数据(NOAA)下载
  10. Clip_by_norm 函数理解