java調(diào)用ffmpeg實(shí)現(xiàn)轉(zhuǎn)換視頻
最近由于項(xiàng)目需要把不同格式的視頻轉(zhuǎn)換為ts流,故研究了一下ffmpeg。在網(wǎng)上找了很多資料,主要參考了Java+Windows+ffmpeg實(shí)現(xiàn)視頻轉(zhuǎn)換功能。
期間也加了幾個(gè)qq群,咨詢(xún)了各大高手,其中在代碼中關(guān)于ffmpeg的命令就是來(lái)自其中一個(gè)qq群里面的大神。
下載相關(guān)文件
ffmpeg地址,我下載是windows 64位static版本。
xuggler下載地址
下面的代碼我上傳到了github,需要的可以下載下來(lái)看看。
步驟:
1.研究java如何調(diào)用外部程序
2.研究ffmpeg轉(zhuǎn)換視頻格式的命令
3.利用xuggle獲取ffmpeg解析的ts流的時(shí)長(zhǎng)、分辨率以及文件大小。
下面直接上代碼:
1.ffmpeg轉(zhuǎn)換實(shí)現(xiàn)
package vedio.ffmpeg; import java.io.File; import java.util.ArrayList; import java.util.List; public class FfmpegUtil { public static Boolean ffmpeg(StringffmpegPath, String inputPath, String outputPath) throwsFFmpegException{ if (!checkfile(inputPath)) { throw newFFmpegException("文件格式不合法"); } int type =checkContentType(inputPath); List command = getFfmpegCommand(type,ffmpegPath, inputPath, outputPath); if (null != command &&command.size() > 0) { return process(command); } return false; } private static int checkContentType(StringinputPath) { String type =inputPath.substring(inputPath.lastIndexOf(".") + 1,inputPath.length()).toLowerCase(); //ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) if (type.equals("avi")) { return 1; } else if (type.equals("mpg")){ return 1; } else if (type.equals("wmv")){ return 1; } else if (type.equals("3gp")){ return 1; } else if (type.equals("mov")){ return 1; } else if (type.equals("mp4")){ return 1; } else if(type.equals("mkv")){ return 1; }else if (type.equals("asf")){ return 0; } else if (type.equals("flv")){ return 0; }else if (type.equals("rm")){ return 0; } else if (type.equals("rmvb")){ return 1; } return 9; } private static boolean checkfile(Stringpath) { File file = new File(path); if (!file.isFile()) { return false; } return true; } private static boolean process(Listcommand) throws FFmpegException{ try { if (null == command || command.size() ==0) return false; Process videoProcess = newProcessBuilder(command).redirectErrorStream(true).start(); newPrintStream(videoProcess.getErrorStream()).start(); newPrintStream(videoProcess.getInputStream()).start(); int exitcode =videoProcess.waitFor(); if (exitcode == 1) { return false; } return true; } catch (Exception e) { throw new FFmpegException("file uploadfailed",e); } } private static List getFfmpegCommand(inttype, String ffmpegPath, String oldfilepath, String outputPath)throws FFmpegException { List command = newArrayList(); if (type == 1) { command.add(ffmpegPath +"\\ffmpeg"); command.add("-i"); command.add(oldfilepath); command.add("-c:v"); command.add("libx264"); command.add("-x264opts"); command.add("force-cfr=1"); command.add("-c:a"); command.add("mp2"); command.add("-b:a"); command.add("256k"); command.add("-vsync"); command.add("cfr"); command.add("-f"); command.add("mpegts"); command.add(outputPath); } else if(type==0){ command.add(ffmpegPath +"\\ffmpeg"); command.add("-i"); command.add(oldfilepath); command.add("-c:v"); command.add("libx264"); command.add("-x264opts"); command.add("force-cfr=1"); command.add("-vsync"); command.add("cfr"); command.add("-vf"); command.add("idet,yadif=deint=interlaced"); command.add("-filter_complex"); command.add("aresample=async=1000"); command.add("-c:a"); command.add("libmp3lame"); command.add("-b:a"); command.add("192k"); command.add("-pix_fmt"); command.add("yuv420p"); command.add("-f"); command.add("mpegts"); command.add(outputPath); }else{ throw newFFmpegException("不支持當(dāng)前上傳的文件格式"); } return command; } } class PrintStream extends Thread{ java.io.InputStream __is =null; public PrintStream(java.io.InputStream is){ __is = is; } public void run() { try { while (this != null) { int _ch = __is.read(); if (_ch == -1) { break; } else { System.out.print((char) _ch); } } } catch (Exception e) { e.printStackTrace(); } } }
2.調(diào)用測(cè)試類(lèi)
package vedio.ffmpeg; public class ConvertVedio { public static void convertVedio(StringinputPath){ String ffmpegPath =getFfmpegPath(); String outputPath =getOutputPath(inputPath); try { FfmpegUtil.ffmpeg(ffmpegPath, inputPath,outputPath); } catch (FFmpegException e) { e.printStackTrace(); } } private static String getFfmpegPath(){ return "ffmpeg"; } private static String getOutputPath(StringinputPath) { return inputPath.substring(0,inputPath.lastIndexOf(".")).toLowerCase() + ".ts"; } }
3.自定義的異常類(lèi)
package vedio.ffmpeg; public class FFmpegException extendsException { private static final long serialVersionUID= 1L; public FFmpegException() { super(); } public FFmpegException(String message){ super(message); } public FFmpegException(Throwable cause){ super(cause); } public FFmpegException(String message,Throwable cause) { super(message, cause); } }
4.獲取ts流的時(shí)長(zhǎng)、大小以及分辨率(用到了Xuggle,需要下載對(duì)應(yīng)jar包)
importcom.xuggle.xuggler.ICodec; importcom.xuggle.xuggler.IContainer; importcom.xuggle.xuggler.IStream; importcom.xuggle.xuggler.IStreamCoder; */ public static void getVedioInfo(String filename){ // first we create a Xuggler containerobject IContainer container =IContainer.make(); // we attempt to open up thecontainer int result = container.open(filename,IContainer.Type.READ, null); // check if the operation wassuccessful if (result<0) return; // query how many streams the call to openfound int numStreams =container.getNumStreams(); // query for the total duration long duration =container.getDuration(); // query for the file size long fileSize =container.getFileSize(); long secondDuration =duration/1000000; System.out.println("時(shí)長(zhǎng):"+secondDuration+"秒"); System.out.println("文件大小:"+fileSize+"M"); for (int i=0; i IStreamstream = container.getStream(i); IStreamCoder coder = stream.getStreamCoder(); if(coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO){ System.out.println("視頻寬度:"+coder.getWidth()); System.out.println("視頻高度:"+coder.getHeight()); } } }
以上就是在開(kāi)發(fā)過(guò)程中做的全部,希望大家多多學(xué)習(xí),交流!
相關(guān)文章
springboot省去配置Tomcat的步驟問(wèn)題
這篇文章主要介紹了springboot省去配置Tomcat的步驟問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06maven手動(dòng)上傳jar包示例及圖文步驟過(guò)程
這篇文章主要為大家介紹了maven手動(dòng)上傳jar包示例及圖文步驟過(guò)程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03Java?數(shù)據(jù)結(jié)構(gòu)與算法系列精講之漢諾塔
漢諾塔是源于印度一個(gè)古老傳說(shuō)的益智玩具。大梵天創(chuàng)造世界時(shí)做了三根石柱,在一根柱子上從下往上按大小順序摞著64片黃金圓盤(pán)。大梵天命令婆羅門(mén)把圓盤(pán)從下面開(kāi)始按大小順序重新擺放在另一根柱子上。并且規(guī)定,在小圓盤(pán)上不能放大圓盤(pán),三根柱子之間一次只能移動(dòng)一個(gè)圓盤(pán)2022-02-02詳解MyBatis-Puls中saveBatch批量添加慢的問(wèn)題
本文主要介紹了詳解MyBatis-Puls中saveBatch批量添加慢的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01JAVA幫助文檔全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版整理
JDK(Java Development Kit,Java開(kāi)發(fā)包,Java開(kāi)發(fā)工具)是一個(gè)寫(xiě)Java的applet和應(yīng)用程序的程序開(kāi)發(fā)環(huán)境。它由一個(gè)處于操作系統(tǒng)層之上的運(yùn)行環(huán)境還有開(kāi)發(fā)者編譯,調(diào)試和運(yùn)行用Java語(yǔ)言寫(xiě)的applet和應(yīng)用程序所需的工具組成2014-01-01通過(guò)Java實(shí)現(xiàn)設(shè)置Word文檔頁(yè)邊距的方法詳解
頁(yè)邊距是指頁(yè)面的邊線(xiàn)到文字的距離。通??稍陧?yè)邊距內(nèi)部的可打印區(qū)域中插入文字和圖形等。今天這篇文章將為您展示如何通過(guò)編程方式,設(shè)置Word?文檔頁(yè)邊距,感興趣的可以了解一下2023-02-02IDEA如何實(shí)現(xiàn)顯示類(lèi)的所有方法
這篇文章主要介紹了IDEA如何顯示類(lèi)的所有方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03