java结合ffmpeg实现多个视频截图,按时长平均分割截取固定数量
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实现多个视频截图,按时长平均分割截取固定数量相关推荐
- java 视频截取图片 linux,在Windows和Linux下用JAVA调用FFMPEG 3.x进行视频截图的最新范例...
ffmpeg3.x版本,相对2.x版本,在接口上,作了较大的改动.原来的程序可能就不能正常编译.运行了.网上不少范例程序,所以也就不能用了.java 下面的例子,是本人在原ffmpeg2.X例子基础上 ...
- avi和音频合成 ffmpeg_使用Java和ffmpeg把音频和视频合成视频的操作方法
FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先进的音频/视频编解码库l ...
- 用Java和ffmpeg把音频和视频合成视频
借助第三方工具ffmpeg合成视频 需求:在小破站上下载了一些视频,但是放到电脑里面看,我擦,声音文件和视频文件是分开的. 正确安装ffmpeg并配置好环境变量. Java代码测试 转载指明源头 里面 ...
- java调用FFmpeg及mencoder转换视频为FLV并截图
Conver.java package com.ll19.flv;public class Conver {public void run() {try {// 转换并截图String filePat ...
- java调用ffmpeg,mencoder进行视频转换,读取时长等
2019独角兽企业重金招聘Python工程师标准>>> 以前做的一个基于ffmpeg的视频格式转换的程序,现在抽空整理一下,很多地方都是从别的大神那借鉴的,只是把自己的觉得有用的,对 ...
- Java使用ffmpeg合并多个视频文件、mp3文件
/*** 合并多个视频文件.mp3文件*/@Testpublic void mergeFile(){// 合并命令String commit = "$0 -f concat -safe 0 ...
- PHP获取视频截图及时长
//获得视频文件的缩略图 function getVideoCover($file,$time,$name) { if(empty($time))$time = '1';//默认截取第一秒第一帧 $s ...
- android视频剪辑处理第三方,Android 中通过 FFmpeg 命令对音视频编辑处理
以下文章来源于DevYk ,作者DevYK 音视频编辑器 前言 有时候我们想对音视频进行加工处理,比如视频编辑.添加字幕.裁剪等功能处理,虽然 Github 上开源了一些比较不错的项目,但是如果我们想 ...
- Android 中通过 FFmpeg 命令对音视频编辑处理(已开源)
视音频编辑器 前言 有时候我们想对音视频进行加工处理,比如视频编辑.添加字幕.裁剪等功能处理,虽然 Github 上开源了一些比较不错的项目,但是如果我们想在此项目上进行二次开发,比如我想拿到该项目的 ...
最新文章
- oracle SEQUENCE 创建, 修改,删除
- JAVA SE学习day_13 :Map 查找表
- struts2的配置
- nodeJs多线程 -- 学习记录
- mysql试题错误记录字段_MySQL这三道常见的面试题,你有被问过吗?
- codeforces1559 D2. Mocha and Diana (Hard Version)(并查集+启发式合并+随机化)
- python3列表生成式中的for循环与普通放在外面的for循环细微差异
- AndroidStudio_下载和安装---Android原生开发工作笔记67
- php在线编辑器_8款功能强大的Java编辑器,建议收藏!「渡一教育」
- java(6) ArrayList源码
- 拓端tecdat|Python在线零售数据关联规则挖掘Apriori算法数据可视化
- webpack和 php配合,javascript - webpack和laravel-elixir-webpack的正确配合方式?
- 计算机技术能力校本培训总结,教师现代教育技术校本培训总结(2篇)
- 外汇天眼:标普9月制造业PMI改善至51.8,综合PMI升至49.3
- 浏览器-错误 未能加载 PDF 文档
- VM+Lamp环境搭建
- java ews_Java---使用EWS读取exchange邮件
- 使用函数打印n*n的乘法口诀表
- Hadoop之金庸江湖人物关系网分析
- 去掉fgets拷贝的回车符
热门文章
- 【AutoSec汽车安全直播课】Bosch/ETAS专场:在AUTOSAR架构下如何应对车辆信息安全?
- 智能电表实现远程抄表,剔除人工抄表的弊端!
- java web毕业答辩ppt_javaweb在线考试系统毕业答辩.ppt
- prometheus安装
- springboot 打卡功能_SpringBoot 动态定时器的使用方法
- 【转】SPSS与EXCEL的比较
- maven 导入eclipse 出现错误 copy should be executed after packaging: see MDEP-187
- 潘仁美的原型是北宋一代开国名将
- 微信外卖小程序 怎么计算与客户的距离_外卖订单少收益低?开发一个小程序皆可以提解决...
- 2021年4月自考总结