昨天,有個朋友給我出了個難題:他手上有一個視頻,1080P的,49秒,200多兆;要求在確保質量的情況下把文件壓縮到10M以內。
這是什麼概念呢?按照文件大小10M來計算,碼率是:10 x 8 / 49 = 1.6 Mbps。也就比VCD的質量略好一點(注:VCD的標準碼率是1150 Kbps)。談何“確保質量”?mission impossible啊!
咱還是現實一點吧。在不明顯損失畫質的前提下,看看使用FFmpeg能夠幫到多少忙。用iPhone拍了一個1920 x 1080的視頻,33秒,46.3 MB,編碼格式是H.264。考慮到H.264目前尚是主流的視頻格式,爲了播放的兼容性,我們在使用FFmpeg轉碼時同樣選擇H.264。
命令行參數-crf
在優先保證畫面質量(也不太在乎轉碼時間)的情況下,使用-crf參數來控制轉碼是比較適宜的。這個參數的取值範圍爲0~51,其中0爲無損模式,數值越大,畫質越差,生成的文件卻越小。從主觀上講,18~28是一個合理的範圍。18被認爲是視覺無損的(從技術角度上看當然還是有損的),它的輸出視頻質量和輸入視頻相當。
我們的策略是,在保證可接受視頻畫質的前提下,選擇一個最大的crf值——如果輸出視頻質量很好,那就嘗試一個更大的值;如果看起來很糟,那就嘗試一個小一點的值。
讓我們先執行下面這條命令(關於FFmpeg運行環境的配置,請參閱這篇文章):
ffmpeg -i D:\src.mov -c:v libx264 -preset veryslow -crf 18 -c:a copy D:\dest1.mp4
意思是:將D盤的源文件src.mov,以“非常慢”的速度重新編碼成H.264格式,保存爲D:\dest1.mp4。其中,-preset指定的編碼速度越慢,獲得的壓縮效率就越高。而-c:a copy又是什麼意思呢?因爲音頻的碼率一般都比較小,我們就不折騰它了,況且解碼後重新編碼也會損害音質,於是,就將音頻數據從源文件中以原有編碼格式直接拷入目標文件吧。
小提示:想知道-c:v 後面的參數值怎麼填嗎?或者說FFmpeg到底支持哪些音視頻編碼格式?執行ffmpeg –encoders看一下吧。另外,執行ffmpeg -i D:\src.mov -c:v libx264 -preset -tune D:\dummy.mp4可以看到-preset參數的取值範圍,如下:
有個小疑問:既然不在乎等待時間,爲什麼不給-preset指定一個最慢的placebo呢?那是因爲:與 veryslow相比,placebo以極高的編碼時間爲代價,只換取了大概1%的視頻質量提升。這是一種收益遞減準則:slow 與 medium相比提升了5%~10%;slower 與 slow相比提升了5%;veryslow 與 slower相比提升了3%。
另外,針對特定類型的源內容(比如電影、動畫等),還可以使用-tune參數進行特別的優化。但如果你不確定該用哪個選項,還是忽略這個參數吧。
對比效果
執行完一條轉碼命令之後,調整-crf參數值,分別設爲19、20、28、51,重新轉碼輸出爲不同的MP4文件。記錄數據,對比如下:
| 源 | crf = 18 | crf = 19 | crf = 20 | crf = 28 | crf = 51 |
文件大小(MB) | 46.3 | 36.7 | 31.2 | 26.5 | 7.95 | 1.25 |
縮減比率 |
| 21% | 33% | 43% | 83% | 97% |
嘗試播放這些文件。發現crf取值爲18~28的情況下生成的文件,其畫質沒有明顯的差異,而以-crf 51生成的視頻畫質已經慘不忍睹了!在實際應用中,多試幾個crf值,在畫質和壓縮比之間找到一個你能接受的平衡點即可。
參考文章:ffmpeg與x264編碼指南