废话不多说,直接上代码:

这是转码工具类:

  1. package com.gcsoft.pyas.sysbase.utils;
  2.  
  3. import com.gcsoft.pyas.AppProperties;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Component;
  8.  
  9. import java.io.File;
  10. import java.io.IOException;
  11. import java.io.InputStream;
  12. import java.util.ArrayList;
  13. import java.util.List;
  14. import java.util.UUID;
  15.  
  16. /**
  17. * 视频转码工具类
  18. *
  19. * @author jwc
  20. */
  21. @Component
  22. public class ConverVideoUtils {
  23. @Autowired
  24. private AppProperties appProperties;
  25.  
  26. protected final Logger logger = LoggerFactory.getLogger(this.getClass());
  27.  
  28. /**
  29. * 转换视频格式
  30. *
  31. * @param sourceVideoPath 视频地址
  32. * @return
  33. */
  34. public String beginConver(String sourceVideoPath) {
  35. //转码格式
  36. String targetExtension = appProperties.getVideoFormat();
  37. //是否删除原文件
  38. Boolean isDeleteResult = appProperties.getIsDeleteResult();
  39. File fi = new File(sourceVideoPath);
  40. String fileName = fi.getName();
  41. //文件名不带扩展名
  42. String fileRealName = fileName.substring(0, fileName.lastIndexOf("."));
  43. logger.info("接收到文件(" + sourceVideoPath + ")需要转换");
  44. if (!checkfile(sourceVideoPath)) {
  45. logger.error(sourceVideoPath + "文件不存在" + " ");
  46. return "";
  47. }
  48. long beginTime = System.currentTimeMillis();
  49. logger.info("开始转文件(" + sourceVideoPath + ")");
  50. String path = process(fileRealName, sourceVideoPath, targetExtension, isDeleteResult);
  51. if (StringUtil.isNotEmpty(path)) {
  52. logger.info("转换成功");
  53. long endTime = System.currentTimeMillis();
  54. long timeCha = (endTime - beginTime);
  55. String totalTime = sumTime(timeCha);
  56. logger.info("转换视频格式共用了:" + totalTime + " ");
  57. if (isDeleteResult) {
  58. deleteFile(sourceVideoPath);
  59. }
  60. return path;
  61. } else {
  62. return "";
  63. }
  64. }
  65.  
  66. /**
  67. * 实际转换视频格式的方法
  68. *
  69. * @param fileRealName 文件名不带扩展名
  70. * @param sourceVideoPath 原文件地址
  71. * @param targetExtension 目标视频扩展名
  72. * @param isDeleteResult 转换完成后是否删除源文件
  73. * @return
  74. */
  75. private String process(String fileRealName, String sourceVideoPath, String targetExtension, boolean isDeleteResult) {
  76. int type = checkContentType(sourceVideoPath);
  77. String path = "";
  78. if (type == 0) {
  79. //如果type为0用ffmpeg直接转换
  80. path = processVideoFormat(sourceVideoPath, fileRealName, targetExtension, isDeleteResult);
  81. } else if (type == 1) {
  82. //如果type为1,将其他文件先转换为avi,然后在用ffmpeg转换为指定格式
  83. String aviFilePath = processAVI(fileRealName, sourceVideoPath);
  84. if (aviFilePath == null) {
  85. // avi文件没有得到
  86. return "";
  87. } else {
  88. logger.info("开始转换:");
  89. path = processVideoFormat(aviFilePath, fileRealName, targetExtension, isDeleteResult);
  90. if (isDeleteResult) {
  91. deleteFile(aviFilePath);
  92. }
  93. }
  94. }
  95. return path;
  96. }
  97.  
  98. /**
  99. * 检查文件类型
  100. *
  101. * @param sourceVideoPath 原文件地址
  102. * @return
  103. */
  104. private int checkContentType(String sourceVideoPath) {
  105. String type = sourceVideoPath.substring(sourceVideoPath.lastIndexOf(".") + 1).toLowerCase();
  106. // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
  107. if (type.equals("avi")) {
  108. return 0;
  109. } else if (type.equals("mpg")) {
  110. return 0;
  111. } else if (type.equals("wmv")) {
  112. return 0;
  113. } else if (type.equals("3gp")) {
  114. return 0;
  115. } else if (type.equals("mov")) {
  116. return 0;
  117. } else if (type.equals("mp4")) {
  118. return 0;
  119. } else if (type.equals("asf")) {
  120. return 0;
  121. } else if (type.equals("asx")) {
  122. return 0;
  123. } else if (type.equals("flv")) {
  124. return 0;
  125. }
  126. // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),
  127. // 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
  128. else if (type.equals("wmv9")) {
  129. return 1;
  130. } else if (type.equals("rm")) {
  131. return 1;
  132. } else if (type.equals("rmvb")) {
  133. return 1;
  134. }
  135. return 9;
  136. }
  137.  
  138. /**
  139. * 检查文件是否存在
  140. *
  141. * @param path 文件地址
  142. * @return
  143. */
  144. private boolean checkfile(String path) {
  145. File file = new File(path);
  146. if (!file.isFile()) {
  147. return false;
  148. } else {
  149. return true;
  150. }
  151. }
  152.  
  153. /**
  154. * 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
  155. *
  156. * @param fileRealName 文件名不带扩展名
  157. * @param sourceVideoPath 原文件地址
  158. * @return
  159. */
  160. private String processAVI(String fileRealName, String sourceVideoPath) {
  161. /**
  162. * mencoder.exe的地址
  163. */
  164. String menCoderPath = appProperties.getMencoderPath();
  165. /**
  166. * 转码后的存放视频地址 avi格式
  167. */
  168. String videoFolder = appProperties.getUploadAndFormatPath();
  169.  
  170. List<String> commend = new java.util.ArrayList<>();
  171. commend.add(menCoderPath);
  172. commend.add(sourceVideoPath);
  173. commend.add("-oac");
  174. commend.add("mp3lame");
  175. commend.add("-lameopts");
  176. commend.add("preset=64");
  177. commend.add("-ovc");
  178. commend.add("xvid");
  179. commend.add("-xvidencopts");
  180. commend.add("bitrate=600");
  181. commend.add("-of");
  182. commend.add("avi");
  183. commend.add("-o");
  184. commend.add(videoFolder + fileRealName + ".avi");
  185. try {
  186. ProcessBuilder builder = new ProcessBuilder();
  187. builder.command(commend);
  188. Process p = builder.start();
  189. doWaitFor(p);
  190. return videoFolder + fileRealName + ".avi";
  191. } catch (Exception e) {
  192. e.printStackTrace();
  193. return null;
  194. }
  195. }
  196.  
  197. /**
  198. * 转换为指定格式
  199. * ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
  200. *
  201. * @param oldFilePath 源文件地址
  202. * @param fileRealName 文件名不带扩展名
  203. * @param targetExtension 目标格式扩展名 .xxx
  204. * @return
  205. */
  206. private String processVideoFormat(String oldFilePath, String fileRealName, String targetExtension, Boolean isDeleteResult) {
  207. /**
  208. * ffmpeg.exe的地址
  209. */
  210. String ffmpegPath = appProperties.getFfmpegPath();
  211. /**
  212. * 转码后的存放视频地址 mp4格式
  213. */
  214. String targetFolder = appProperties.getUploadAndFormatPath();
  215. if (!checkfile(oldFilePath)) {
  216. logger.error(oldFilePath + "文件不存在");
  217. return "";
  218. }
  219. List<String> commend = new ArrayList<>();
  220. commend.add(ffmpegPath);
  221. commend.add("-i");
  222. commend.add(oldFilePath);
  223. commend.add("-vcodec");
  224. commend.add("mpeg4");
  225. commend.add("-q");
  226. commend.add("0");
  227. commend.add("-y");
  228. commend.add(targetFolder + fileRealName + targetExtension);
  229. try {
  230. ProcessBuilder builder = new ProcessBuilder();
  231. builder.command(commend);
  232. Process p = builder.start();
  233. doWaitFor(p);
  234. p.destroy();
  235. String videoPath = targetFolder + fileRealName + targetExtension;
  236. String path = this.processVideoFormatH264(videoPath, ffmpegPath, targetFolder, targetExtension, isDeleteResult);
  237. return path;
  238. } catch (Exception e) {
  239. e.printStackTrace();
  240. return "";
  241. }
  242. }
  243.  
  244. /**
  245. * 将mpeg4转为h264编码 为了支持播放器
  246. *
  247. * @param path
  248. * @param ffmpegPath
  249. * @return
  250. */
  251. private String processVideoFormatH264(String path, String ffmpegPath, String targetFolder, String targetExtension, Boolean isDeleteResult) {
  252. if (!checkfile(path)) {
  253. logger.error(path + "文件不存在");
  254. return "";
  255. }
  256. String newFilePath = targetFolder + UUID.randomUUID().toString() + targetExtension;
  257. List<String> commend = new ArrayList<>();
  258. commend.add(ffmpegPath);
  259. commend.add("-i");
  260. commend.add(path);
  261. commend.add("-vcodec");
  262. commend.add("h264");
  263. commend.add("-q");
  264. commend.add("0");
  265. commend.add("-y");
  266. commend.add(newFilePath);
  267. try {
  268. ProcessBuilder builder = new ProcessBuilder();
  269. builder.command(commend);
  270. Process p = builder.start();
  271. doWaitFor(p);
  272. p.destroy();
  273. if (isDeleteResult) {
  274. deleteFile(path);
  275. }
  276. return newFilePath;
  277. } catch (Exception e) {
  278. e.printStackTrace();
  279. return "";
  280. }
  281. }
  282.  
  283. public int doWaitFor(Process p) {
  284. InputStream in = null;
  285. InputStream err = null;
  286. int exitValue = -1;
  287. try {
  288. in = p.getInputStream();
  289. err = p.getErrorStream();
  290. boolean finished = false;
  291.  
  292. while (!finished) {
  293. try {
  294. while (in.available() > 0) {
  295. in.read();
  296. }
  297. while (err.available() > 0) {
  298. err.read();
  299. }
  300.  
  301. exitValue = p.exitValue();
  302. finished = true;
  303.  
  304. } catch (IllegalThreadStateException e) {
  305. Thread.sleep(500);
  306. }
  307. }
  308. } catch (Exception e) {
  309. logger.error("doWaitFor();: unexpected exception - " + e.getMessage());
  310. } finally {
  311. try {
  312. if (in != null) {
  313. in.close();
  314. }
  315.  
  316. } catch (IOException e) {
  317. logger.info(e.getMessage());
  318. }
  319. if (err != null) {
  320. try {
  321. err.close();
  322. } catch (IOException e) {
  323. logger.info(e.getMessage());
  324. }
  325. }
  326. }
  327. return exitValue;
  328. }
  329.  
  330. /**
  331. * 删除文件方法
  332. *
  333. * @param filepath
  334. */
  335. public void deleteFile(String filepath) {
  336. File file = new File(filepath);
  337. if (file.delete()) {
  338. logger.info("文件" + filepath + "已删除");
  339. }
  340. }
  341.  
  342. /**
  343. * 计算转码时间
  344. *
  345. * @param ms
  346. * @return
  347. */
  348. public String sumTime(long ms) {
  349. int ss = 1000;
  350. long mi = ss * 60;
  351. long hh = mi * 60;
  352. long dd = hh * 24;
  353.  
  354. long day = ms / dd;
  355. long hour = (ms - day * dd) / hh;
  356. long minute = (ms - day * dd - hour * hh) / mi;
  357. long second = (ms - day * dd - hour * hh - minute * mi) / ss;
  358. long milliSecond = ms - day * dd - hour * hh - minute * mi - second
  359. * ss;
  360.  
  361. String strDay = day < 10 ? "0" + day + "天" : "" + day + "天";
  362. String strHour = hour < 10 ? "0" + hour + "小时" : "" + hour + "小时";
  363. String strMinute = minute < 10 ? "0" + minute + "分" : "" + minute + "分";
  364. String strSecond = second < 10 ? "0" + second + "秒" : "" + second + "秒";
  365. String strMilliSecond = milliSecond < 10 ? "0" + milliSecond : ""
  366. + milliSecond;
  367. strMilliSecond = milliSecond < 100 ? "0" + strMilliSecond + "毫秒" : ""
  368. + strMilliSecond + " 毫秒";
  369. return strDay + " " + strHour + ":" + strMinute + ":" + strSecond + " "
  370. + strMilliSecond;
  371.  
  372. }
  373. }

工具类用到的参数

  1. #视频上传和转码后存放的位置
  2. video.trans.coding=D:/PYAS/TMS/upload/video/
  3. #ffmpeg地址
  4. tool.ffmpeg.path=D:/FFmpeg/ffmpeg.exe
  5. #mencoder地址
  6. tool.mencoder.path=D:/FFmpeg/mencoder.exe
  7. #转码格式
  8. video.format=.mp4
  9. #是否删除源文件
  10. video.isdelete.result=false

工具类用到的转码工具分别是:

  ffmpeg、mencoder

  转码工具 密码 eada

java实现视频转码的更多相关文章

  1. Java实现视频转码或压缩demo.

    先点击这里下载资源包(包括jar和文档) 使用这个资源包,处理起来很简单. demo如下: import java.io.File; import it.sauronsoftware.jave.Aud ...

  2. java ffmpeg视频转码(自测通过)

    import java.io.*; public class VideoTransfer { //ffmepg文件 安装目录 private static String ffmpeg = " ...

  3. Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能

    视频网站中提供的在线视频播放功能,播放的都是FLV格式的文件,它是Flash动画文件,可通过Flash制作的播放器来播放该文件.项目中用制作的player.swf播放器. 多媒体视频处理工具FFmpe ...

  4. Java Web 中使用ffmpeg实现视频转码、视频截图

    Java Web 中使用ffmpeg实现视频转码.视频截图 转载自:[ http://www.cnblogs.com/dennisit/archive/2013/02/16/2913287.html  ...

  5. Java实现视频网站的视频上传、视频转码、及视频播放功能(ffmpeg)

    视频网站中提供的在线视频播放功能,播放的都是FLV格式的文件,它是Flash动画文件,可通过Flash制作的播放器来播放该文件.项目中用制作的player.swf播放器. 多媒体视频处理工具FFmpe ...

  6. BAT推荐免费下载JAVA转型大数据开发全链路教程(视频+源码)价值19880元

    如今随着环境的改变,物联网.AI.大数据.人工智能等,是未来的大趋势,而大数据是这些基石,万物互联,机器学习都是大数据应用场景! 为什么要学习大数据?我们JAVA到底要不要转型大数据? 好比问一个程序 ...

  7. 利用JAVA生成二维码

    本文章整理于慕课网的学习视频<JAVA生成二维码>,如果想看视频内容请移步慕课网. 维基百科上对于二维码的解释. 二维条码是指在一维条码的基础上扩展出另一维具有可读性的条码,使用黑白矩形图 ...

  8. 最简单的基于FFmpeg的移动端样例:Android 视频转码器

    ===================================================== 最简单的基于FFmpeg的移动端样例系列文章列表: 最简单的基于FFmpeg的移动端样例:A ...

  9. 【JDK1.8】 Java小白的源码学习系列:HashMap

    目录 Java小白的源码学习系列:HashMap 官方文档解读 基本数据结构 基本源码解读 基本成员变量 构造器 巧妙的tableSizeFor put方法 巧妙的hash方法 JDK1.8的putV ...

随机推荐

  1. 使用async/await消除callback hell

    使用async/await消除callback hell 通过Future回调中再返回Future的方式虽然能避免层层嵌套,但是还是有一层回调,有没有一种方式能够让我们可以像写同步代码那样来执行异步任 ...

  2. 51nod1681 公共祖先

    [传送门] 很明显,可以转化成求每个点在两棵树中对应的子树中有多少个相同的节点,对答案的贡献就是$C(x, 2)$.关键就是怎么求这个东西.一是,对第一棵树求出dfs序,然后dfs第二棵树,用树状数组 ...

  3. JavaScript基础11——ES5和ES6

    ES5↓↓↓ bind方法/this关键字     bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入bind()方法的第一个参数作为this,传入 bin ...

  4. 使用mustache 做为docker容器运行动态配置工具

    很多时候我们需要在启动容器的时候基于配置文件运行,如果在配置比较简单的时候我们可以通过环境变量 注入,同时当前12 factors 越来越融入大家的开发中了(对于配置通过环境变量处理),但是好多老的软 ...

  5. c# 如何进行动态加载dll

    最近遇到了在c#中如何进行动态加载dll的话,搞定了,下面介绍一下自己的步骤. 1,新建dll. 打开vs,新建project->Class Library->项目名为testdll1.在 ...

  6. 洛谷 P1462 通往奥格瑞玛的道路 题解

    P1462 通往奥格瑞玛的道路 题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡 ...

  7. word2vector的tensorflow代码实现

    import collections import math import os import random import zipfile import numpy as np import urll ...

  8. Foxmail: 错误信息::ssl连接错误, errorCode: 5,各种解决方案的大杂烩。

    1.  收件数据过多,删除部分邮件可解决 我尝试失败,在foxmail把收件箱全部删完了没解决. 2.  网上最常见的解决方法 https://help.foxmail.com/cgi-bin/hel ...

  9. unicode欺骗—— hctf - admin

    查看源代码,发现<!-- you are not admin --> 提示要以管理员身份登陆 尝试注册管理员账号,提示The username has been registered 于是 ...

  10. JPA的一对多,多对多用法

    一.@OneToOne关系映射 JPA使用@OneToOne来标注一对一的关系. 实体 People :用户. 实体 Address:家庭住址. People 和 Address 是一对一的关系. 这 ...