FFmpeg命令列轉碼
本文主要了解FFmpeg進行音視訊編碼轉換。主要學習如下幾個知識點:
- FFmpeg使用libx264進行H,264(AVC)軟編碼,使用libx265進行H.265(HEVC)軟編碼
- 使用FFmpeg在MacOS環境下硬編碼
- 瞭解音訊編碼,MP3,AAC的引數設定編碼
FFmpeg軟編碼H.264和H.265
支援H.264的封裝格式的檔案格式有很多,例如FLV,MP4,HLS,TS等。FFmpeg本身不支援H.264的編碼器,通過第三方庫x264或者OpenH264來支援,但是OpenH264開源較晚,所以多數使用的還是x264,可以通過命令列ffmpeg -h encoder=libx264
H.264編碼例項
通過上面的-h命令檢視x264支援的引數真的很多,我們在要用到優化的時候可以仔細瞭解其引數的含義,下面的幾個例項列出了一些引數的使用,簡單的瞭解引數的含義以及使用方法。每一個引數都可以帶很多不同的配置,在使用的時候檢視文件
編碼器預設引數preset
這個引數主要調節編碼速度和質量的平衡,有ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo這10個選項,從快到慢。
使用H.264轉碼檔案
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -b:v 2000k output.mp4
輸出關鍵速度資訊
多了一個引數-preset ultrafast 中的ultrafast表示使用最快的編碼方式,預設的編碼速度是medium模式的,來檢視這兩種模式生成的輸出資訊差異。
ffmpeg -i input.mp4 -vcodec libx264 -preset medium -b:v 2000k output.mp4
上面的ultrafast速度是41.1倍,使用medium速度是6。24倍但是生成的視訊的畫質速度低的會好一些,
編碼優化引數tune
這個引數配合視訊型別和視覺優化的引數。可選項
- film:電影真人型別
- animation:動畫
- grain:需要保留大量的grain
- stillimage:靜態影象編碼時使用
- psnr:提高psnr做了優化的引數
- ssim:提高ssim做了優化引數
- fastdecode:可以快速解碼的引數
- zerolatency:零延遲,用在需要非常低的延遲的情況,比如電視電話會議編碼。
ffmpeg -i input.mp4 -vcodec libx264 -tune zerolatency -b:v 2000k output.mp4
profile和level設定
profile和level的設定和H.264標準文件ISO-14496-Part10描述的profile和level資訊基本相同。profile有如下選項:
- Baseline
- Extented
- Main
- High
- High10
- High422
- High444
profile設定資訊不同會影響編碼出來的視訊的很多引數不同。例如是否支援I與P分片。level也會影響很多引數,例如最大解碼速度不同。
下面使用baseline profile和high profile編碼一個H.264視訊,分析兩個編碼出來的檔案的區別。有一個知識我們提取了解一下baseline profile編碼出來額視訊不會包含B幀,而high profile包含B幀,下面就看它們B幀的差別
ffmpeg -i input.mp4 -vcodec libx264 -profile:v baseline -level 3.1 -s 352x288 -an -y -t 10 ouput_baseline.ts
ffmpeg -i input.mp4 -vcodec libx264 -profile:v high -level 3.1 -s 352x288 -an -y -t 10 ouput_high.ts
生成了兩個檔案,通過ffprobe來檢視包含B幀的資訊
ffprobe -v quiet -show_frames -select_streams v output_baseline.ts |grep "pict_type=B"|wc -l
輸出0
ffprobe -v quiet -show_frames -select_streams v output_high.ts |grep "pict_type=B"|wc -l
輸出161
驗證了我們的理論baseline profile包含0個B幀,而high profile包含B幀。在進行實時流媒體直播時,使用包含B幀的編碼更可靠些;適當加入B幀可以有效降低位元速率
sc_threshold
FFmpeg可以通過引數-g設定幀數間隔為GOP的長度,但是遇到場景切換的時候,從一個畫面突然變為另一個畫面時,會強行插入一個關鍵幀,這時GOP的長度會重新開始。可以通過引數sc_threshold決定是否在場景切換的時候插入關鍵幀。
執行命令控制編碼時GOP的大小。
ffmpeg -i input.mp4 -c:v libx264 -g 50 -t 60 output.mp4
執行完畢後生成的檔案每50幀被設定為一個GOP間隔。
通過軟體Elecrd StreamEye檢視幀資訊如下:
可以看到紅色框框框起來的兩個I幀間隔很短,因為插入的I幀和前面的畫面完全不同
看到有些GOP的間距很短,這是因為強行插入了GOP導致的,為了使GOP的插入更加均勻,使用sc_threshold設定一下:
ffmpeg -i input.mp4 -c:v libx264 -g 50 -sc_threshold 0 -t 60 output.mp4
再看GOP的幀資訊如下:
拖動下面的滾動條沒有發現和上面一樣相隔很近的兩個I幀了。
x264opts
由於FFmpeg設定x264引數時增加的引數比較多,FFmpeg開放了x264opts,可以通過這個引數設定x264的內部私有引數,如設定IBP幀的順序以及規律。下面列舉在上面生成的GOP檔案資料分析基礎上控制生成的檔案不出現B幀,只要設定x264內部引數bframes=0即可:
ffmpeg -i input.mp4 -c:v libx264 -x264opts "bframes=0" -g 50 -sc_threshold 0 -t 60 output.mp4
通過StreamEye檢視Stream資訊沒有出現B幀
如果希望控制I幀P幀B幀的頻率和規律,可以通過控制GOP中B幀的幀數來實現,P幀的頻率可以通過x264的引數b-adapt進行設定。
例如設定GOP中,每2個P幀之間存放3個B幀:
ffmpeg -i input.mp4 -c:v libx264 -x264opts "bframes=3:b-adapt=0" -g 50 -sc_threshold 0 -t 60 output.mp4
看看分析:
nal-hrd
編碼可以設定VBR,CBR的編碼模式,VBR為可變位元速率,CBR為恆定位元速率。網際網路上VBR居多,但是我們可以使用FFmpeg製作CBR位元速率視訊。
ffmpeg -i input.mp4 -c:v libx264 -x264opts "bframes=10:b-adapt=0" -b:v 1000k -maxrate 1000k -minrate 1000k -bufsize 50k -nal-hrd cbr -g 50 -sc_threshold 0 -t 60 output.ts
命令執行引數介紹
- 設定B幀個數,每兩個P幀之間包含10個B幀
- 設定視訊位元速率為1000kbit/s
- 設定最大位元速率為1000kbit/s
- 設定最小位元速率為1000kbit/s
- 設定編碼的buffer大小為50KB
- 設定H.264的編碼HRD訊號為CBR
- 設定每50幀一個GOP
- 設定場景切換不強行插入關鍵幀
- 設定視訊輸出時間為60s
可以通過工具Bitrate Viewer檢視位元速率波動,我就沒試了,通過Elecard StreamEye檢視流資訊的bitrate type為CBR。
FFmpeg硬編解碼
以前都不知道FFmpeg可以硬編解碼,以為它就只能軟編解碼,它真的強大。FFmpeg可以在Nvidia GPU,Intel QSV,樹莓派,OS X系統下硬編解碼。我使用的是OS X系統,所以下面來實驗一個在該系統的硬編解碼。
OS X系統硬編解碼
直接看一個硬轉碼的例項,先把一個視訊通過h264_vda硬解碼,然後通過h264_videotoolbox硬編碼視訊檔案。
ffmpeg -vcodec h264_vda -i input.mp4 -vcodec h264_videotoolbox -b:v 2000k output.mp4
結果出現錯誤如下:
這個錯誤可清楚的知道是沒有安裝h264_vda工具庫,在前面的文章我們知道如何重新給本機的FFmpeg帶引數安裝一些我們要使用的庫了。但是我找了可以帶的–with引數,不知道解碼器h264_vda屬於哪個庫裡面的。//todo
FFmpeg輸出MP3
編碼MP3使用編碼器libmp3lame這個庫,通過命令ffmpeg -h encoder=libmp3lame
可以檢視它的一些引數資訊。
先來看最簡單的一條命令使用libmp3lame來進行音訊檔案編碼為MP3檔案。
ffmpeg -i input -acodec libmp3lame output.mp3
輸出的位元速率型別引數設定
- VBR:編碼位元速率不斷變化,通過引數-q:a設定
- CBR:位元速率幾乎不變,通過引數-b設定
- ABR:平均位元速率是上面兩個的結合體,使用它的引數編碼速度比VBR高,質量比VBR差一點,比CBR質量好點,通過引數-abr來設定
控制碼率的引數為-q:a後面帶數字
FFmpeg輸出AAC
AAC是一種比MP3的編碼效率更高,編碼音質更好的音訊編碼格式,常見的使用AAC編碼後的檔案儲存格式為m4a。FFmpeg可以使用如下三種編碼器
- aac:FFmpeg自帶的AAC編碼
- libfaac:第三方AAC編碼器
- libfdk_aac:第三方AAC編碼器
FFmpeg使用AAC編碼器
看下面最簡單的例子:
ffmpeg -i input.mp4 -c:a aac -b:a 160k output.aac
同樣可以使用-q:a帶數值代表的位元速率資訊進行轉換