FFmpeg是一個開源免費跨平台的視頻和音頻流方案,屬於自由軟件,采用LGPL或GPL許可證(依據你選擇的組件)。它提供了錄制、轉換以及流化音視頻的完整解決方案。它包含了非常先進的音頻/視頻編解碼庫libavcodec,為了保證高可移植性和編解碼質量,libavcodec里很多codec都是從頭開發的。FFmpeg在Linux平台下開發,但它同樣也可以在其它操作系統環境中編譯運行。
在java開發中,FFmpeg也常被調用用來進行視頻的轉碼,錄播和直播,總的來說,FFmpeg是一款非常強大的,而且做與視頻相關的業務平台開發人員必須要學會的工具,那具體怎么實習呢,第一章我們先從分別windows和linux下調用FFmpeg進行視頻的轉碼,和對視頻的截圖做出說明解釋。
ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等),而對於ffmpeg無法解析的文件格式(wmv9,rm,rmvb等),我們在下面采用了mencoder工具,先將視頻轉換成AVI格式再用ffmpeg進行轉碼;
windows下:
1.首先需要FFmpeg和mencoder的工具。一共五個文件,點此下載,將他解壓放在你的D盤FFmpeg文件夾下。
linux下:
依次執行下面的指令
1.下載yasm-1.3.0.tar.gz這個版本:
1
|
yasm是一個完全重寫的NASM匯編。目前,它支持x86和AMD64指令集,接受NASM和氣體匯編語法,產出二進制, ELF32 , ELF64 , COFF , Mach - O的( 32和64 ) , RDOFF2 ,的Win32和Win64對象的格式,並生成STABS 調試信息的來源,DWARF 2 ,CodeView 8格式。之所以在FFmpeg中用這個,主要是支持編譯ffmpeg-x264.
|
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz tar xzvf yasm-1.3.0.tar.gz cd yasm-1.3.0 ./configure make make install
2.下載3.1.3 release ffmpeg
wget http://ffmpeg.org/releases/ffmpeg-3.1.3.tar.gz
tar -zxvf ffmpeg-3.1.3.tar.gz
cd ffmpeg-3.1.3
./configure
make
make install
第二步的時間可能會有點長,耐心等待~!安裝完成之后輸入 ffmpeg -version 可以看到版本說明安裝成功
下面直接上代碼,都寫好注釋的,很清楚。
package wordtopdf;import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;public class ConvertVideo {
private final static String PATH = "【需要轉碼的視頻路徑】";</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) { </span><span style="color: #0000ff;">if</span> (!checkfile(PATH)) { <span style="color: #008000;">//</span><span style="color: #008000;">判斷路徑是不是一個文件</span> System.out.println(PATH + " is not file"<span style="color: #000000;">); </span><span style="color: #0000ff;">return</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">if</span> (process()) { <span style="color: #008000;">//</span><span style="color: #008000;">執行轉碼任務</span> System.out.println("ok"<span style="color: #000000;">); } } </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> checkfile(String path) { File file </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> File(path); </span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">file.isFile()) { </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> process() { </span><span style="color: #008000;">//</span><span style="color: #008000;"> 判斷視頻的類型</span> <span style="color: #0000ff;">int</span> type =<span style="color: #000000;"> checkContentType(); </span><span style="color: #0000ff;">boolean</span> status = <span style="color: #0000ff;">false</span><span style="color: #000000;">; </span><span style="color: #008000;">//</span><span style="color: #008000;">如果是ffmpeg可以轉換的類型直接轉碼,否則先用mencoder轉碼成AVI</span> <span style="color: #0000ff;">if</span> (type == 0<span style="color: #000000;">) { System.out.println(</span>"直接將文件轉為flv文件"<span style="color: #000000;">); status </span>= processFLV(PATH);<span style="color: #008000;">//</span><span style="color: #008000;"> 直接將文件轉為flv文件 </span> } <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type == 1<span style="color: #000000;">) { String avifilepath </span>=<span style="color: #000000;"> processAVI(type); </span><span style="color: #0000ff;">if</span> (avifilepath == <span style="color: #0000ff;">null</span><span style="color: #000000;">) </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span>;<span style="color: #008000;">//</span><span style="color: #008000;"> avi文件沒有得到 </span> status = processFLV(avifilepath);<span style="color: #008000;">//</span><span style="color: #008000;"> 將avi轉為flv </span>
}
return status;
}</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> checkContentType() { String type </span>= PATH.substring(PATH.lastIndexOf(".") + 1<span style="color: #000000;">, PATH.length()) .toLowerCase(); </span><span style="color: #008000;">//</span><span style="color: #008000;"> ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) </span> <span style="color: #0000ff;">if</span> (type.equals("avi"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("mpg"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("wmv"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("3gp"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("mov"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("mp4"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("asf"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("asx"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("flv"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 0<span style="color: #000000;">; } </span><span style="color: #008000;">//</span><span style="color: #008000;"> 對ffmpeg無法解析的文件格式(wmv9,rm,rmvb等), </span><span style="color: #008000;">//</span><span style="color: #008000;"> 可以先用別的工具(mencoder)轉換為avi(ffmpeg能解析的)格式. </span> <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("wmv9"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 1<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("rm"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 1<span style="color: #000000;">; } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (type.equals("rmvb"<span style="color: #000000;">)) { </span><span style="color: #0000ff;">return</span> 1<span style="color: #000000;">; } </span><span style="color: #0000ff;">return</span> 9<span style="color: #000000;">; } </span><span style="color: #008000;">//</span><span style="color: #008000;"> 對ffmpeg無法解析的文件格式(wmv9,rm,rmvb等), 可以先用別的工具(mencoder)轉換為avi(ffmpeg能解析的)格式. </span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> String processAVI(<span style="color: #0000ff;">int</span><span style="color: #000000;"> type) { List</span><String> commend = <span style="color: #0000ff;">new</span> ArrayList<String><span style="color: #000000;">(); commend.add(</span>"D:\\ffmpeg\\mencoder"<span style="color: #000000;">); commend.add(PATH); commend.add(</span>"-oac"<span style="color: #000000;">); commend.add(</span>"lavc"<span style="color: #000000;">); commend.add(</span>"-lavcopts"<span style="color: #000000;">); commend.add(</span>"acodec=mp3:abitrate=64"<span style="color: #000000;">); commend.add(</span>"-ovc"<span style="color: #000000;">); commend.add(</span>"xvid"<span style="color: #000000;">); commend.add(</span>"-xvidencopts"<span style="color: #000000;">); commend.add(</span>"bitrate=600"<span style="color: #000000;">); commend.add(</span>"-of"<span style="color: #000000;">); commend.add(</span>"avi"<span style="color: #000000;">); commend.add(</span>"-o"<span style="color: #000000;">); commend.add(</span>"【存放轉碼后視頻的路徑,記住一定是.avi后綴的文件名】"<span style="color: #000000;">); </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { </span><span style="color: #008000;">//</span><span style="color: #008000;">調用線程命令啟動轉碼</span> ProcessBuilder builder = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ProcessBuilder(); builder.command(commend); builder.start(); </span><span style="color: #0000ff;">return</span> "【存放轉碼后視頻的路徑,記住一定是.avi后綴的文件名】"<span style="color: #000000;">; } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e) { e.printStackTrace(); </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">; } } </span><span style="color: #008000;">//</span><span style="color: #008000;"> ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) </span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> processFLV(String oldfilepath) { </span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">checkfile(PATH)) { System.out.println(oldfilepath </span>+ " is not file"<span style="color: #000000;">); </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">; } </span><span style="color: #008000;">//</span><span style="color: #008000;"> 文件命名 </span> Calendar c =<span style="color: #000000;"> Calendar.getInstance(); String savename </span>= String.valueOf(c.getTimeInMillis())+ Math.round(Math.random() * 100000<span style="color: #000000;">); List</span><String> commend = <span style="color: #0000ff;">new</span> ArrayList<String><span style="color: #000000;">(); commend.add(</span>"D:\\ffmpeg\\ffmpeg"<span style="color: #000000;">); commend.add(</span>"-i"<span style="color: #000000;">); commend.add(oldfilepath); commend.add(</span>"-ab"<span style="color: #000000;">); commend.add(</span>"56"<span style="color: #000000;">); commend.add(</span>"-ar"<span style="color: #000000;">); commend.add(</span>"22050"<span style="color: #000000;">); commend.add(</span>"-qscale"<span style="color: #000000;">); commend.add(</span>"8"<span style="color: #000000;">); commend.add(</span>"-r"<span style="color: #000000;">); commend.add(</span>"15"<span style="color: #000000;">); commend.add(</span>"-s"<span style="color: #000000;">); commend.add(</span>"600x500"<span style="color: #000000;">); commend.add(</span>"【存放轉碼后視頻的路徑,記住一定是.flv后綴的文件名】"<span style="color: #000000;">); </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { Runtime runtime </span>=<span style="color: #000000;"> Runtime.getRuntime(); Process proce </span>= <span style="color: #0000ff;">null</span><span style="color: #000000;">; </span><span style="color: #008000;">//</span><span style="color: #008000;">視頻截圖命令,封面圖。 8是代表第8秒的時候截圖</span> String cmd = ""<span style="color: #000000;">; String cut </span>= " c:\\ffmpeg\\ffmpeg.exe -i " +<span style="color: #000000;"> oldfilepath </span>+ " -y -f image2 -ss 8 -t 0.001 -s 600x500 c:\\ffmpeg\\output\\" + "a.jpg"<span style="color: #000000;">; String cutCmd </span>= cmd +<span style="color: #000000;"> cut; proce </span>=<span style="color: #000000;"> runtime.exec(cutCmd); </span><span style="color: #008000;">//</span><span style="color: #008000;">調用線程命令進行轉碼</span> ProcessBuilder builder = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ProcessBuilder(commend); builder.command(commend); builder.start(); </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Exception e) { e.printStackTrace(); </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">; } }
}
注:ffmpeg的功能十分強大,但是命令也非常多,轉換每種格式的命令都不相同!需要轉換其他格式的,請寫對命令。
命令格式:
普通轉碼:
ffmpeg -i [輸入文件名] [參數選項] -f [格式] [輸出文件]
比如:MP4轉avi c:\ffmpeg\ffmpeg -i c:\ffmpeg\input\c.mp4 -f avi c:\ffmpeg\output\a.avi
參數:-an 去掉音頻
-b 1000K 壓縮碼率為1000K
-s 800*500 壓縮尺寸為800*500
-aspect 寬高比,格式 16:9 或 1.778
(當源尺寸是16:9,要壓縮成非16:9的,一方面要設定 -s,另一方面要給出 -aspect)
-ss 開始時間
-t 持續時長