ffmpeg基礎使用
文章轉自:(http://www.lxweimin.com/u/50e1d98d51ac)
最近學習音視頻流
參考
ffmpeg常用命令
ffmpeg參數中文詳細解釋
[總結]FFMPEG視音頻編解碼零基礎學習方法
一、安裝
打開https://ffmpeg.zeranoe.com/builds/,該網站中的FFMPEG分為3個版本:Static,Shared,Dev。
前兩個版本可以直接在命令行中使用,他們的區別在于:Static里面只有3個應用程序:ffmpeg.exe,ffplay.exe,ffprobe.exe,每個exe的體積都很大,相關的Dll已經被編譯到exe里面去了。Shared里面除了3個應用程序:ffmpeg.exe,ffplay.exe,ffprobe.exe之外,還有一些Dll,比如說avcodec-54.dll之類的。Shared里面的exe體積很小,他們在運行的時候,到相應的Dll中調用功能。Dev版本是用于開發的,里面包含了庫文件xxx.lib以及頭文件xxx.h,這個版本不包含exe文件。
這里下載了static版本,是個zip壓縮文件,解壓到指定目錄,去配置環境變量,比如e:\ffmpeg20180919\bin,這樣bin下面的ffmpeg.exe就可以在命令行中使用了,可以用ffmpeg -version測試一下:
放一個mp4視頻,然后把聲音提取到output.acc,用命令測試一下:ffmpeg -i mov_bbb.mp4 -acodec copy -vn output.aac
二、常用命令
主要參數:
-i 設定輸入流
-f 設定輸出格式
-ss 開始時間
視頻參數:
-b 設定視頻流量(碼率),默認為200Kbit/s
-r 設定幀速率,默認為25
-s 設定畫面的寬與高
-aspect 設定畫面的比例
-vn 不處理視頻
-vcodec 設定視頻編解碼器,未設定時則使用與輸入流相同的編解碼器
音頻參數:
-ar 設定采樣率
-ac 設定聲音的Channel數
-acodec 設定聲音編解碼器,未設定時則使用與輸入流相同的編解碼器
-an 不處理音頻
1. 視頻格式轉換
(其實格式轉換說法不太準確,但大家都這么叫,準確的說,應該是視頻容器轉換)
比如一個avi文件,想轉為mp4,或者一個mp4想轉為ts。
ffmpeg -i input.avi output.mp4
ffmpeg -i input.mp4 output.ts
插個號外:某天我在知乎上看到一段視頻,想轉給微信好友看,怎么操作呢。這里參考如何全自動下載知乎上的視頻到本地(注意不要濫用),先打開要觀看的視頻頁面,再F12清空,然后開始播放視頻,就能看到類似https://vdn.vzuu.com/SD/49c84c7c-c61a-11e8-8bad-0242ac112a0a.mp4?auth_key=1539832492-0-0-c61c22f39c&expiration=1539832492&disable_local_cache=1
這樣的字符串,然后用ffmpeg -i "https://vdn.vzuu.com/SD/49c8..." output.mp4
即可下載。弄到電腦上,用電腦QQ發送到手機QQ上,在手機QQ上點擊選擇保存到手機上。然后在微信里選照片就能看到這個視頻了(注意視頻文件不要超過20M,另外最開始用的不是電腦QQ,而是百度網盤,發現不行……)。
2. 提取音頻
比如我有一個“曉松奇談”,可是我不想看到他的臉,我只想聽聲音, 地鐵上可以聽,咋辦?
ffmpeg -i 曉松奇談.mp4 -acodec copy -vn output.aac
上面的命令,默認mp4的audio codec是aac,如果不是會出錯,咱可以暴力一點,不管什么音頻,都轉為最常見的aac。
ffmpeg -i 曉松奇談.mp4 -acodec aac -vn output.aac
(-vn 不處理視頻 )
3. 提取視頻
我目測有些IT員工,特別是做嵌入式的,比如機頂盒,想debug一下,沒有音頻的情況下,播放一個視頻幾天幾夜會不會crash,這時候你需要一個純視頻文件,可以這么干。
ffmpeg -i input.mp4 -vcodec copy -an output.mp4
-an 不處理音頻
4. 視頻剪切
經常要測試視頻,但是只需要測幾秒鐘,可是視頻卻有幾個G,咋辦?切啊!
下面的命令,就可以從時間為00:00:15開始,截取5秒鐘的視頻。
ffmpeg -ss 00:00:15 -t 00:00:05 -i input.mp4 -vcodec copy -acodec copy output.mp4
-ss表示開始切割的時間,-t表示要切多少。上面就是從開始,切5秒鐘出來。
注意一個問題,ffmpeg 在切割視頻的時候無法做到時間絕對準確,因為視頻編碼中關鍵幀(I幀)和跟隨它的B幀、P幀是無法分割開的,否則就需要進行重新幀內編碼,會讓視頻體積增大。所以,如果切割的位置剛好在兩個關鍵幀中間,那么 ffmpeg 會向前/向后切割,所以最后切割出的 chunk 長度總是會大于等于應有的長度。
5. 碼率控制
碼率控制對于在線視頻比較重要。因為在線視頻需要考慮其能提供的帶寬。
那么,什么是碼率?很簡單: bitrate = file size / duration
比如一個文件20.8M,時長1分鐘,那么,碼率就是:
biterate = 20.8M bit/60s = 20.8*1024*1024*8 bit/60s= 2831Kbps
一般音頻的碼率只有固定幾種,比如是128Kbps, 那么,video的就是
video biterate = 2831Kbps -128Kbps = 2703Kbps。
說完背景了。好了,來說ffmpeg如何控制碼率。 ffmpg控制碼率有3種選擇,-minrate -b:v -maxrate
-b:v主要是控制平均碼率。 比如一個視頻源的碼率太高了,有10Mbps,文件太大,想把文件弄小一點,但是又不破壞分辨率。
ffmpeg -i input.mp4 -b:v 2000k output.mp4
上面把碼率從原碼率轉成2Mbps碼率,這樣其實也間接讓文件變小了。目測接近一半。不過,ffmpeg官方wiki比較建議,設置b:v時,同時加上 -bufsize
-bufsize 用于設置碼率控制緩沖器的大小,設置的好處是,讓整體的碼率更趨近于希望的值,減少波動。(簡單來說,比如1 2的平均值是1.5, 1.49 1.51 也是1.5, 當然是第二種比較好)ffmpeg -i input.mp4 -b:v 2000k -bufsize 2000k output.mp4
-minrate -maxrate就簡單了,在線視頻有時候,希望碼率波動,不要超過一個閾值,可以設置maxrate。
ffmpeg -i input.mp4 -b:v 2000k -bufsize 2000k -maxrate 2500k output.mp4
6. 視頻編碼格式轉換
比如一個視頻的編碼是MPEG4,想用H264編碼,咋辦?
ffmpeg -i input.mp4 -vcodec h264 output.mp4
相反也一樣
ffmpeg -i input.mp4 -vcodec mpeg4 output.mp4
當然了,如果ffmpeg當時編譯時,添加了外部的x265或者X264,那也可以用外部的編碼器來編碼。(不知道什么是X265,可以Google一下,簡單的說,就是她不包含在ffmpeg的源碼里,是獨立的一個開源代碼,用于編碼HEVC,ffmpeg編碼時可以調用它。當然了,ffmpeg自己也有編碼器)
ffmpeg -i input.mp4 -c:v libx265 output.mp4
ffmpeg -i input.mp4 -c:v libx264 output.mp4
7. 只提取視頻ES數據
這個可能做開發的人會用到,順便提一下吧。
ffmpeg –i input.mp4 –vcodec copy –an –f m4v output.h264
8. 過濾器的使用
這個我在另一篇博客提到了,具體參考ffmpeg filter過濾器 基礎實例及全面解析
8.1 將輸入的1920x1080縮小到960x540輸出:
ffmpeg -i input.mp4 -vf scale=960:540 output.mp4
//ps: 如果540不寫,寫成-1,即scale=960:-1, 那也是可以的,ffmpeg會通知縮放濾鏡在輸出時保持原始的寬高比。
8.2 為視頻添加logo
比如,我有這么一個圖片
想要貼到一個視頻上,那可以用如下命令:
./ffmpeg -i input.mp4 -i iQIYI_logo.png -filter_complex overlay output.mp4
結果如下所示:
9. 抓取視頻的一些幀,存為jpeg圖片
比如,一個視頻,我想提取一些幀,存為圖片,咋辦?
ffmpeg -i input.mp4 -r 1 -q:v 2 -f image2 pic-%03d.jpeg
-r 表示每一秒幾幀
-q:v表示存儲jpeg的圖像質量,一般2是高質量。
如此,ffmpeg會把input.mp4,每隔一秒,存一張圖片下來。假設有60s,那會有60張。60張?什么?這么多?不要不要。。。。。不要咋辦?? 可以設置開始的時間,和你想要截取的時間呀。
ffmpeg -i input.mp4 -ss 00:00:20 -t 10 -r 1 -q:v 2 -f image2 pic-%03d.jpeg
-ss 表示開始時間
-t表示共要多少時間。
如此,ffmpeg會從input.mp4的第20s時間開始,往下10s,即20~30s這10秒鐘之間,每隔1s就抓一幀,總共會抓10幀。
10.輸出YUV420原始數據
對于一下做底層編解碼的人來說,有時候常要提取視頻的YUV原始數據。 怎么坐?很簡答: ffmpeg -i input.mp4 output.yuv
怎么樣,是不是太簡單啦?!!!哈哈(如果你想問yuv的數據,如何播放,我不會告訴你,RawPlayer挺好用的!!)
那如果我只想要抽取某一幀YUV呢? 簡單,你先用上面的方法,先抽出jpeg圖片,然后把jpeg轉為YUV。 比如: 你先抽取10幀圖片。 ffmpeg -i input.mp4 -ss 00:00:20 -t 10 -r 1 -q:v 2 -f image2 pic-%03d.jpeg
結果:
-rw-rw-r-- 1 chenxf chenxf 296254 7月 20 16:08 pic-001.jpeg
-rw-rw-r-- 1 chenxf chenxf 300975 7月 20 16:08 pic-002.jpeg
-rw-rw-r-- 1 chenxf chenxf 310130 7月 20 16:08 pic-003.jpeg
-rw-rw-r-- 1 chenxf chenxf 268694 7月 20 16:08 pic-004.jpeg
-rw-rw-r-- 1 chenxf chenxf 301056 7月 20 16:08 pic-005.jpeg
-rw-rw-r-- 1 chenxf chenxf 293927 7月 20 16:08 pic-006.jpeg
-rw-rw-r-- 1 chenxf chenxf 340295 7月 20 16:08 pic-007.jpeg
-rw-rw-r-- 1 chenxf chenxf 430787 7月 20 16:08 pic-008.jpeg
-rw-rw-r-- 1 chenxf chenxf 404552 7月 20 16:08 pic-009.jpeg
-rw-rw-r-- 1 chenxf chenxf 412691 7月 20 16:08 pic-010.jpeg
然后,你就隨便挑一張,轉為YUV: ffmpeg -i pic-001.jpeg -s 1440x1440 -pix_fmt yuv420p xxx3.yuv
如果-s參數不寫,則輸出大小與輸入一樣。當然了,YUV還有yuv422p啥的,你在-pix_fmt 換成yuv422p就行啦!
11.H264編碼profile & level控制
舉3個例子吧
ffmpeg -i input.mp4 -profile:v baseline -level 3.0 output.mp4
ffmpeg -i input.mp4 -profile:v main -level 4.2 output.mp4
ffmpeg -i input.mp4 -profile:v high -level 5.1 output.mp4
如果ffmpeg編譯時加了external的libx264,那就這么寫:
ffmpeg -i input.mp4 -c:v libx264 -x264-params "profile=high:level=3.0" output.mp4
從壓縮比例來說,baseline< main < high,對于帶寬比較局限的在線視頻,可能會選擇high,但有些時候,做個小視頻,希望所有的設備基本都能解碼(有些低端設備或早期的設備只能解碼baseline),那就犧牲文件大小吧,用baseline。自己取舍吧!
三、小丸工具箱
小丸工具箱是一款用于處理音視頻等多媒體文件的軟件。是一款x264、ffmpeg等命令行程序的圖形界面。它的目標是讓視頻壓制變得簡單、輕松。
主要功能:
- 高質量的H264+AAC視頻壓制
- ASS/SRT字幕內嵌到視頻
- AAC/WAV/FLAC/ALAC音頻轉換
- MP4/MKV/FLV的無損抽取和封裝
參考自小丸FAQ:小丸工具箱是一個x264(taro編譯版,現在是7mod)、MP4Box、ffmpeg、MediaInfo等軟件的GUI。工具箱只是一個調用其他程序的程序,自己沒有壓制功能!只是把平常需要命令行完成的工作圖形化了!其實一切轉換軟件都是這個意思。
四、fluent-ffmpeg
參考自
[FFmpeg探秘]Ep.(1) 什么是FFmpeg?
[FFmpeg探秘]Ep.(2) 從node-fluent-ffmpeg開始
NODEJS基于FFMPEG視頻推流測試
該nodejs包封裝了ffmpeg的命令行調用部分,加強了代碼的可讀性,若熟悉ffmpeg 命令行使用手冊,亦可不使用該包。
npm install --save fluent-ffmpeg
//使用js編碼的用戶,可以忽略下條命令
npm install --save @types/fluent-ffmpeg
五、使用ffmpeg推RTMP直播流
1.安裝nignx環境
弄個WINDOWS版本的Nginx吧,參照Linux&Windows搭建基于nginx的視頻點播服務器,使用了nginx-rtmp-win32做了本地點播測試。具體步驟參照原文,為了節約時間,最好去CSDN下載作者那個DEMO
2.參考手把手教你搭建Nginx-rtmp流媒體服務器+使用ffmpeg推流
在上述下載的demo中,看一下conf/nginx.conf配置文件:
rtmp {
server {
listen 1935;
application live {
live on;
}
application vod {
play video;
}
application hls {
live on;
hls on;
hls_path temp/hls;
hls_fragment 8s;
}
}
}
其中rtmp就是rtmp服務器模塊,端口是1935,application我理解為一個路徑。可以通過訪問rtmp://localhost/live
來訪問live這個資源。live on 表示這是實時的傳輸,這不同于點播,點播就好比我在某視頻網站上想看一個視頻,無論我什么時候去點擊,它會從頭開始播放。而實時傳輸(直播),就是好比看電視,我在19:20去打開電視(打開直播路),視頻不會從頭開始播放,而是從當前(19:20)的視頻數據開始播放。
然后在nginx.exe路徑下命令行運行nginx -s reload重新加載配置。
3.使用ffmpeg推流
參考使用FFmpeg在B站直播的姿勢
ffmpeg -re -i 1.mp4 -vcodec copy -f flv rtmp://localhost/live
或者
ffmpeg -re -i 1.mp4 -vcodec copy -acodec copy
-b:v 800k -b:a 32k -f flv rtmp://localhost/live
-re : 表示使用文件的原始幀率進行讀取,因為ffmpeg讀取視頻幀的速度很快,如果不使用這個參數,ffmpeg可以在很短時間就把video.mp4中的視頻幀全部讀取完并進行推流,這樣就無法體現出視頻播放的效果了。官方文檔中對這個參數的解釋是:
-re (input)
Read input at native frame rate. Mainly used to simulate a grab device, or live input stream (e.g. when reading from a file). Should not be used with actual grab devices or live input streams (where it can cause packet loss). By default ffmpeg attempts to read the input(s) as fast as possible. This option will slow down the reading of the input(s) to the native frame rate of the input(s). It is useful for real-time output (e.g. live streaming).
-vcodec copy : -vcodec表示使用的視頻編解碼器 ,前綴v表示video。后面緊跟的copy 表示復制使用源文件的視頻編解碼器,比如原文件的編解碼器(codec)是h264,則這里就使用h264。
-acodec copy : -acodec表示使用的音頻編解碼器,前綴a表示audio。后面的copy 表示使用源文件的音頻編解碼器。
-b:v 800k : -b:v表示視頻的比特率(bitrate) ,為800k。
-b:a 32k : 表示音頻的比特率為32k。
-f flv : -f表示format ,就是強制輸出格式為flv,這一步其實也叫封裝(mux),封裝要做的事就是把視頻和音頻混合在一起,進行同步。緊跟在后面的rtmp://localhost/live
表示輸出的"文件名",這個文件名可以是一個本地的文件,也可以指定為rtmp流媒體地址。指定為rtmp流媒體地址后,則ffmpeg就可以進行推流。
4.可以使用VLC或ffplay進行播放了