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

  • 本工具简单介绍
  • 使用方式
  • 效果展示
  • 工具源码
本工具简单介绍
  • 先强调下,本工具可以直接上手使用

  • 本来ffmpeg就可以支持很多功能,比如视频截图,比如可以执行每隔多少秒截取一帧图片,但是本人没找到按时长平均分割截取固定数量的图片的功能,而且一次只能截取一个视频,不能截取指定的整个目录的所有视频,不够自动化,所以就有了这个工具。

  • 而本工具可以根据视频的长度来平均截取固定数量的图片,支持传递“源视频文件目录路径”、“输出目录路径”、“共截取图片个数”、“分割方式”等参数,后面有详细说明

  • 声明一下,本工具目前只在windows下可用,需要用在其他平台的童鞋可以自行改造。

使用方式
  • 首先需要先安装jdk1.8或以上版本,以及ffmpeg这个玩意,不会安装的自行百度哈,官网地址如下:

    http://www.ffmpeg.org/download.html.

  • 要使用本工具,安装好后需要添加环境变量 FFMPEG_HOME,就是ffmpeg的bin目录的绝对路径,目录带不带\都可以,并重启电脑(不重启电脑需要带一个“ffmpeg.exe所在目录”的参数)。

  • 将本文最后的源码保存为Vedios2Images.java文件,然后在cmd命令中执行以下命令,将其编译成Vedios2Images.class

javac -encoding UTF-8 Vedios2Images.java
  • 然后就可以使用Vedios2Images.class对多个视频进行截图了

  • 命令参数含义


命令格式 java VedioToImages [源视频文件路径] [目标目录路径] [截取图片个数] [ffmpeg.exe所在目录] [是否分目录存放截图]以下参数中,参数1和参数2是必填参数。参数1:源视频文件目录路径,此目录带不带\都可以,须填绝对路径。必传参数。参数2:输出目录路径,此目录带不带\都可以,须填绝对路径。必传参数。参数3:共截取图片个数。 可不传,不传默认为6。参数4:ffmpeg.exe所在目录。可不传,不填自动从环境变量 FFMPEG_HOME 获取。注意:刚配置不重启电脑时java中获取不到,所以不想重启可暂时传入,此目录带不带\都可以,须填绝对路径。若不想重启又不想传此参数,可以将其安装(重命名后解压)到D:\tools_install\ffmpeg\bin 目录下(ffmpeg.exe在这个目录就行)。参数5:表示是否将每个视频的截图分割为目录,不填不分割。值为s则将每个视频切分到以视频名命
名的目录中,否则直接放在输出目录中。始终为最后一个参数。如 :java Vedios2Images D:\tmp\test D:\jietu 20 D:\tools_install\ffmpeg\bin s表示将D:\tmp\test目录下的所有视频截图,输出到D:\jietu目录下,每个视频的输出个数为20个,D:\tools_install\ffmpeg\bin 显式的指定了ffmpeg.exe所在目录,最后的s代表将每个视频的多个截图存放在以视频名命名的目录中。下面的命令也是正确的:java Vedios2Images D:\tmp\test D:\jietujava Vedios2Images D:\tmp\test D:\jietu  10java Vedios2Images D:\tmp\test D:\jietu sjava Vedios2Images D:\tmp\test D:\jietu  10 s
效果展示
  • 命令指定out为输出目录,source为源目录

  • source中有两个视频

  • 截图前out目录为空(不为空也可以)

  • 在Vedios2Images.class所在目录下打开cmd窗口,并输入示例命令:

    java Vedios2Images D:\tmp\test\source D:\tmp\test\out 15 s
    

  • 执行完成
  • out目录中已有截图,且按目录分割

  • 视频01
  • 视频02
  • 清空out目录,执行下面的不带 s 参数的命令
java Vedios2Images D:\tmp\test\source D:\tmp\test\out 15

  • 执行完毕后
  • 截图不按目录分割
工具源码

时间仓促,代码可能有比较多不足的地方,望见谅!

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class Vedios2Images {public static void main(String[] args) throws Exception {//去前后空格并校验参数个数不能小于2trimAndCheckArgs(args);File[] vedios = new File(args[0]).listFiles();//目录中不能有其他文件for(File vedio : vedios){if(vedio.isDirectory() || Objects.equals(vedio.getName(), "Vedios2Images.class")){continue;}String vedioPath = vedio.getAbsolutePath();String outPath;if(isSplit(args)){outPath = getOutSplitToDirPath(args, vedio.getName());}else{outPath = getOutPath(args, vedio.getName());}int imgCount = getImgCount(args);String ffmpegPath = getFfmpegPath(args);singleVedioToImages(vedioPath, outPath, imgCount, ffmpegPath);}System.out.println("执行完毕!!!");}private static boolean isSplit(String[] args) {//大于两个参数,且最后一个参数值为s说明为分目录截图return args.length > 2 && Objects.equals("s", args[args.length - 1]);}private static void trimAndCheckArgs(String [] args) {if(args.length < 2){throw new RuntimeException("至少需要传入两个参数:源视频目录 和 截图输出目录");}for (int i = 0; i < args.length; i++){args[i] = args[i].trim();}}private static String getOutPath(String[] args, String vedioName){String outPath = "D:\\jietu\\img_%d.jpg";if(args.length > 1){if(!args[1].endsWith("\\")){args[1] += "\\";}String vedioNameIgnoreSufix = vedioName.substring(0, vedioName.lastIndexOf("."));outPath = args[1] + vedioNameIgnoreSufix + "_%d.jpg";}return outPath;}/*** 获取视频截图路径,每个视频截图放在以各自文件名命名的目录* @param args args* @param vedioName vedioName* @return 截图路径*/private static String getOutSplitToDirPath(String[] args, String vedioName){String outPath = "D:\\jietu\\img_%d.jpg";if(args.length > 1){if(!args[1].endsWith("\\")){args[1] += "\\";}String vedioNameIgnoreSufix = vedioName.substring(0, vedioName.lastIndexOf("."));String destDir = args[1] + vedioNameIgnoreSufix + "\\";if(!new File(args[1]).exists()){throw new RuntimeException("目录 " + args[1] + "不存在");}new File(destDir).mkdir();outPath = destDir + vedioNameIgnoreSufix + "_%d.jpg";}return outPath;}private static int getImgCount(String[] args){//默认截取6张int imgCount = 6;if(args.length > 2 && isInteger(args[2])){imgCount = Integer.parseInt(args[2]);}return imgCount;}private static String getFfmpegPath(String[] args){String ffmpegHome = System.getenv("FFMPEG_HOME");if(ffmpegHome == null){if(args.length == 3 && !isInteger(args[2])){pathAdapter(args,2);ffmpegHome = args[2];}else if(args.length > 3){pathAdapter(args,3);ffmpegHome = args[3];}else{ffmpegHome = "D:\\tools_install\\ffmpeg\\bin\\";}}//FFMPEG_HOMEreturn ffmpegHome + "ffmpeg";}public static boolean isInteger(String str) {Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");return pattern.matcher(str).matches();}private static void singleVedioToImages(String vedioPath, String outPath,int imgCount, String ffmpegPath) throws Exception {List<String> commands = new ArrayList<>();//ffmpeg -i 001.mp4 -vf fps=0.1 -q:v 2 -f image2 D:\jietu\test-%d.jpgcommands.add(ffmpegPath);commands.add("-i");commands.add(vedioPath);Long vedioTime = getVedioTime(commands);commands.add("-vf");double fpsParam = 1.0 / ((double) vedioTime / imgCount);commands.add("fps=" + fpsParam);commands.add("-q:v");commands.add("2");commands.add("-f");commands.add("image2");commands.add(outPath);ProcessBuilder builder = new ProcessBuilder();builder.command(commands);Process process = builder.start();
//        process.waitFor();//从输入流中读取视频信息BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
//        StringBuilder stringBuilder = new StringBuilder();String line;while ((line = br.readLine()) != null) {
//            stringBuilder.append(line);System.out.println(line);}br.close();System.out.println("视频 " + vedioPath + " 截图完毕");}private static void pathAdapter(String[] args, int index){if(!args[index].endsWith("\\")){args[index] += "\\";}}/*** 获取视频总时间*/private static Long getVedioTime(List<String> commands/*, String vedioPath, String ffmpegPath*/) throws Exception{/*List<String> commands = new ArrayList<>();commands.add(ffmpegPath);commands.add("-i");commands.add(vedioPath);*/ProcessBuilder builder = new ProcessBuilder();builder.command(commands);Process p = builder.start();//从输入流中读取视频信息BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));StringBuilder stringBuilder = new StringBuilder();String line = "";while ((line = br.readLine()) != null) {stringBuilder.append(line);}br.close();//从视频信息中解析时长String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";Pattern pattern = Pattern.compile(regexDuration);Matcher m = pattern.matcher(stringBuilder.toString());if (m.find()) {Long time = getTimelen(m.group(1));
//            System.out.println("视频时长:" + time + "s , 开始时间:" + m.group(2) + ", 比特率:" + m.group(3) + "kb/s");return time;}return null;}private static Long getTimelen(String timelen) {Long min = 0L;String strs[] = timelen.split(":");if (strs[0].compareTo("0") > 0) {// 秒min += Long.parseLong(strs[0]) * 60 * 60;}if (strs[1].compareTo("0") > 0) {min += Long.parseLong(strs[1]) * 60;}if (strs[2].compareTo("0") > 0) {min += Math.round(Double.parseDouble(strs[2]));}return min;}}

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

  1. java 视频截取图片 linux,在Windows和Linux下用JAVA调用FFMPEG 3.x进行视频截图的最新范例...

    ffmpeg3.x版本,相对2.x版本,在接口上,作了较大的改动.原来的程序可能就不能正常编译.运行了.网上不少范例程序,所以也就不能用了.java 下面的例子,是本人在原ffmpeg2.X例子基础上 ...

  2. avi和音频合成 ffmpeg_使用Java和ffmpeg把音频和视频合成视频的操作方法

    FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先进的音频/视频编解码库l ...

  3. 用Java和ffmpeg把音频和视频合成视频

    借助第三方工具ffmpeg合成视频 需求:在小破站上下载了一些视频,但是放到电脑里面看,我擦,声音文件和视频文件是分开的. 正确安装ffmpeg并配置好环境变量. Java代码测试 转载指明源头 里面 ...

  4. java调用FFmpeg及mencoder转换视频为FLV并截图

    Conver.java package com.ll19.flv;public class Conver {public void run() {try {// 转换并截图String filePat ...

  5. java调用ffmpeg,mencoder进行视频转换,读取时长等

    2019独角兽企业重金招聘Python工程师标准>>> 以前做的一个基于ffmpeg的视频格式转换的程序,现在抽空整理一下,很多地方都是从别的大神那借鉴的,只是把自己的觉得有用的,对 ...

  6. Java使用ffmpeg合并多个视频文件、mp3文件

    /*** 合并多个视频文件.mp3文件*/@Testpublic void mergeFile(){// 合并命令String commit = "$0 -f concat -safe 0 ...

  7. PHP获取视频截图及时长

    //获得视频文件的缩略图 function getVideoCover($file,$time,$name) { if(empty($time))$time = '1';//默认截取第一秒第一帧 $s ...

  8. android视频剪辑处理第三方,Android 中通过 FFmpeg 命令对音视频编辑处理

    以下文章来源于DevYk ,作者DevYK 音视频编辑器 前言 有时候我们想对音视频进行加工处理,比如视频编辑.添加字幕.裁剪等功能处理,虽然 Github 上开源了一些比较不错的项目,但是如果我们想 ...

  9. Android 中通过 FFmpeg 命令对音视频编辑处理(已开源)

    视音频编辑器 前言 有时候我们想对音视频进行加工处理,比如视频编辑.添加字幕.裁剪等功能处理,虽然 Github 上开源了一些比较不错的项目,但是如果我们想在此项目上进行二次开发,比如我想拿到该项目的 ...

最新文章

  1. oracle SEQUENCE 创建, 修改,删除
  2. JAVA SE学习day_13 :Map 查找表
  3. struts2的配置
  4. nodeJs多线程 -- 学习记录
  5. mysql试题错误记录字段_MySQL这三道常见的面试题,你有被问过吗?
  6. codeforces1559 D2. Mocha and Diana (Hard Version)(并查集+启发式合并+随机化)
  7. python3列表生成式中的for循环与普通放在外面的for循环细微差异
  8. AndroidStudio_下载和安装---Android原生开发工作笔记67
  9. php在线编辑器_8款功能强大的Java编辑器,建议收藏!「渡一教育」
  10. java(6) ArrayList源码
  11. 拓端tecdat|Python在线零售数据关联规则挖掘Apriori算法数据可视化
  12. webpack和 php配合,javascript - webpack和laravel-elixir-webpack的正确配合方式?
  13. 计算机技术能力校本培训总结,教师现代教育技术校本培训总结(2篇)
  14. 外汇天眼:标普9月制造业PMI改善至51.8,综合PMI升至49.3
  15. 浏览器-错误 未能加载 PDF 文档
  16. VM+Lamp环境搭建
  17. java ews_Java---使用EWS读取exchange邮件
  18. 使用函数打印n*n的乘法口诀表
  19. Hadoop之金庸江湖人物关系网分析
  20. 去掉fgets拷贝的回车符

热门文章

  1. 【AutoSec汽车安全直播课】Bosch/ETAS专场:在AUTOSAR架构下如何应对车辆信息安全?
  2. 智能电表实现远程抄表,剔除人工抄表的弊端!
  3. java web毕业答辩ppt_javaweb在线考试系统毕业答辩.ppt
  4. prometheus安装
  5. springboot 打卡功能_SpringBoot 动态定时器的使用方法
  6. 【转】SPSS与EXCEL的比较
  7. maven 导入eclipse 出现错误 copy should be executed after packaging: see MDEP-187
  8. 潘仁美的原型是北宋一代开国名将
  9. 微信外卖小程序 怎么计算与客户的距离_外卖订单少收益低?开发一个小程序皆可以提解决...
  10. 2021年4月自考总结