# [FFmpeg] H.264 編碼基本說明 ## 簡介 H.264 / MPEG-4 AVC 是目前最被廣泛被應用的視訊編碼格式,它的壓縮效率比 MPEG-2、MPEG-4、RV40 ...等舊視訊編碼格式還要高許多。它通常使用在 MP4 容器內;副檔名為 .mp4。第二常見使用是在 MKV (Matroska) 檔內,因為它比 MP4 支援更多以文字為基礎的軟字幕 (例如 ass, ssa...)。本文中的範例將使用 MP4 副檔名。 如果要使用編碼輸出 h.264 / AVC 視訊編碼,你需要 libx264 編碼器,此為額外的函式庫,FFmpeg 的 configuration 之中必須有 `--enable-libx264` 則 libx264 才可用。 ## 位元率控制 通常只會使用兩種速率控制: Constant Rate Factor (CRF) 或 2-Pass Bitrate。位元率控制是指決定多少位元將被用於每個畫格的方法。這將決定檔案大小且品質如何分布。而 CRF 的位元率分配效果是最佳的,若無控制輸出大小的需求則使用 CRF 即可。 ### Constant Rate Factor (CRF) 此方法允許編碼器自動分配位元速率來試著達到一定輸出品質。讓每個畫格得到它需要的位元數來保持所需的品質等級。CRF 會得到最佳的位元速率分配結果,缺點是你不能直接指定一個目標位元率或是檔案大小。 設定值範圍為 0–51.0,0 為最高品質,預設值為 23。比較低的數值會得到比較高的品質,合理的範圍 18 - 28。CRF 18 為視覺無損 (或接近),所以它看起來應該與輸入相同 (或接近) 但它技術上不是無損。 CRF 18: ```powershell ffmpeg -i INPUT -c:v libx264 -crf 18 OUTPUT ``` ### 2-Pass Bitrate 此方法會在 1st-Pass 得到一個位元速率分配結果,在 2nd-Pass 時會參考 1st-Pass 時得到的結果再加以分析並編碼來得到一個比較合理的結果。位元速率分配結果會越接近 CRF,缺點是耗費大量時間,所以如果不需要強制控制輸出大小則改用 CRF 即可。 1st-Pass: ```powershell ffmpeg -y -i INPUT -an -pass 1 -c:v libx264 -b:v 5000k -f null - ``` 2nd-Pass: ```powershell ffmpeg -i INPUT -pass 2 -c:v libx264 -b:v 5000k output.mp4 ``` 在每個 Pass 都必須指定相同的位元率值,若無特殊需求 1st-Pass 使用與 2nd-Pass 相同的編碼參數設定即可。由於編碼器兩次的輸入必須是相同的,如果有使用視訊篩選器的話,則 1st-Pass 與 2nd-Pass 的篩選器流程圖必須完全一樣。 1st-Pass: ```powershell ffmpeg -y -i INPUT -an -vf "crop=1920:804:0:138,scale=1280:536" -pass 1 -c:v libx264 -b:v 5000k -f null - ``` 2nd-Pass: ```powershell ffmpeg -i INPUT -vf "crop=1920:804:0:138,scale=1280:536" -pass 2 -c:v libx264 -b:v 5000k output.mp4 ``` 若要加速 1st-Pass 可以在 1st-Pass 使用 `-fastfirstpass 1`,某些參數將使用較低的預設值將使用較低的值取代,但是最終位元率分配結果會比較差。 ## Preset Preset 是一個選項集合,這設定一編碼速度來決定壓縮比。速度越慢則會得到更好的壓縮編碼效率 (畫質-位元率比 或 畫質-檔案大小比)。也就是說,若你設定一個目標位元率或是檔案大小,則越慢的 Preset 將會得到更好的輸出品質。而對於設定一個恆定品質 (CRF) 或是恆定量化值 (QP),你可以透過選擇更慢的 Preset 來簡單的節省位元率 (也就是得到更小的檔案大小)。 一般而言是使用你所能忍受的最慢 Preset。目前 Presets 依速度遞減排序是: `ultrafast`, `superfast`, `veryfast`, `faster`, `fast`, `medium`, `slow`, `slower`, `veryslow`, `placebo`。該預設 Preset 是 `medium`。忽略 `placebo` 因為它會比 `veryslow` 浪費更多時間而且效果差異太小。 ### 覆蓋 Preset 設定 而越慢的 Preset 其 Reference frame (ref) 值也越高,例如 veryslow preset 的 ref 為 16。由於通常不需這麼高的 ref,你可以透過指定一個 Level 來限制 ref,或是手動指定一個合理的 ref 值 (1 ~ 6)。 VerySlow Preset: ```powershell ref=16:bframes=8:b-adapt=2:direct=auto:me=umh:merange=24:subq=10:rc-lookahead=60:analyse=all:trellis=2 ``` 如果要覆蓋 ref 與 bframes 的值為 4 與 5,可以使用 `-refs 4 -bf 5` 或 `-x264opts ref=4:bframes=6`。 覆蓋 ref 值為 4: ```powershell ffmpeg -i input.m2ts -c:v libx264 -crf 18 -refs 4 -preset:v veryslow output.mp4 ``` ## FFmpeg 與 x264 選項 x264 的部分選項被對應到 FFmpeg 選項,例如: `--crf` (`-crf`), `--ref` (`-refs`), `--bframes` (`-bf`), `--preset` (`-preset`)。但並不是全部的 x264 選項都有對應到 FFmpeg 選項,如果你要使用那些選項就必須透過 `-x264opts` 或 `-x264-params`。 語法: ```text key[=value][:key[=value]][:key[=value]]... ``` 注意,`key` 必須使用 x264 的選項名稱。 而某些 x264 選項有對應到 FFmpeg 選項但無法使用 `-x264opts` 或 `-x264-params` 來設定,例如 `--profile` `(-profile`), `--preset` (`-preset`), `--slow-firstpass` (`-fsatfirstpass 0`)。 例如: ```powershell x264 --preset veryslow --crf 18 --ref 4 -- bframes 5 --output output.mp4 input.m2ts ``` 相同編碼參數在 ffmpeg: ```powershell ffmpeg -i input.m2ts -c:v libx264 -preset:v veryslow -x264opts crf=18:ref=4:bframes=5 output.mp4 ``` 某些選項 x264 與 FFmpeg 的預設值是不同的,例如在 x264 預設不使用 `--slow-firstpass`,但在 FFmpeg 中 `-fsatfirstpass 0` (`--slow-firstpass`) 預設是使用,如果要關掉 `--slow-firstpass` 必須設定 `-fsatfirstpass 1` 。 ## 無損 H.264 你可以使用 `-qp 0` 來編碼無損輸出。兩個有用的 Presets 是 `ultrafast` 或 `veryslow`,因為無論是高編碼速度或是高壓縮通常都是最重要的因素。大多數非 FFmpeg 基礎的播放器會無法解碼無損 (但 YouTube 可以),因此,如果有相容性問題的話則不應該使用無損。如果要輸出 YUV 4:4:4 可以使用 `libx264rgb` 編碼器。 無損範例 (高速度壓縮編碼): ```powershell ffmpeg -i INPUT -c:v libx264 -preset ultrafast -qp 0 OUTPUT ``` 無損範例 (高效率壓縮編碼): ```powershell ffmpeg -i INPUT -c:v libx264 -preset veryslow -qp 0 OUTPUT ``` ## 相容性 一般而言要輸出影片相容某播放設備,通常只要影片的 Profile 與 Level 符合或低於播放設備標示規格即可。 對於較舊 iOS 或 Android 設備,你可以嘗試 Baseline Profile, Level 3.0: ```powershell -profile:v baseline -level:v 3.0 ``` Profile 或 Level 越低則會得到更差的壓縮 (畫質-位元率比 或 畫質-檔案大小比),但可以提高相容性與降低對播放設備的性能需求。通常情況下你也許不需要這些設定 (因此,若無必要則避免使用 `-profile`, `-level`)。 Level 由解析度與 Reference frame (ref) 數量來決定,越高的解析度與 ref 則代表 Level 越高。若指定一個 Level 則編碼器會自動限制 ref 數量以符合解析度與 Level 設定,除非你也強制設定 ref 數量。 越低的 Profile 會禁用越多進階功能但提供了更好的相容性: https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles ## 可變位元率 (VBR) 範圍控制 瞬間位元率過高可以能發生播放不流暢的情形,可能由於硬體解碼運性能不足算或是儲存媒介讀取速度不足。你可以使用 `-maxrate` 選項來設定最大流量容許值 (bps, bits/sec) 與 -bufsize 選項來設定流量控制緩衝區大小 (bits) 來解決此問題。或是用於網路直播時限制最大位元率不超過網路上傳速度。 如果一儲存媒介的讀取速度只有 18Mbps (18000Kbps),若要在該儲存媒介上開啟並流暢播放(或錄製)影片,則影片最大位元率不應超過 18Mbps,若音訊位元率為恆定 448kbps,則你可以將視訊最大位元率限制為 17500kbps。 限制影片最大位元率不超過 17.5Mbps: ```powershell -maxrate:v 17500k -bufsize:v 17500k ``` 限制最大位元率可能會得到較差的品質,但可以提高相容性與降低對播放設備的性能需求。通常情況下你也許不需要這些設定 (因此,若無必要則避免使用 `-maxrate`, `-bufsize`)。 ###### tags: `ffmpeg`