2017年9月6日 星期三

FFmpeg的使用方式

我想大家應該都知道了,但這邊還是簡單敘述一下FFmpeg:

"這是Open Source的好東西。"
"用來處理視訊、音訊和其他相關的部分。"
"有自己一套的Command line法則,內容博大精深。"

最後加上我自己的心得:"因為很複雜,所以我不是很懂,只摸索過一些基本和專案開發上所需要使用的部分。"

因為之前搜索過相關資訊,發現絕大部分都是直接就講Command line的功用,非常少講FFmpeg從一開始的使用方式;因此像我這麼新手的人,就得要記錄一下從頭到尾的使用方式了。

========================================================================
★取得FFmpeg

首先,上網查一下FFmpeg,就可以找到官網並進入:
這裡官方有註明一句話:"Converting Video and audio has never been so easy.",應該是因為很多人用時總是無法隨心所欲地匯出自己想要的東西,所以才特地標註的吧。

這邊需要注意,要下載的不是標示最大的那個*.tar.bz2檔案,而是Get the packages的Windos平台封包檔才對:

確認你要選擇的版本,這邊預設會是Static的穩定版,然後就可以下載了:

下載完後解壓縮,就可以在bin的資料夾內看到三個應用程式檔,這就是我們所需要的FFmpeg執行檔:

========================================================================
使用FFmpeg

我們可以在任何地方使用FFmpeg的功能,只要把剛剛上面所述的三個檔案和要處理的資源放在同一個資料夾內就好了;Unity的話,如果是Project就將檔案放置在Project的根目錄下,如果是Standalone就將檔案放在和EXE檔同層的地方:
                              

然後創造一個bat批次檔,最簡單的創造方式是可以先創造一個txt檔,檔名可以隨便取,然後把副檔名更改為bat;接著可以用任何文字編輯器來開啟這個bat檔案,在裡面輸入FFmpeg的Cpmmand line後,儲存該bat檔並且執行,就可以得到結果了。

舉例,我想要把mov格式的影片檔,轉檔為mp4格式的檔案;因此我創造了一個名為VideoFormat.bat的檔案,然後在裡面輸入如下的Command line:

然後儲存好內容,關閉文字編輯器,像執行一般exe檔一樣對這個VideoFormat.bat快速滑鼠點擊兩下,就會執行程式並得到轉檔完成的影片檔了:
我將Source.mov轉檔為Result.mp4了,大功告成。

========================================================================
FFmpeg的一些實作功能

這邊講一下,我不會去一個個解釋Command line內的各參數意義和設定方式,也不會在此寫出Unity如何呼叫FFmpeg並使用的方式,原因如下:

1.在網路上已有不少詳盡的FFmpeg教學了,像我這種新手不需要在此搞混大家,有心想學的
   可去找FFmpeg的教學,我也是這樣摸索起來的。
2.Unity呼叫FFmpeg並使用的方式也可在網路上搜尋得到,故不在此記載。
3.FFmpeg最麻煩、且為唯一麻煩的便是Command line的組成方式,一個目的可以有好幾種
   不同的組成方式和參數下法,所以這邊記錄的不會是唯一作法。

那麽下面分享一些我在做專案時實做過的功能,有些是別人告知的,有些是自己參考網路資訊後摸出來的;如果有問題的話請不要問我,因為我應該大多回答不出來吧,所以可依此去網路搜尋相關資訊:

--------------------------------------------------------------------------------------------------------------------------
ffmpeg -i source.avi -c:v libx264 -loglevel 16 -preset slow -c:a aac -b:a copy -crf 15 -vf "scale = 1920:1080" -y -pix_fmt yuv420p result.mp4
pause

將source影片檔轉換格式,匯出result影片檔;檔名、格式和解析度當然可以任意更換。
--------------------------------------------------------------------------------------------------------------------------
ffmpeg -i source.mp4 -loglevel 16 -y -c:v libx264 -preset fast -crf 15 -pix_fmt yuv420p -vf "scale=1280:-1" result.mp4
pause

將source影片檔縮小解析度,匯出result影片檔。
--------------------------------------------------------------------------------------------------------------------------
ffmpeg -f concat -i List.txt -loglevel 16 -y -c copy result.mp4
pause

將記載在List.txt內的影片依順序結合,也可將單一影片重複數次加以結合匯出result影片檔。
List.txt是自創的,檔名可以隨便取,需要幾支影片就輸入幾行,裡面內容如下:

--------------------------------------------------------------------------------------------------------------------------
ffmpeg -r 60 -f image2 -s 640x360 -start_number 001 -i "%%03d.png" -vcodec libx264 -crf 25 -pix_fmt yuv420p -y result.mp4
pause

使用一系列的圖片來生成影片檔,連續圖片檔名部分需對應Command line內所寫的檔名,像在這裡的範例內我使用的是單純只有三位數字的檔名:

========================================================================
FFmpeg使用時的錯誤

使用FFmpeg時很容易發生錯誤,但通常不是FFmpeg本身的錯,而是使用者不了解他所寫的Command line組成有誤、參數設定不正確、或是使用的資源檔不符合規則等;這也是為何FFmpeg會讓人覺得複雜難學的原因,也就是為何官方在主頁會寫那句話的理由。

這邊舉例一下使用時發生的錯誤情況,例如我想要把一系列的圖片轉成影片檔,因此我寫了這個Command line:
ffmpeg -r 60 -f image2 -s 330x125 -start_number 001 -i "GUI%%02d.png" -vcodec libx264 -crf 25 -pix_fmt yuv420p -y result.mp4
pause

接著執行後便發生了這樣的錯誤:

可以看到因為我的圖片本身解析度是330 x 125,所以我在Command line內便設定了同樣的解析度,但是FFmpeg卻沒辦法打包轉成影片檔,因為它須要解析度可被2整除的圖片才行。因此我把所有圖片重新調整了解析度,並且依此重新設定Command line內的解析度:
ffmpeg -r 60 -f image2 -s 330x126 -start_number 001 -i "GUI%%02d.png" -vcodec libx264 -crf 25 -pix_fmt yuv420p -y result.mp4
pause

便順利得到了想要的結果,連續圖片結合成一支影片了:

用這個例子再舉出一個情況,假如我寫這樣的Command line:
ffmpeg -r 60 -f image2 -s 330x126 -start_number 001 -i "GUI%02d.png" -vcodec libx264 -crf 25 -pix_fmt yuv420p -y result.mp4
pause

接著出現這樣的錯誤結果:

可以看得出來FFmpeg依照設定的路徑無法找到相對應的連續圖片,檢查了一下Command line發現原本的路徑"GUI%02d.png"應該寫成"GUI%%02d.png",也就是兩個百分比;因此更改過後再執行,便能正常得到結果了。

使用FFmpeg時,除錯是很重要的能力,不能單是會寫Command line而已,有時候錯誤並非在Command line的組成上。

========================================================================

以上便是我對FFmpeg的一些分享,我以前並不知道FFmpeg這個東西,是換新工作後才接觸到的。使用FFmpeg可以依照需求來調整影片,對製作專案很有幫助,果然工程師就是應該多接觸各方面資訊並提升自己啊。