使用的是ffmepg,需要先下载,然后解压到指定文件夹,
其中的变量ffmpegPath指定的是ffmepg解压后的exe路径

这里看到processVideoFormat()方法中,推荐一律使用MgrPrintStream的方式进行使用而不是用doWaitFor,
如果用doWaitFor方法,可能会导致程序执行完了,线程还没有执行完,转码失败
工具类ConverVideoUtils

值得一提的是:ffmpeg默认就会转成h264,
如果有出现视频看不了但是有声音,可以尝试转码

package com.haoyu.framework.modules.file.utils;import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;/*** 视频转码工具类** @author jwc*/
@Component
public class ConverVideoUtils {protected final Logger logger = LoggerFactory.getLogger(this.getClass());/*** 转换视频格式** @param sourceVideoPath 视频地址* @return*/public String beginConver(String sourceVideoPath) {//转码格式String targetExtension = ".mp4";//是否删除原文件Boolean isDeleteResult = false;File fi = new File(sourceVideoPath);String fileName = fi.getName();//文件名不带扩展名String fileRealName = fileName.substring(0, fileName.lastIndexOf("."));logger.info("接收到文件(" + sourceVideoPath + ")需要转换");if (!checkfile(sourceVideoPath)) {logger.error(sourceVideoPath + "文件不存在" + " ");return "";}long beginTime = System.currentTimeMillis();logger.info("开始转文件(" + sourceVideoPath + ")");String path = process(fileRealName, sourceVideoPath, targetExtension, isDeleteResult);if (StrUtil.isNotEmpty(path)) {logger.info("转换成功");long endTime = System.currentTimeMillis();long timeCha = (endTime - beginTime);String totalTime = sumTime(timeCha);logger.info("转换视频格式共用了:" + totalTime + " ");if (isDeleteResult) {deleteFile(sourceVideoPath);}return path;} else {return "";}}/*** 实际转换视频格式的方法** @param fileRealName    文件名不带扩展名* @param sourceVideoPath 原文件地址* @param targetExtension 目标视频扩展名* @param isDeleteResult  转换完成后是否删除源文件* @return*/private String process(String fileRealName, String sourceVideoPath, String targetExtension, boolean isDeleteResult) {int type = checkContentType(sourceVideoPath);String path = "";if (type == 0) {//如果type为0用ffmpeg直接转换path = processVideoFormat(sourceVideoPath, fileRealName, targetExtension, isDeleteResult);}return path;}/*** 检查文件类型** @param sourceVideoPath 原文件地址* @return*/private int checkContentType(String sourceVideoPath) {String type = sourceVideoPath.substring(sourceVideoPath.lastIndexOf(".") + 1).toLowerCase();// ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)if (type.equals("avi")) {return 0;} else if (type.equals("mpg")) {return 0;} else if (type.equals("wmv")) {return 0;} else if (type.equals("3gp")) {return 0;} else if (type.equals("mov")) {return 0;} else if (type.equals("mp4")) {return 0;} else if (type.equals("asf")) {return 0;} else if (type.equals("asx")) {return 0;} else if (type.equals("flv")) {return 0;}// 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),// 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.else if (type.equals("wmv9")) {return 1;} else if (type.equals("rm")) {return 1;} else if (type.equals("rmvb")) {return 1;}return 9;}/*** 检查文件是否存在** @param path 文件地址* @return*/private boolean checkfile(String path) {File file = new File(path);if (!file.isFile()) {return false;} else {return true;}}/*** 转换为指定格式* ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)** @param oldFilePath     源文件地址* @param fileRealName    文件名不带扩展名* @param targetExtension 目标格式扩展名 .xxx* @return*/private String processVideoFormat(String oldFilePath, String fileRealName, String targetExtension, Boolean isDeleteResult) {/*** ffmpeg.exe的地址*/
//      String ffmpegPath = "D:\\ffmpeg\\bin\\ffmpeg.exe";String ffmpegPath = "E:\\ffmpeg-20171225-be2da4c-win64-static\\bin\\ffmpeg.exe";/*** 转码后的存放视频地址 mp4格式*/
//      String targetFolder = "C:\\Users\\Administrator\\Desktop\\test\\";String targetFolder = "E:\\testzhuanma\\";if (!checkfile(oldFilePath)) {logger.error(oldFilePath + "文件不存在");return "";}List<String> commend = new ArrayList<>();commend.add(ffmpegPath);commend.add("-i");commend.add(oldFilePath);commend.add("-threads");commend.add("5");commend.add("-preset");commend.add("-ultrafast");commend.add("-vcodec");commend.add("copy");commend.add(targetFolder + fileRealName + targetExtension);try {//          ProcessBuilder builder = new ProcessBuilder(commend);
//          builder.command(commend);
//          builder.redirectErrorStream(true);
//          Process p = builder.start();
//          doWaitFor(p);
//          p.destroy();Process videoProcess = new ProcessBuilder(commend).redirectErrorStream(true).start();new MgrPrintStream(videoProcess.getErrorStream()).start();new MgrPrintStream(videoProcess.getInputStream()).start();videoProcess.waitFor();String videoPath = targetFolder + fileRealName + targetExtension;
//          String path = this.processVideoFormatH264(videoPath, ffmpegPath, targetFolder, targetExtension, isDeleteResult);return videoPath;} catch (Exception e) {e.printStackTrace();return "";}}/*** 将mpeg4转为h264编码 为了支持播放器** @param path* @param ffmpegPath* @return*/private String processVideoFormatH264(String path, String ffmpegPath, String targetFolder, String targetExtension, Boolean isDeleteResult) {if (!checkfile(path)) {logger.error(path + "文件不存在");return "";}String newFilePath = targetFolder + UUID.randomUUID().toString() + targetExtension;List<String> commend = new ArrayList<>();commend.add(ffmpegPath);commend.add("-i");commend.add(path);commend.add("-threads");commend.add("5");commend.add("-preset");commend.add("-ultrafast");commend.add("-vcodec");commend.add("h264");commend.add("-q");commend.add("0");commend.add("-y");commend.add(newFilePath);try {ProcessBuilder builder = new ProcessBuilder();builder.command(commend);Process p = builder.start();doWaitFor(p);p.destroy();if (isDeleteResult) {deleteFile(path);}return newFilePath;} catch (Exception e) {e.printStackTrace();return "";}}public int doWaitFor(Process p) {InputStream in = null;InputStream err = null;int exitValue = -1;try {in = p.getInputStream();err = p.getErrorStream();boolean finished = false;while (!finished) {try {while (in.available() > 0) {in.read();}while (err.available() > 0) {err.read();}//                    exitValue = p.exitValue();finished = true;} catch (IllegalThreadStateException e) {Thread.sleep(500);}}} catch (Exception e) {logger.error("doWaitFor();: unexpected exception - " + e.getMessage());} finally {try {if (in != null) {in.close();}} catch (IOException e) {logger.info(e.getMessage());}if (err != null) {try {err.close();} catch (IOException e) {logger.info(e.getMessage());}}}return exitValue;}/*** 保存视频缩略图* @throws IOException*/public static void saveVideoThumbnail(String ffmpegPath,String videoPath, String imagePath) {try{//ffmpeg -i xxx.mp4 -y -f image2 -t 0.001 -s 125x125 xxx.jpgList<String> cmd = new java.util.ArrayList<String>();
//            cmd.add("ffmpeg");// 视频提取工具的位置cmd.add(ffmpegPath + "ffmpeg");// 视频提取工具的位置cmd.add("-i");cmd.add(videoPath);cmd.add("-y");cmd.add("-f");cmd.add("image2");cmd.add("-t");cmd.add("0.001");cmd.add("-s");cmd.add("125x125");cmd.add(imagePath);
//            ProcessBuilder builder = new ProcessBuilder();
//            builder.command(cmd);
//            builder.start();// 方案2Process videoProcess = new ProcessBuilder(cmd).redirectErrorStream(true).start();new MgrPrintStream(videoProcess.getErrorStream()).start();new MgrPrintStream(videoProcess.getInputStream()).start();videoProcess.waitFor();}catch (Exception e){System.out.println("图片转换失败");}}/*** 删除文件方法** @param filepath*/public void deleteFile(String filepath) {File file = new File(filepath);if (file.delete()) {logger.info("文件" + filepath + "已删除");}}/*** 计算转码时间** @param ms* @return*/public String sumTime(long ms) {int ss = 1000;long mi = ss * 60;long hh = mi * 60;long dd = hh * 24;long day = ms / dd;long hour = (ms - day * dd) / hh;long minute = (ms - day * dd - hour * hh) / mi;long second = (ms - day * dd - hour * hh - minute * mi) / ss;long milliSecond = ms - day * dd - hour * hh - minute * mi - second* ss;String strDay = day < 10 ? "0" + day + "天" : "" + day + "天";String strHour = hour < 10 ? "0" + hour + "小时" : "" + hour + "小时";String strMinute = minute < 10 ? "0" + minute + "分" : "" + minute + "分";String strSecond = second < 10 ? "0" + second + "秒" : "" + second + "秒";String strMilliSecond = milliSecond < 10 ? "0" + milliSecond : ""+ milliSecond;strMilliSecond = milliSecond < 100 ? "0" + strMilliSecond + "毫秒" : ""+ strMilliSecond + " 毫秒";return strDay + " " + strHour + ":" + strMinute + ":" + strSecond + " "+ strMilliSecond;}
}

MgrPrintStream

package com.haoyu.framework.modules.file.utils;public class MgrPrintStream extends Thread
{java.io.InputStream __is = null;public MgrPrintStream(java.io.InputStream is){__is = is;}public void run(){try{while(this != null){int _ch = __is.read();if(_ch != -1)System.out.print((char)_ch);else break;}}catch (Exception e){e.printStackTrace();}}
}

MgrPrintStream 的使用参考的是

https://blog.csdn.net/qq_32230309/article/details/78875607

中的PrintStream,改了个名字改成MgrPrintStream(因为spring里已经有PrintStream了)

测试类

@Slf4j
public class myTest {@Testpublic void test4(){ConverVideoUtils converVideoUtils = new ConverVideoUtils();// 转视频converVideoUtils.beginConver("E:\\testfile\\test_vedio.mp4");
//       获取视频的第一张缩略图converVideoUtils.saveVideoThumbnail("E:\\ffmpeg-20171225-be2da4c-win64-static\\bin\\","E:\\testfile\\test_vedio.mp4","E:\\testzhuanma\\cc.jpeg");}
}

Spring视频转码工具类ffmpeg相关推荐

  1. java 视频转码工具类_JavaCV入门指南:FrameConverter转换工具类及CanvasFrame图像预览工具类(javaCV教程完结篇)...

    JavaCV入门指南:FrameConverter转换工具类及CanvasFrame图像预览工具类(javaCV教程完结篇) 前言 再此章之前,我们已经详细介绍和剖析了javacv的结构和ffmpeg ...

  2. Spring源码工具类ClassUtils之isAssignable

    Spring源码工具类ClassUtils之isAssignable 文章目录 Spring源码工具类ClassUtils之isAssignable 一.isAssignable 二.代码示例 一.i ...

  3. android 转码工具下载,m3u8视频转码工具

    m3u8视频转码工具是一款非常好用的个m3u8视频工具可以帮助我们对视频进行很好的处理.M3u8视频合并软件支持各种短视频.Mp4文件,通过M3u8合并工具可以快速将这些视频合并在一起.软件操作简单, ...

  4. Java 字符串转码工具类

    StringConvertUtils.java package javax.utils;/*** 字符串转码工具类* * @author Logan* @createDate 2019-04-01* ...

  5. java将链接生成二维码工具类

    一.添加依赖 <!-- 生成二维码--><dependency><groupId>com.google.zxing</groupId><artif ...

  6. java获取视频第一帧工具类

    java获取视频文件第一帧,为了防止黑画面,此例取第五帧,本例子采用maven形式,可以获取视频的文件大小. 1. pom.xml 添加引用jar包 jdk采用1.8,日志自行添加即可,这里使用的是l ...

  7. 视频提取关键帧工具类KeyFramesExtractUtils.py,动态支持三种取帧方式,关键参数可配置,代码经过优化处理,效果和性能更好。

    同步上一期视频关键帧提取方法: 视频提取关键帧的三种方式[已调通]_君临天下tjm的博客-CSDN博客_视频关键帧提取关键代码如下:# -*- coding: utf-8 -*-"" ...

  8. Java二维码工具类(使用zxing实现,可支持logo)

    本工具类基于Google二维码框架zxing3.1.0实现. 1. pom.xml中依赖包设置 <dependency><groupId>com.google.zxing< ...

  9. com.google.zxing 二维码工具类

    com.google.zxing 二维码工具类 pom 工具类 使用 pom <dependency><groupId>com.google.zxing</groupId ...

最新文章

  1. 反思深度学习与传统计算机视觉的关系
  2. 今天开始学习shell编程!!!
  3. Nmap中文手册浅析
  4. vmstat命令列出的属性详解
  5. signature=800c2934bb72de8d2912c36e4444ceb9,Detection and Quantification of Stiction
  6. creat-react-app 支持 less
  7. fileoutputstream 文件不存在_总结Java中创建并写文件的5种方式
  8. AI即开即用,这是悄然推出的“腾讯最新AI技术”小程序
  9. caffeine java1.7_Caffeine高性能命中率近似最优的Java缓存库
  10. OpenRefine使用教程
  11. Atitit 项目常用模块 非业务模块 通用技术模块 attilax大总结 理论上可行。但要限制接口方式。 不然现在很多ui与后端接口模式很多,导致组合爆炸。。。 常用模块也就100来个而已。。
  12. 华为服务器麒麟系统,麒麟服务器
  13. 如何在TransCAD中制作美观的地图
  14. 【今日头条测试开发笔试】部分题目总结
  15. 如何获取ppt内的视频文件
  16. Python herhan学习 day2
  17. 自动驾驶 4-5 自行车模型的横向动力学 Lateral Dynamics of Bicycle Model
  18. When and why vgs command can change metadata and incur old metadata to be backed up?
  19. Unity 托管内存(Managed Memory)
  20. 3第三课:区块链的激励机制

热门文章

  1. Bash bug漏洞目前最新最全的修复方式
  2. 全双工,半双工和半工的区别
  3. inux 快速建站
  4. 面试点:五句话教你计算属性和和侦听器区别
  5. 一建经济公式存入计算机,【2017一建《工程经济》干货第二篇:工程经济必记5个计算公式】- 环球网校...
  6. 虐猫事件-萝北县声明及当事人道歉信
  7. uwsgi模式_一篇就弄懂WSGI、uwsgi和uWSGI的区别
  8. java mvvm框架实例_什么是MVVM框架?
  9. lightning接口_Lightning+Micro USB+Type-C数据线转接头如何选择
  10. TS类型体操 之 字符串的妙用