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這個版本:
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 = "【需要轉碼的視頻路徑】"; public static void main(String[] args) { if (!checkfile(PATH)) { //判斷路徑是不是一個文件 System.out.println(PATH + " is not file"); return; } if (process()) { //執行轉碼任務 System.out.println("ok"); } } private static boolean checkfile(String path) { File file = new File(path); if (!file.isFile()) { return false; } return true; } private static boolean process() { // 判斷視頻的類型 int type = checkContentType(); boolean status = false; //如果是ffmpeg可以轉換的類型直接轉碼,否則先用mencoder轉碼成AVI if (type == 0) { System.out.println("直接將文件轉為flv文件"); status = processFLV(PATH);// 直接將文件轉為flv文件 } else if (type == 1) { String avifilepath = processAVI(type); if (avifilepath == null) return false;// avi文件沒有得到 status = processFLV(avifilepath);// 將avi轉為flv } return status; } private static int checkContentType() { String type = PATH.substring(PATH.lastIndexOf(".") + 1, PATH.length()) .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; } // 對ffmpeg無法解析的文件格式(wmv9,rm,rmvb等), 可以先用別的工具(mencoder)轉換為avi(ffmpeg能解析的)格式. private static String processAVI(int type) { List<String> commend = new ArrayList<String>(); commend.add("D:\\ffmpeg\\mencoder"); commend.add(PATH); commend.add("-oac"); commend.add("lavc"); commend.add("-lavcopts"); commend.add("acodec=mp3:abitrate=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("【存放轉碼后視頻的路徑,記住一定是.avi后綴的文件名】"); try { //調用線程命令啟動轉碼 ProcessBuilder builder = new ProcessBuilder(); builder.command(commend); builder.start(); return "【存放轉碼后視頻的路徑,記住一定是.avi后綴的文件名】"; } catch (Exception e) { e.printStackTrace(); return null; } } // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) private static boolean processFLV(String oldfilepath) { if (!checkfile(PATH)) { System.out.println(oldfilepath + " is not file"); return false; } // 文件命名 Calendar c = Calendar.getInstance(); String savename = String.valueOf(c.getTimeInMillis())+ Math.round(Math.random() * 100000); List<String> commend = new ArrayList<String>(); commend.add("D:\\ffmpeg\\ffmpeg"); commend.add("-i"); commend.add(oldfilepath); commend.add("-ab"); commend.add("56"); commend.add("-ar"); commend.add("22050"); commend.add("-qscale"); commend.add("8"); commend.add("-r"); commend.add("15"); commend.add("-s"); commend.add("600x500"); commend.add("【存放轉碼后視頻的路徑,記住一定是.flv后綴的文件名】"); try { Runtime runtime = Runtime.getRuntime(); Process proce = null; //視頻截圖命令,封面圖。 8是代表第8秒的時候截圖 String cmd = ""; String cut = " c:\\ffmpeg\\ffmpeg.exe -i " + oldfilepath + " -y -f image2 -ss 8 -t 0.001 -s 600x500 c:\\ffmpeg\\output\\" + "a.jpg"; String cutCmd = cmd + cut; proce = runtime.exec(cutCmd); //調用線程命令進行轉碼 ProcessBuilder builder = new ProcessBuilder(commend); builder.command(commend); builder.start(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } }
注: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 持續時長