macOS 下 FFmpeg 視頻轉碼入門及進階使用教程

原文連接: http://www.codedata.cn/hackne...html

現在較爲常見的視頻封裝格式有 mp4 和 mkv 等, 內部的視頻編碼格式從前幾年盛行的 H.264/x264 逐漸開始向新一代的 HEVC/x265(High Efficiency Video Coding 高效視頻編碼)過渡,而常見的音頻編碼格式無非 AC三、DTS 或者 AAC 等。不管是藉助帶有 GUI 的編碼軟件,仍是使用命令行,FFmpeg 是最爲普遍使用的工具,理論上 FFmpeg 支持各個平臺,包括 Windows、macOS、iOS 以及 Android 等,這裏只介紹在 macOS 下的使用。經過簡單的命令,你能夠大體瞭解 FFmpeg 在視頻轉換上的強大之處,視頻編碼部分也集中在 x26四、x265,以及如何壓制 macOS High Sierra 和 iOS 11 能夠正確識別並生成縮略圖的 HEVC 10bit 視頻。文章最後,也會用一個較爲複雜的例子,應用 -filter_complex 進行視頻幀率的插值運算、嵌入 pgs 圖形字幕,以及最後輸出 HEVC 編碼進行說明。web

    • *

安裝

若是有看過我之前文章的朋友,可能會注意到使用 Homebrew 編譯 mpv 的一個重要依賴就是 FFmpeg。不過,若是將其用做視頻轉碼,默認編譯的 FFmpeg 會缺乏一部分組件,所以這裏可能須要從新安裝 FFmpeg。以我我的編譯版本爲例,使用 --HEAD 來配合最新的 mpv,在 Terminal 中輸入以下命令:算法

brew install ffmpeg --HEAD --with-fdk-aac --with-sdl2 --with-freetype --with-libass --with-libbluray --with-libvorbis --with-libvpx --with-opus --with-webp --with-x265

等待安裝結束便可。swift

基礎篇

壓制 x264 編碼視頻文件

ffmpeg -i input.mp4 -c:a libfdk_aac -c:v libx264 -crf 20 -preset slow output.mp4

使用 FFmpeg 編碼的基本規則, -i 以後的文件爲輸入的視頻文件,即 input.mp4,支持的格式衆多,例如 mkv、flv、vob 等等,文件能夠包含目錄,使用 macOS 的文件拖拽功能很方便。output.mp4 即爲輸出文件,文件名可自定義,視頻封裝格式建議對應編碼格式,不該將 mpeg-2 或者 vp8 編碼的視頻也封裝爲 mp4。-c:a 以後表示輸出文件的音頻編碼器,通常 mp4 經常使用的音頻編碼爲 AAC-LC,按照官方 Wiki 指南,建議使用編碼器 libfdk_aac 而不是 aaclibfdk_aac 音質更好,這也是爲何在前文中編譯 FFmpeg 增長 --with-fdk-aac 的緣由。-c:v 以後表明輸出文件的視頻編碼器,使用 libx264 便可壓制 x264 編碼的視頻流。-crf 20 表明視頻編碼的碼率係數,數字越大,壓制的效果越差,建議選擇範圍在 16 - 28,壓制高質量的視頻建議取值 20 如下。-preset slow 表明一組控制壓縮時間和文件大小的參數選擇,通常常選 fastmediumslowapp

以上都是基於 one-pass 壓制,若是須要嚴格控制碼率則須要使用 two-pass,更詳細的介紹,能夠參考 Encode / H.264ide

壓制 HEVC 10bit 編碼視頻文件

其實 FFmpeg 很早就開始支持 HEVC (x265) 的視頻轉碼,只是一直改動較大,而最近的版本也終於支持編碼 macOS High Sierra 下 Quicktime 能夠播放,而且在系統中可以正確預覽並生成縮略圖的視頻文件。編碼命令的改動很小,添加一個 format tag 參數便可,以下:工具

ffmpeg -i input.mp4 \
       -c:v libx265 -preset medium -crf 18 -pix_fmt yuv420p10le \
       -c:a libfdk_aac -b:a 256k \
       -tag:v hvc1 \
       output_10bit.mp4

和壓制 x264 視頻很是相似,主要的不一樣點在於 -c:v 視頻編碼器需換爲 libx265,而且壓制 10bit 須要指定色彩空間,添加 -pix_fmt yuv420p10le。在音頻編碼參數中,若是增長 -b:a,能夠控制音頻文件的碼率,按需使用。最後,很是重要的一點,必須添加參數 tag:v hvc1,這樣輸出的 Video Stream 會被標記爲 hvc1,能夠被 macOS 以及 iOS 11 原生支持播放,不然默認會被標記爲 hev1,不被原生支持,第三方播放器播放倒沒什麼問題。ui

進階篇

修改視頻分辨率

假如原視頻的分辨率爲 1920x1080,爲了下降文件大小,最簡單的辦法是將其轉壓成一個分辨率較低的版本,例如 720p,即 1280x720,那麼咱們可使用 scale 視頻濾鏡來縮放視頻:編碼

ffmpeg -i input.mp4 -vf scale=-2:720 -c:v libx264 -crf 20 -preset slow -c:a copy output.mp4

-vf scale=-2:720 會自動計算對應的橫向分辨率(需爲 2 的倍數,所以爲 -2),源文件音頻編碼保持不變,所以設爲 copy 便可。特殊狀況下,遇到源文件視頻比例錯誤,除了修改分辨率數值,還須要設置 dar 參數,例如:命令行

ffmpeg -i input.avi -vf scale=722x406,setdar=16/9 -c:v libx264 -c:a libfdk_aac -preset slow -crf 20 output.mp4

另外,絕對不建議增大分辨率,由於毫無心義,受限於原視頻的視頻質量,增大分辨率除了體積增大,畫質只會更差。

反交錯(Deinterlace)

偶爾我會遇到一些早期使用 VCD/DVD 時代編碼的視頻,其中一個重要的特色就是隔行掃描,而直接轉碼的結果就是視頻中快速運動的物體都能看到很是明顯的掃描線。解決辦法一樣須要應用 vf 視頻濾鏡中的 yadif 來進行反交錯,以下:

ffmpeg -i input.vob -vf yadif -c:v libx264 -preset slow -crf 20 -c:a libfdk_aac -b:a 256k output.mp4

若是壓制出來的效果不佳(仍是有掃描線),能夠嘗試將 vf 的部分改成 -vf yadif=1:-1:0,mcdeint=2:1:10

旋轉視頻

須要將原視頻進行旋轉,一樣能夠應用視頻濾鏡來達到目的,以下:

ffmpeg -i input.mov -vf "transpose=1" -c:a copy output.mov

其中,

0 = 90 Counter Clockwise and Vertical Flip (default) 
1 = 90 Clockwise 
2 = 90 Counter Clockwise 
3 = 90 Clockwise and Vertical Flip

若是想要 180 度翻轉視頻,則須要改成 -vf "transpose=2,transpose=2"。值得注意的是,旋轉視頻意味着對視頻進行重編碼,輸出質量會稍微受到影響,能夠添加 crf 參數控制視頻輸出質量,音頻部分可使用 copy

一個複雜的「栗子」

最後的這個例子,是我最近遇到的一個視頻,簡要的編碼信息以下:

Input #0, matroska,webm, from 'Input.mkv':
    Duration: 00:23:55.97, start: 0.000000, bitrate: 16372 kb/s
    Stream #0:0: Video: hevc (Main 10), yuv420p10le(tv, bt709), 1920x1080, SAR 1:1 DAR 16:9, 59.94 fps, 59.94 tbr, 1k tbn, 59.94 tbc (default)
    Stream #0:1(jpn): Audio: flac, 48000 Hz, stereo, s32 (24 bit) (default)
    Stream #0:2(jpn): Audio: flac, 48000 Hz, stereo, s32 (24 bit)
    Stream #0:3(chi): Subtitle: hdmv_pgs_subtitle (default)
    Stream #0:4(chi): Subtitle: hdmv_pgs_subtitle

能夠看到,這是一個 HEVC 10bit 編碼,分辨率 1080p,幀率 59.94 fps 的視頻文件,帶有兩條 flac 編碼的音軌,另有兩條是 pgs 格式的圖形字幕。我本身的 Macbook Pro 已經沒法徹底流暢地播放這個視頻了,除了 HEVC 帶來的巨大計算量,高幀率也是一個麻煩,惋惜網上沒有其它好的片源,所以,我只有本身嘗試壓縮。目標:維持分辨率但幀率減半,即降爲 29. 97 fps,音軌只須要第一條,而且重編碼爲 AAC-LC,原片爲日語,所以必須帶有字幕,圖形字幕直接嵌入視頻,最後以 HEVC 10bit 重編碼,少量下降碼率。

改變幀率廣泛會使用 -vf fps=fps=29.97 這類的參數,但本身嘗試後發現一個問題,視頻觀看的感受有跳躍性,不流暢,很像是丟幀的感受。由於將幀率減半,意味着有一半的信息都丟棄了,而普通下降幀率的算法只有簡單的插值運算甚至徹底沒有,形成了視頻不連貫的效果。所以,改變幀率正確的作法是進行運動插值運算(Motion Interpolation),此法既可用在提升幀率上,也能夠用於下降幀率,最終的結果都是提升視頻播放的流暢度。這裏會使用 -filter_complex 代替 vf,聯合應用 minterpolateoverlay 以及 map 來解決幀率、嵌入視頻,和保留一條音軌的問題。壓制命令以下:

ffmpeg -i input.mkv \
-filter_complex "[0:v]minterpolate='fps=29.97:mi_mode=mci:me_mode=bidir:mc_mode=aobmc:vsbmc=1'[bg],[bg][0:s:0]overlay[v]" -map "[v]" -map 0:a:0 \
-c:v libx265 -preset medium -crf 18 -pix_fmt yuv420p10le \
-c:a libfdk_aac -b:a 256k \
-tag:v hvc1 \
output_10bit.mp4

這裏看起來會很複雜,實際上 -filter_complex 的工做模式就像是 pipe,[0:v] 表示輸入文件的視頻流,對應 Stream #0:0。從 minterpolatevsbmc=1 都是插補濾鏡的設置參數,具體的做用能夠查看官方文檔[bg]表明該濾鏡輸出後的視頻流,並傳遞給下一個濾鏡 overlay[0:s:0]表示輸入文件的第一個字幕通,對應 Stream #0:3,因此若是是 [0:s:1] 則對應 Stream #0:4。 overlay 就會將該圖形字幕嵌入到視頻中,而後輸出爲 [v],進行 mapping。視頻取處理後的 [v],音頻取原輸入文件的第一個音頻通道,[0:a:0] 即表明 Stream #0:1。最後和此前壓制視頻的參數就如出一轍了,壓制爲 HEVC 10bit 編碼的視頻文件。

須要注意的是,運動插值運算很是耗時,CPU 佔用確不高,應該是 minterpolate 濾鏡只能調用單核的緣故。在個人電腦上, 此 23 分鐘左右的視頻壓制一次耗時約 20 小時,請謹慎使用。

好了,關於 FFmpeg 視頻轉碼和壓縮的話題就聊到這裏,下次見。Peace!

相關文章
相關標籤/搜索