1. 程式人生 > >FFmpeg命令列轉碼

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

來檢視x264編碼的一些基本資訊和引數情況。

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帶數值代表的位元速率資訊進行轉換