FFmpeg H.264編碼器指南[譯]

2023-10-10 09:00:23

H264 視訊編碼器指南

本指引著眼於x264編碼器,這裡假設你的FFmpeg 編譯了--enable-libx264支援。如果你需要編譯支援的幫助請看這篇檔案:https://trac.ffmpeg.org/wiki/CompilationGuide,看 HWAccelIntro關於支援H264編碼器在邏輯上的支援;

有兩種適用於大部分場景的位元速率控制模式

Constant Rate Factor (CRF) : 恆定位元速率因子模式

Two-Pass ABR: 兩遍式控制模式

位元速率控制是指每幀需要處理多少bits的資料。位元速率控制會決定視訊檔的大小和質量的優劣。需要更多關於位元速率控制模式的區別,請看這篇文章

CRF-- 恆定位元速率因子模式

推薦在你需要保證視訊的質量最佳,而完全不關心視訊檔的大小的時候使用這種模式;

這種模式執行編碼器當在不關心輸出檔案的大小時,得到一個一定質量的視訊;這種方式可以讓一次處理達到一個最大的壓縮效果。也可以通過調整每幀所謂的量化因子,可以得到所需的位元率去保證要求的視訊質量等級;不過缺點就是你不能指定輸出檔案的大小或者限制視訊不能超過某個大小閾值,也就是說這種方式不推薦用到流式的視訊編碼。

1、設定CRF的值

CRF的取值範圍是0-51,0是畫面質量最高的無失真(只是針對8bit,10bit的話要用 -qp 0),預設值是23,51的話是畫質最差的。值越低,質量越高(可以理解為畫面質量的損失值),主管的認為合理的值範圍是17-28。

17或者18是肉眼區別不出來的無失真或者幾乎區分不出來的無失真;這時看起來跟輸入一樣或者非常接近,但技術來說並不是無失真的。

CRF的取值範圍對畫質的影響是指數級別的,所以,引數值+6的結果差不多隻有原數值位元率/檔案大小的一半。同樣,引數值-6會導致大概位元率/檔案大小是原來的兩倍。

在視訊質量可以接受的範圍選擇一個CRF最大的值。 如果輸出畫質依舊非常好,再選大一點,如果畫質不行,再調小;

注意:0-51 的CRF取值範圍僅適用於8-bit 的x264. 如果你編譯了10bit的x264,CRF的取值範圍是 0-63,(在x264的原始碼上,它是-12到51,只不過是 FFmpeg的 libx264給包裝了一層,做了偏移處理。所以0依舊是無失真的,但只在受支援的組態檔中,High 10 不支援無失真)。
你可以通過FFmpeg編碼處理的控制檯輸出判斷你究竟在用哪種(yuv420p就是8-bit的,yuv420p10le就是10-bit的)。8-bit更常用;

2、選擇一個預設值和Tune;

preset--預設值

譯者:--preset的引數主要調節編碼速度和質量的平衡

預設值是一系列保證確定的編碼速度和壓縮率的選項值的集合。慢的預設值能提供更好的壓縮效率(也就是檔案能壓縮得更小)。例如,如果你設定了確定的檔案大小或者固定的位元率,你能用更慢的預設值得到更好的質量。同樣的,對於固定的質量編碼,你能通過選擇較慢的預設值到簡單儲存位元率;

選在你耐心範圍內最慢的預設值。所有的預設值由慢到快的速度排序如下:

  • ultrafast (很快,但檔案很大 幾乎沒怎麼壓縮)
  • superfast
  • veryfast
  • faster
  • fast
  • medium – 預設預設值
  • slow
  • slower
  • veryslow (很慢,但壓縮率很高 檔案很小)
  • placebo – 忽略這個,這個沒啥用 (參考 FAQ)

你可以通過引數:-preset help看到當前的所有預設值。如你安裝了x264的庫,你也可以用x264 --fullhelp 檢視完整的預設設定;

Tune

譯者:--tune的引數主要配合視訊型別和視覺優化的引數。

你可以用-tune引數去改變你指定的輸入的設定,當前的turn有如下值:

  • film – 適用於高質量的電影,降低去塊效應。use for high quality movie content; lowers deblocking
  • animation – 適用於動畫,使用更高階的去塊處理和更多的參考幀。 good for cartoons; uses higher deblocking and more reference frames
  • grain – 保留舊的、顆粒狀的影片材料中的顆粒結構。 preserves the grain structure in old, grainy film material
  • stillimage – 適用於幻燈片式的內容。good for slideshow-like content
  • fastdecode – 通過關掉某些路徑,實現更快的編碼。allows faster decoding by disabling certain filters
  • zerolatency – 適用於快的編碼和低延遲的流。 good for fast encoding and low-latency streaming
  • psnr – 忽略此項,編碼器開發用的。ignore this as it is only used for codec development
  • ssim – 忽略此項,編碼器開發用的。ignore this as it is only used for codec development

例如,如果你的輸入是一個動畫你可以用animation,或者你你保留顆粒狀在影片裡你可以用grain選項。如果你不確定你要用那個選項或者不知道你的輸入適用何選項你可以忽略 -tune 選項。你可以用 -tune help檢視所用的tune選項列表,或者用 x264 --fullhelp看這些選項設定的含義。

Profile(組態檔)

譯者:限制輸出檔案的profile。這個引數將覆蓋其它所有值,此選項能保證輸出profile相容的視訊流。如果使用了這個選項,將不能進行無失真壓縮(qp 0 or crf 0)。

一般不建議設定;

-profile:v 引數將輸出限定為特定的H264設定。一般來說你不想理用這個選項,建議忽略這個設定h264會自動選擇合適的組態檔;

某些裝置(一般是老掉牙的)只支援更多限制的Constrained BaselineMain profiles。你可以設定這些選項值為 -profile:v baseline or -profile:v main. 新裝置一般都支援更高階的 High組態檔。

另外要用這個引數的原因是,要去匹配其他用 concat demuxer連線的視訊檔。

注意:-profile:v引數不相容無失真的編碼,setting -profile:v high444 也是無效的。

x264支援的組態檔如下:

  • baseline
  • main
  • high
  • high10 (first 10 bit compatible profile)
  • high422 (支援yuv420p, yuv422p, yuv420p10le and yuv422p10le)
  • high444 (supports as above as well as yuv444p and yuv444p10le)

列出預算和tunes

用以下命令列出當前的預算和tunes:

ffmpeg -hide_banner -f lavfi -i nullsrc -c:v libx264 -preset help -f mp4 -

注意: windows環境要改為:

ffmpeg -hide_banner -f lavfi -i nullsrc -c:v libx264 -preset help -f mp4 NUL

CRF 範例

下面命令用更慢的預設值與更好的壓縮,將視訊重新編碼為質量好的視訊。

ffmpeg -i input -c:v libx264 -preset slow -crf 22 -c:a copy output.mkv

注意,這條範例直接用簡單拷貝的方式將輸入的音訊流拷貝到輸出而沒有重新編碼;

如果你要處理一批相似的視訊,用統一的設定,能保證這樣這批視訊的輸出質量都接近;

譯者:這裡的-preset控制的是壓縮率和編碼速度的,-crf控制輸出質量的。

Two-Pass--兩遍式

如果你要輸出指定大小的檔案,並且輸出質量和每幀的質量要求沒那麼高的時候, 那就用這種位元速率控制模式。這是用範例最好的解釋。你的視訊時長600秒並且需要輸出大小是200MB。根據:bitrate = file size / duration:

(200 MB * 8388.608 [轉換MB到KBit(1024*8/1000); 注意不是8192,因為1KBit是1000bit。]) / 600 seconds = ~2796 kBit/s 總位元率

2796 - 128 kBit/s (減去音訊位元率) = 2668 kBit/s 是視訊的位元率

你也可以忽略什麼的計算公式如果你已經知道最終的模板位元率的話。

譯者:通過上面的公式,你就能得到一個最終輸出檔案大小確定的視訊;

兩遍式範例

對應兩遍式,你要用差不多一樣引數跑兩次,引數不同點如下:

  • 在第一遍和第二遍,用 -pass 1-pass 2 選項區別;
  • 在第一遍,輸出是一個空描述,沒有一個顯式的輸出(但會生成一個紀錄檔檔案ffmpeg在第二遍需要用);
  • 在第一遍,你可以用-an引數剝離音訊檔;

注意:第一遍,當用-an引數可能最終得到報段記憶體錯誤或者順壞的檔案。這樣的話,去掉-an引數改為-vsync cfr就行;

例如:

ffmpeg -y -i input -c:v libx264 -b:v 2600k -pass 1 -an -f null /dev/null && \
ffmpeg -i input -c:v libx264 -b:v 2600k -pass 2 -c:a aac -b:a 128k output.mp4

windows下空輸出「/dev/null」要改成「NUL」,‘\’ 要改成'`';

跟CRF一樣,可用可以接受的-preset-tune-profile:v引數以得到不同的目標視訊;

無失真的H.264

如果設定了-profile:v high444引數你可以用 -crf 0 生成無失真的視訊,否則用 -pb 0(High 10 profile 設定不支援無失真視訊, 詳看 https://code.videolan.org/videolan/x264/-/blob/master/x264.c)。 ultrafastveryslow 這兩個預設值是非常常用的,因為更快的編碼速度和更好的壓縮一般來說都是挺重要的考慮因素。

更快的編碼範例:

ffmpeg -i input -c:v libx264 -preset ultrafast -qp 0 output.mkv

更好的壓縮效果範例:

ffmpeg -i input -c:v libx264 -preset veryslow -qp 0 output.mkv

提示:無失真的視訊檔一般來說都非常大,不是基於ffmpeg的播放器可能不能解碼播放。所以,如果相容性和檔案大小問題不可忽略,就別用無失真了。

提示:如果你要的視訊是「視覺上無失真」而不是技術上的無失真的話,用-crf 17或者18就行(你自己試哪個數值可以接受)。這樣不會像真正的無失真模式一樣搞出一個非常大和相容性有問題的視訊檔;

覆蓋預設預設設定

雖然 -preset 已經預設好了可能是最優預設設定給你,但你還是可以用 x264-params 引數去覆蓋預設設定,也可以用libx264 的私有引數(ffmpeg -h encoder=libx264)。當然這些引數不推薦初學者使用。預設值是ffmpeg開發人人給出的最優解你去調這些引數一般都是浪費時間。

範例:

ffmpeg -i input -c:v libx264 -preset slow -crf 22 -x264-params keyint=123:min-keyint=20 -c:a copy output.mkv

注意: 不要用‘x264opts’這個引數, 這個引數後續版本會被刪的。用’x264-params‘就行;

【原文】

https://trac.ffmpeg.org/wiki/Encode/H.264

測試範例命令

crf輸出範例

#修改編碼速度與壓縮率
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast  ultrafast.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow  veryslow.mp4

#加入crf,速度快
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 18  ultrafast_18.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 23  ultrafast_23.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 51  ultrafast_51.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 39  ultrafast_39.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 45  ultrafast_45.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -crf 0  ultrafast_0.mp4

#加入crf,壓縮率高
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow -crf 18  veryslow_18.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow -crf 23  veryslow_23.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow -crf 51  veryslow_51.mp4
ffmpeg -i input.mp4 -vcodec libx264 -preset veryslow -crf 0  veryslow_0.mp4

兩遍式範例

ffmpeg -y -i input.mp4 -c:v libx264 -b:v 2097k -pass 1 -an -f null NUL  && ffmpeg -i input.mp4 -c:v libx264 -b:v 2097k -pass 2 -c:a aac -b:a 128k tow_pass_3MB_2097k.mp4

[參考]

https://ffmpeg.0voice.com/forum.php?mod=viewthread&tid=282