java實(shí)現(xiàn)視頻轉(zhuǎn)碼工具類(lèi)
廢話不多說(shuō),直接上代碼:
這是轉(zhuǎn)碼工具類(lèi):
package com.gcsoft.pyas.sysbase.utils; import com.gcsoft.pyas.AppProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; 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; /** * 視頻轉(zhuǎn)碼工具類(lèi) * * @author jwc */ @Component public class ConverVideoUtils { @Autowired private AppProperties appProperties; protected final Logger logger = LoggerFactory.getLogger(this.getClass()); /** * 轉(zhuǎn)換視頻格式 * * @param sourceVideoPath 視頻地址 * @return */ public String beginConver(String sourceVideoPath) { //轉(zhuǎn)碼格式 String targetExtension = appProperties.getVideoFormat(); //是否刪除原文件 Boolean isDeleteResult = appProperties.getIsDeleteResult(); File fi = new File(sourceVideoPath); String fileName = fi.getName(); //文件名不帶擴(kuò)展名 String fileRealName = fileName.substring(0, fileName.lastIndexOf(".")); logger.info("接收到文件(" + sourceVideoPath + ")需要轉(zhuǎn)換"); if (!checkfile(sourceVideoPath)) { logger.error(sourceVideoPath + "文件不存在" + " "); return ""; } long beginTime = System.currentTimeMillis(); logger.info("開(kāi)始轉(zhuǎn)文件(" + sourceVideoPath + ")"); String path = process(fileRealName, sourceVideoPath, targetExtension, isDeleteResult); if (StringUtil.isNotEmpty(path)) { logger.info("轉(zhuǎn)換成功"); long endTime = System.currentTimeMillis(); long timeCha = (endTime - beginTime); String totalTime = sumTime(timeCha); logger.info("轉(zhuǎn)換視頻格式共用了:" + totalTime + " "); if (isDeleteResult) { deleteFile(sourceVideoPath); } return path; } else { return ""; } } /** * 實(shí)際轉(zhuǎn)換視頻格式的方法 * * @param fileRealName 文件名不帶擴(kuò)展名 * @param sourceVideoPath 原文件地址 * @param targetExtension 目標(biāo)視頻擴(kuò)展名 * @param isDeleteResult 轉(zhuǎn)換完成后是否刪除源文件 * @return */ private String process(String fileRealName, String sourceVideoPath, String targetExtension, boolean isDeleteResult) { int type = checkContentType(sourceVideoPath); String path = ""; if (type == 0) { //如果type為0用ffmpeg直接轉(zhuǎn)換 path = processVideoFormat(sourceVideoPath, fileRealName, targetExtension, isDeleteResult); } else if (type == 1) { //如果type為1,將其他文件先轉(zhuǎn)換為avi,然后在用ffmpeg轉(zhuǎn)換為指定格式 String aviFilePath = processAVI(fileRealName, sourceVideoPath); if (aviFilePath == null) { // avi文件沒(méi)有得到 return ""; } else { logger.info("開(kāi)始轉(zhuǎn)換:"); path = processVideoFormat(aviFilePath, fileRealName, targetExtension, isDeleteResult); if (isDeleteResult) { deleteFile(aviFilePath); } } } return path; } /** * 檢查文件類(lèi)型 * * @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; } // 對(duì)ffmpeg無(wú)法解析的文件格式(wmv9,rm,rmvb等), // 可以先用別的工具(mencoder)轉(zhuǎn)換為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; } } /** * 對(duì)ffmpeg無(wú)法解析的文件格式(wmv9,rm,rmvb等), 可以先用別的工具(mencoder)轉(zhuǎn)換為avi(ffmpeg能解析的)格式. * * @param fileRealName 文件名不帶擴(kuò)展名 * @param sourceVideoPath 原文件地址 * @return */ private String processAVI(String fileRealName, String sourceVideoPath) { /** * mencoder.exe的地址 */ String menCoderPath = appProperties.getMencoderPath(); /** * 轉(zhuǎn)碼后的存放視頻地址 avi格式 */ String videoFolder = appProperties.getUploadAndFormatPath(); List<String> 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 = new ProcessBuilder(); builder.command(commend); Process p = builder.start(); doWaitFor(p); return videoFolder + fileRealName + ".avi"; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 轉(zhuǎn)換為指定格式 * ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) * * @param oldFilePath 源文件地址 * @param fileRealName 文件名不帶擴(kuò)展名 * @param targetExtension 目標(biāo)格式擴(kuò)展名 .xxx * @return */ private String processVideoFormat(String oldFilePath, String fileRealName, String targetExtension, Boolean isDeleteResult) { /** * ffmpeg.exe的地址 */ String ffmpegPath = appProperties.getFfmpegPath(); /** * 轉(zhuǎn)碼后的存放視頻地址 mp4格式 */ String targetFolder = appProperties.getUploadAndFormatPath(); if (!checkfile(oldFilePath)) { logger.error(oldFilePath + "文件不存在"); return ""; } List<String> 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 = new ProcessBuilder(); 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); return path; } catch (Exception e) { e.printStackTrace(); return ""; } } /** * 將mpeg4轉(zhuǎn)為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("-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; } /** * 刪除文件方法 * * @param filepath */ public void deleteFile(String filepath) { File file = new File(filepath); if (file.delete()) { logger.info("文件" + filepath + "已刪除"); } } /** * 計(jì)算轉(zhuǎn)碼時(shí)間 * * @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 + "小時(shí)" : "" + hour + "小時(shí)"; 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; } }
工具類(lèi)用到的參數(shù)
#視頻上傳和轉(zhuǎn)碼后存放的位置 video.trans.coding=D:/PYAS/TMS/upload/video/ #ffmpeg地址 tool.ffmpeg.path=D:/FFmpeg/ffmpeg.exe #mencoder地址 tool.mencoder.path=D:/FFmpeg/mencoder.exe #轉(zhuǎn)碼格式 video.format=.mp4 #是否刪除源文件 video.isdelete.result=false
工具類(lèi)用到的轉(zhuǎn)碼工具分別是:
ffmpeg、mencoder
到此這篇關(guān)于java實(shí)現(xiàn)視頻轉(zhuǎn)碼的文章就介紹到這了,更多相關(guān)java視頻轉(zhuǎn)碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java日期時(shí)間字符串和毫秒相互轉(zhuǎn)換的方法
這篇文章主要為大家詳細(xì)介紹了Java日期時(shí)間字符串和毫秒相互轉(zhuǎn)換的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12spring boot輸入數(shù)據(jù)校驗(yàn)(validation)的實(shí)現(xiàn)過(guò)程
web項(xiàng)目中,用戶(hù)的輸入總是被假定不安全不正確的,在被處理前需要做校驗(yàn)。本文介紹在spring boot項(xiàng)目中實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)的過(guò)程,通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-09-09java實(shí)現(xiàn)壓縮字符串和java字符串過(guò)濾
這篇文章主要介紹了java實(shí)現(xiàn)壓縮字符串和java字符串過(guò)濾,需要的朋友可以參考下2014-04-04spring使用ehcache實(shí)現(xiàn)頁(yè)面緩存示例
這篇文章主要介紹了spring使用ehcache實(shí)現(xiàn)頁(yè)面緩存示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02使用Java創(chuàng)建數(shù)據(jù)透視表并導(dǎo)出為PDF的方法
數(shù)據(jù)透視分析是一種強(qiáng)大的工具,可以幫助我們從大量數(shù)據(jù)中提取有用信息并進(jìn)行深入分析,本文將介紹如何使用Java來(lái)構(gòu)建PivotTable以及實(shí)現(xiàn)數(shù)據(jù)透視分析,并將其導(dǎo)出為PDF2023-10-10