packagecom.gcsoft.pyas.sysbase.utils;importcom.gcsoft.pyas.AppProperties;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importjava.io.File;importjava.io.IOException;importjava.io.InputStream;importjava.util.ArrayList;importjava.util.List;importjava.util.UUID;/*** 视频转码工具类
*
*@authorjwc*/@Componentpublic classConverVideoUtils {
@AutowiredprivateAppProperties appProperties;protected final Logger logger = LoggerFactory.getLogger(this.getClass());/*** 转换视频格式
*
*@paramsourceVideoPath 视频地址
*@return
*/
publicString beginConver(String sourceVideoPath) {//转码格式
String targetExtension =appProperties.getVideoFormat();//是否删除原文件
Boolean isDeleteResult =appProperties.getIsDeleteResult();
File fi= newFile(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(StringUtil.isNotEmpty(path)) {
logger.info("转换成功");long endTime =System.currentTimeMillis();long timeCha = (endTime -beginTime);
String totalTime=sumTime(timeCha);
logger.info("转换视频格式共用了:" + totalTime + " ");if(isDeleteResult) {
deleteFile(sourceVideoPath);
}returnpath;
}else{return "";
}
}/*** 实际转换视频格式的方法
*
*@paramfileRealName 文件名不带扩展名
*@paramsourceVideoPath 原文件地址
*@paramtargetExtension 目标视频扩展名
*@paramisDeleteResult 转换完成后是否删除源文件
*@return
*/
private String process(String fileRealName, String sourceVideoPath, String targetExtension, booleanisDeleteResult) {int type =checkContentType(sourceVideoPath);
String path= "";if (type == 0) {//如果type为0用ffmpeg直接转换
path =processVideoFormat(sourceVideoPath, fileRealName, targetExtension, isDeleteResult);
}else if (type == 1) {//如果type为1,将其他文件先转换为avi,然后在用ffmpeg转换为指定格式
String aviFilePath =processAVI(fileRealName, sourceVideoPath);if (aviFilePath == null) {//avi文件没有得到
return "";
}else{
logger.info("开始转换:");
path=processVideoFormat(aviFilePath, fileRealName, targetExtension, isDeleteResult);if(isDeleteResult) {
deleteFile(aviFilePath);
}
}
}returnpath;
}/*** 检查文件类型
*
*@paramsourceVideoPath 原文件地址
*@return
*/
private intcheckContentType(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;
}/*** 检查文件是否存在
*
*@parampath 文件地址
*@return
*/
private booleancheckfile(String path) {
File file= newFile(path);if (!file.isFile()) {return false;
}else{return true;
}
}/*** 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
*
*@paramfileRealName 文件名不带扩展名
*@paramsourceVideoPath 原文件地址
*@return
*/
privateString processAVI(String fileRealName, String sourceVideoPath) {/*** mencoder.exe的地址*/String menCoderPath=appProperties.getMencoderPath();/*** 转码后的存放视频地址 avi格式*/String videoFolder=appProperties.getUploadAndFormatPath();
List commend = new java.util.ArrayList<>();
commend.add(menCoderPath);
commend.add(sourceVideoPath);
commend.add("-oac");
commend.add("mp3lame");
commend.add("-lameopts");
commend.add("preset=64");
commend.add("-ovc");
commend.add("xvid");
commend.add("-xvidencopts");
commend.add("bitrate=600");
commend.add("-of");
commend.add("avi");
commend.add("-o");
commend.add(videoFolder+ fileRealName + ".avi");try{
ProcessBuilder builder= newProcessBuilder();
builder.command(commend);
Process p=builder.start();
doWaitFor(p);return videoFolder + fileRealName + ".avi";
}catch(Exception e) {
e.printStackTrace();return null;
}
}/*** 转换为指定格式
* ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
*
*@paramoldFilePath 源文件地址
*@paramfileRealName 文件名不带扩展名
*@paramtargetExtension 目标格式扩展名 .xxx
*@return
*/
privateString processVideoFormat(String oldFilePath, String fileRealName, String targetExtension, Boolean isDeleteResult) {/*** ffmpeg.exe的地址*/String ffmpegPath=appProperties.getFfmpegPath();/*** 转码后的存放视频地址 mp4格式*/String targetFolder=appProperties.getUploadAndFormatPath();if (!checkfile(oldFilePath)) {
logger.error(oldFilePath+ "文件不存在");return "";
}
List commend = new ArrayList<>();
commend.add(ffmpegPath);
commend.add("-i");
commend.add(oldFilePath);
commend.add("-vcodec");
commend.add("mpeg4");
commend.add("-q");
commend.add("0");
commend.add("-y");
commend.add(targetFolder+ fileRealName +targetExtension);try{
ProcessBuilder builder= newProcessBuilder();
builder.command(commend);
Process p=builder.start();
doWaitFor(p);
p.destroy();
String videoPath= targetFolder + fileRealName +targetExtension;
String path= this.processVideoFormatH264(videoPath, ffmpegPath, targetFolder, targetExtension, isDeleteResult);returnpath;
}catch(Exception e) {
e.printStackTrace();return "";
}
}/*** 将mpeg4转为h264编码 为了支持播放器
*
*@parampath
*@paramffmpegPath
*@return
*/
privateString 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 commend = new ArrayList<>();
commend.add(ffmpegPath);
commend.add("-i");
commend.add(path);
commend.add("-vcodec");
commend.add("h264");
commend.add("-q");
commend.add("0");
commend.add("-y");
commend.add(newFilePath);try{
ProcessBuilder builder= newProcessBuilder();
builder.command(commend);
Process p=builder.start();
doWaitFor(p);
p.destroy();if(isDeleteResult) {
deleteFile(path);
}returnnewFilePath;
}catch(Exception e) {
e.printStackTrace();return "";
}
}public intdoWaitFor(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());
}
}
}returnexitValue;
}/*** 删除文件方法
*
*@paramfilepath*/
public voiddeleteFile(String filepath) {
File file= newFile(filepath);if(file.delete()) {
logger.info("文件" + filepath + "已删除");
}
}/*** 计算转码时间
*
*@paramms
*@return
*/
public String sumTime(longms) {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;
}
}