java-FFmpeg(一) 實現視頻的轉碼和截圖功能


 

  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>&lt;String&gt; commend = <span style="color: #0000ff;">new</span> ArrayList&lt;String&gt;<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>&lt;String&gt; commend = <span style="color: #0000ff;">new</span> ArrayList&lt;String&gt;<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 持續時長





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM