FFmpeg是目前最牛逼的開源跨平台音視訊處理工具。
準備知識
我不是音視訊編解碼出身的,對于這一塊非常的不了解,導緻在學習FFmpeg的時候雲裡霧裡的,是以學習之前最好看些資料對音視訊編解碼有點認識。
- [[總結]FFMPEG視音頻編解碼零基礎學習方法 - CSDN部落格](http://blog.csdn.net/leixiaohua1020/article/details/15811977)
- [[總結]視音頻編解碼技術零基礎學習方法 - CSDN部落格](http://blog.csdn.net/leixiaohua1020/article/details/18893769)
- 視訊格式那麼多,MP4/RMVB/MKV/AVI 等,這些視訊格式與編碼壓縮标準 mpeg4,H.264.H.265 等有什麼關系? - 知乎
- 各種音視訊編解碼學習詳解 - CSDN部落格
安裝
Windows和MacOS使用者可以從Builds - Zeranoe FFmpeg下載下傳編譯好的FFmpeg,解壓加入環境變量PATH即可使用。
同時安裝包我上傳到百度雲中,還有一些測試用的視訊:連結: https://pan.baidu.com/s/1nwLh4hF 密碼: v7yt
播放視訊,FFplay
學習FFmpeg免不了要看效果,而windows的自帶播放器又垃圾得一匹,而且我們會需要看視訊的中繼資料,看他的編碼,用一般的這播放器,能看但是不是很友善。其實FFmpeg自帶了一個播放器FFplay!
FFplay是結合FFmpeg和SDL實作的一個簡易的跨平台播放器。使用起來特别簡單:
ffplay [選項] ['輸入檔案']
而且控制台會列印出視訊的各種資訊,對于我們檢視視訊轉換結果非常有幫助。
FFplay具體文檔:
- ffplay Documentation
- FFplay使用指南
- ffplay的快捷鍵以及選項
相關學習資料推薦,點選下方連結免費報名,先碼住不迷路~】
【免費分享】音視訊學習資料包、大廠面試題、技術視訊和學習路線圖,資料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以點選加群免費領取~
擷取視訊資訊,FFprobe
FFplay指令中會列印出視訊的中繼資料,那如果我們隻是想擷取這些資料而不想播放視訊呢?比如在程式中我們想擷取視訊的時長,要用什麼指令?用FFprobe指令。
ffprobe [選項] ['輸入檔案']
看輸出一定覺得很熟悉,因為和FFplay列印出的資訊一模一樣:
我們還可以使用一些參數:
- -v quiet:不列印日志,這樣預設的輸出就不會顯示了,就不會幹擾我們想要輸出的資訊
- -print_format json:用JSON格式列印出資訊。還支援xml,csv,flat,ini格式
- -show_format:列印出輸入的格式資訊
- -show_streams:列印出每個流的資訊
預設的輸出是比較簡略的,我們可以使用-show_format和-show_streams列印出我們想要的詳細資訊,比如:
ffprobe -v quiet -show_format -print_format json res\BCSPA039_pre.mp4
然後我們程式讀取解析json,擷取duration字段就是視訊的時長。
視訊操作,FFmpeg
ffmpeg指令的文法:
ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...
ffmepg支援多個輸入源(檔案,管道,網絡流,采集裝置),通過-i指定輸入。ffmpeg支援多個輸出,指令行中所有無法被解析為參數的字段都會被作為輸出的url。
參數一般作用于且隻作用于下一個指定的檔案,是以參數的位置是非常重要的。是以全局生效的參數要在最前面。
ffmpeg指令完整的說明參考:
- ffmpeg Documentation
- ffmpeg參數中文詳細解釋
ffmpeg的參數太多了,我們還是通過常用指令來學習會比較好。
ffmpeg例子
分離音視訊
ffmpeg -i input_file -vcodec copy -an output_file_video //隻輸出視訊
ffmpeg -i input_file -acodec copy -vn output_file_audio //分輸出音頻
參數解釋:
- -i:指定輸入檔案
- -vcodec:指定視訊編碼器,這裡指定copy是一個特殊值,表示複制輸入的視訊流到輸出不做更改
- -an:關閉音頻輸出
- -vn:關閉視訊輸出
視訊轉碼
ffmpeg -i input_file output_file
這是最簡單的視訊轉碼指令,ffmpeg會從input的内容推測格式,從output_file的字尾名推測格式,然後進行轉碼輸出。
來看一個我在工作中接觸的比較複雜的視訊轉碼指令:
ffmpeg -i "#src#" -y -s 1920x1080 -vcodec libx264 -c:a libvo_aacenc -b:a 48k -ar 44100 -ac 2 -qscale 4 -f #targetFmt# -movflags faststart -map 0:v:0 -map 0:a? "#destDir#/1080p/#fileNameNoEx#.mp4"
參數解釋:
- -y:覆寫輸出檔案
- -s 1920x1080:設定幀的大小,也就是視訊分辨率,格式為WxH
- -vcodec libx264:設定視訊編碼器,-codec:v libx264是另外一種寫法
- -c:a libvo_aacenc:設定音頻編碼器
- -b:a 48k:設定音頻的比特率
- -ar 44100:設定音頻采樣率為44100
- -ac 2:設定聲道數
- -f #targetFmt#:設定輸出的格式。如果不指定,則會輸入檔案從内容中推測,輸出檔案通過字尾名推測。
- -movflags faststart:把MOV/MP4檔案的索引資訊放到檔案前面以支援邊下邊播
- -map 0:v:0:選擇輸入檔案的第一個視訊流輸出
- -map 0:a?:選擇輸入檔案的音頻流輸出,如果沒有不報錯
- qscale <數值> 以<數值>品質為基礎的VBR,取值0.01-255,越小品質越好
在mp4轉ogv的時候,如果沒有指定-qscale 4,轉出來的視訊畫面比較差,有很多噪點,而且有卡頓。
視訊截圖
指定時間截取一幀作為輸出:
ffmpeg -i input.flv -ss 00:00:14.435 -vframes 1 out.png
參數解釋:
- -ss:如果作用于輸入檔案表示seek輸入檔案到這個位置,但是很多格式不支援seek的,是以隻能做個大概。如果作用于輸出檔案,則輸入會被解碼,但是指定時間之前的資料都會被忽略。這裡是作用于輸出檔案,是以相當于00:00:14.435之前的内容都被忽略了
- -vframes 1:指定輸出多少幀,這裡就輸出一幀。-vframes是-frames:v的别名。
每隔一段時間截一張圖:
# 每一秒輸出一幀圖像為圖檔, 圖檔命名為 out1.png, out2.png, out3.png,依次順序輸出:
ffmpeg -i input.flv -vf fps=1 out%d.png
# 每一分鐘截一次圖, 命名 img001.jpg, img002.jpg, img003.jpg, 依次順序遞增:
ffmpeg -i myvideo.avi -vf fps=1/60 img%03d.jpg
# 每十分鐘輸出一張圖檔:
ffmpeg -i test.flv -vf fps=1/600 thumb%04d.bmp
參數解釋:
- -vf fps=1:設定視訊的filter為fps。後面參數表示一秒幾幀。這裡設定為1,表示一秒一幀。-vf是-filter:v的别名
- out%d.png:輸出多個圖檔,%d占位符表示數字,從1開始。還可以使用%2d指定固定兩位
fps過濾器的文檔:fps Documentation
多說一句
在學習ffmpeg的過程中,閱讀了幾篇非常好的部落格,然後發現作者都是雷霄骅。沒想到他竟然在2016年的時候去世了。唉,又是一個業内悲劇,而且他竟然是在大學裡猝死的,真的是太拼了。努力雖好,也得注意身體啊。
原文 FFmpeg筆記-基本使用 - 掘金