前言
FFMPEG是特別強大的專門用于處理音視頻的開源庫。你既可以使用它的API對音視頻進行處理供屉,也可以使用它提供的工具,如 ffmpeg, ffplay, ffprobe,來編輯你的音視頻文件憔晒。
本文將簡要介紹一下 FFMPEG 庫的基本目錄結構及其功能,然后詳細介紹一下我們在日常工作中蔑舞,如何使用 ffmpeg 提供的工具來處理音視頻文件拒担。
FFMPEG 目錄及作用
- libavcodec: 提供了一系列編碼器的實現。
- libavformat: 實現在流協(xié)議攻询,容器格式及其本IO訪問从撼。
- libavutil: 包括了hash器,解碼器和各利工具函數钧栖。
- libavfilter: 提供了各種音視頻過濾器低零。
- libavdevice: 提供了訪問捕獲設備和回放設備的接口。
- libswresample: 實現了混音和重采樣拯杠。
- libswscale: 實現了色彩轉換和縮放工能掏婶。
FFMPEG基本概念
在講解 FFMPEG 命令之前,我們先要介紹一些音視頻格式的基要概念潭陪。
- 音/視頻流
在音視頻領域雄妥,我們把一路音/視頻稱為一路流最蕾。如我們小時候經常使用VCD看港片,在里邊可以選擇粵語或國語聲音茎芭,其實就是CD視頻文件中存放了兩路音頻流揖膜,用戶可以選擇其中一路進行播放。
- 容器
我們一般把 MP4? FLV梅桩、MOV等文件格式稱之為容器壹粟。也就是在這些常用格式文件中,可以存放多路音視頻文件宿百。以 MP4 為例趁仙,就可以存放一路視頻流,多路音頻流垦页,多路字幕流雀费。
- channel
channel是音頻中的概念,稱之為聲道痊焊。在一路音頻流中盏袄,可以有單聲道,雙聲道或立體聲薄啥。
FFMPEG 命令
我們按使用目的可以將 FFMPEG 命令分成以下幾類:
- 基本信息查詢命令
- 錄制
- 分解/復用
- 處理原始數據
- 濾鏡
- 切割與合并
- 圖/視互轉
-
直播相關
除了 FFMPEG 的基本信息查詢命令外辕羽,其它命令都按下圖所示的流程處理音視頻。
然后將編碼的數據包傳送給解碼器(除非為數據流選擇了流拷貝垄惧,請參閱進一步描述)刁愿。 解碼器產生未壓縮的幀(原始視頻/ PCM音頻/ ...),可以通過濾波進一步處理(見下一節(jié))到逊。 在過濾之后铣口,幀被傳遞到編碼器,編碼器并輸出編碼的數據包觉壶。 最后脑题,這些傳遞給復用器,將編碼的數據包寫入輸出文件铜靶。
默認情況下旭蠕,ffmpeg只包含輸入文件中每種類型(視頻,音頻旷坦,字幕)的一個流,并將其添加到每個輸出文件中佑稠。 它根據以下標準挑選每一個的“最佳”:對于視頻秒梅,它是具有最高分辨率的流,對于音頻舌胶,它是具有最多channel的流捆蜀,對于字幕,是第一個字幕流。 在相同類型的幾個流相等的情況下辆它,選擇具有最低索引的流誊薄。
您可以通過使用-vn / -an / -sn / -dn選項來禁用某些默認設置。 要進行全面的手動控制锰茉,請使用-map選項呢蔫,該選項禁用剛描述的默認設置。
下面我們就來詳細介紹一下這些命令飒筑。
基本信息查詢命令
FFMPEG 可以使用下面的參數進行基本信息查詢片吊。例如,想查詢一下現在使用的 FFMPEG 都支持哪些 filter协屡,就可以用 ffmpeg -filters 來查詢俏脊。詳細參數說明如下:
參數 | 說明 |
---|---|
-version | 顯示版本。 |
-formats | 顯示可用的格式(包括設備)肤晓。 |
-demuxers | 顯示可用的demuxers爷贫。 |
-muxers | 顯示可用的muxers。 |
-devices | 顯示可用的設備补憾。 |
-codecs | 顯示libavcodec已知的所有編解碼器漫萄。 |
-decoders | 顯示可用的解碼器。 |
-encoders | 顯示所有可用的編碼器余蟹。 |
-bsfs | 顯示可用的比特流filter卷胯。 |
-protocols | 顯示可用的協(xié)議。 |
-filters | 顯示可用的libavfilter過濾器威酒。 |
-pix_fmts | 顯示可用的像素格式窑睁。 |
-sample_fmts | 顯示可用的采樣格式。 |
-layouts | 顯示channel名稱和標準channel布局葵孤。 |
-colors | 顯示識別的顏色名稱担钮。 |
接下來介紹的是 FFMPEG 處理音視頻時使用的命令格式與參數。
命令基本格式及參數
下面是 FFMPEG 的基本命令格式:
ffmpeg [global_options] {[input_file_options] -i input_url} ...
{[output_file_options] output_url} ...
ffmpeg 通過 -i 選項讀取輸任意數量的輸入“文件”(可以是常規(guī)文件尤仍,管道箫津,網絡流,抓取設備等宰啦,并寫入任意數量的輸出“文件”苏遥。
原則上,每個輸入/輸出“文件”都可以包含任意數量的不同類型的視頻流(視頻/音頻/字幕/附件/數據)赡模。 流的數量和/或類型是由容器格式來限制田炭。 選擇從哪個輸入進入到哪個輸出將自動完成或使用 -map 選項。
要引用選項中的輸入文件漓柑,您必須使用它們的索引(從0開始)教硫。 例如叨吮。 第一個輸入文件是0,第二個輸入文件是1瞬矩,等等茶鉴。類似地,文件內的流被它們的索引引用景用。 例如涵叮。 2:3是指第三個輸入文件中的第四個流。
上面就是 FFMPEG 處理音視頻的常用命令丛肢,下面是一些常用參數:
主要參數
參數 | 說明 |
---|---|
-f fmt(輸入/輸出) | 強制輸入或輸出文件格式围肥。 格式通常是自動檢測輸入文件,并從輸出文件的文件擴展名中猜測出來蜂怎,所以在大多數情況下這個選項是不需要的穆刻。 |
-i url(輸入) | 輸入文件的網址 |
-y(全局參數) | 覆蓋輸出文件而不詢問。 |
-n(全局參數) | 不要覆蓋輸出文件杠步,如果指定的輸出文件已經存在氢伟,請立即退出。 |
-c [:stream_specifier] codec(輸入/輸出幽歼,每個流) | 選擇一個編碼器(當在輸出文件之前使用)或解碼器(當在輸入文件之前使用時)用于一個或多個流朵锣。codec 是解碼器/編碼器的名稱或 copy(僅輸出)以指示該流不被重新編碼。如:ffmpeg -i INPUT -map 0 -c:v libx264 -c:a copy OUTPUT |
-codec [:stream_specifier]編解碼器(輸入/輸出甸私,每個流) | 同 -c |
-t duration(輸入/輸出) | 當用作輸入選項(在-i之前)時诚些,限制從輸入文件讀取的數據的持續(xù)時間。當用作輸出選項時(在輸出url之前)皇型,在持續(xù)時間到達持續(xù)時間之后停止輸出诬烹。 |
-ss位置(輸入/輸出) | 當用作輸入選項時(在-i之前),在這個輸入文件中尋找位置弃鸦。 請注意绞吁,在大多數格式中,不可能精確搜索唬格,因此ffmpeg將在位置之前尋找最近的搜索點家破。 當轉碼和-accurate_seek被啟用時(默認),搜索點和位置之間的這個額外的分段將被解碼和丟棄购岗。 當進行流式復制或使用-noaccurate_seek時汰聋,它將被保留。當用作輸出選項(在輸出url之前)時喊积,解碼但丟棄輸入烹困,直到時間戳到達位置。 |
-frames [:stream_specifier] framecount(output注服,per-stream) | 停止在幀計數幀之后寫入流韭邓。 |
-filter [:stream_specifier] filtergraph(output,per-stream) | 創(chuàng)建由filtergraph指定的過濾器圖溶弟,并使用它來過濾流女淑。filtergraph是應用于流的filtergraph的描述,并且必須具有相同類型的流的單個輸入和單個輸出辜御。在過濾器圖形中鸭你,輸入與標簽中的標簽相關聯(lián),標簽中的輸出與標簽相關聯(lián)擒权。有關filtergraph語法的更多信息袱巨,請參閱ffmpeg-filters手冊。 |
視頻參數
參數 | 說明 |
---|---|
-vframes num(輸出) | 設置要輸出的視頻幀的數量碳抄。對于-frames:v愉老,這是一個過時的別名,您應該使用它剖效。 |
-r [:stream_specifier] fps(輸入/輸出嫉入,每個流) | 設置幀率(Hz值,分數或縮寫)璧尸。作為輸入選項咒林,忽略存儲在文件中的任何時間戳,根據速率生成新的時間戳爷光。這與用于-framerate選項不同(它在FFmpeg的舊版本中使用的是相同的)垫竞。如果有疑問,請使用-framerate而不是輸入選項-r蛀序。作為輸出選項欢瞪,復制或丟棄輸入幀以實現恒定輸出幀頻fps。 |
-s [:stream_specifier]大泻甙巍(輸入/輸出引有,每個流) | 設置窗口大小。作為輸入選項倦逐,這是video_size專用選項的快捷方式譬正,由某些分幀器識別,其幀尺寸未被存儲在文件中檬姥。作為輸出選項曾我,這會將縮放視頻過濾器插入到相應過濾器圖形的末尾。請直接使用比例過濾器將其插入到開頭或其他地方健民。格式是'wxh'(默認 - 與源相同)抒巢。 |
-aspect [:stream_specifier] 寬高比(輸出,每個流) | 設置方面指定的視頻顯示寬高比秉犹。aspect可以是浮點數字符串蛉谜,也可以是num:den形式的字符串稚晚,其中num和den是寬高比的分子和分母。例如“4:3”型诚,“16:9”客燕,“1.3333”和“1.7777”是有效的參數值。如果與-vcodec副本一起使用狰贯,則會影響存儲在容器級別的寬高比也搓,但不會影響存儲在編碼幀中的寬高比(如果存在)。 |
-vn(輸出) | 禁用視頻錄制涵紊。 |
-vcodec編解碼器(輸出) | 設置視頻編解碼器傍妒。這是-codec:v的別名。 |
-vf filtergraph(輸出) | 創(chuàng)建由filtergraph指定的過濾器圖摸柄,并使用它來過濾流颤练。 |
音頻參數
參數 | 說明 |
---|---|
-aframes(輸出) | 設置要輸出的音頻幀的數量。這是-frames:a的一個過時的別名塘幅。 |
-ar [:stream_specifier] freq(輸入/輸出昔案,每個流) | 設置音頻采樣頻率。對于輸出流电媳,它默認設置為相應輸入流的頻率踏揣。對于輸入流,此選項僅適用于音頻捕獲設備和原始分路器匾乓,并映射到相應的分路器選件捞稿。 |
-ac [:stream_specifier]通道(輸入/輸出,每個流) | 設置音頻通道的數量拼缝。對于輸出流娱局,它默認設置為輸入音頻通道的數量。對于輸入流咧七,此選項僅適用于音頻捕獲設備和原始分路器衰齐,并映射到相應的分路器選件。 |
-an(輸出) 禁用錄音继阻。
-acodec編解碼器(輸入/輸出) |設置音頻編解碼器耻涛。這是-codec的別名:a。
-sample_fmt [:stream_specifier] sample_fmt(輸出瘟檩,每個流) |設置音頻采樣格式抹缕。使用-sample_fmts獲取支持的樣本格式列表。
-af filtergraph(輸出) |創(chuàng)建由filtergraph指定的過濾器圖墨辛,并使用它來過濾流卓研。
了解了這些基本信息后,接下來我們看看 FFMPEG 具體都能干些什么吧。
錄制
首先通過下面的命令查看一下 mac 上都有哪些設備奏赘。
ffmpeg -f avfoundation -list_devices true -i ""
錄屏
ffmpeg -f avfoundation -i 1 -r 30 out.yuv
- -f 指定使用 avfoundation 采集數據寥闪。
- -i 指定從哪兒采集數據,它是一個文件索引號磨淌。在我的MAC上橙垢,1代表桌面(可以通過上面的命令查詢設備索引號)。
- -r 指定幀率伦糯。按ffmpeg官方文檔說-r與-framerate作用相同,但實際測試時發(fā)現不同嗽元。-framerate 用于限制輸入敛纲,而-r用于限制輸出。
注意剂癌,桌面的輸入對幀率沒有要求淤翔,所以不用限制桌面的幀率。其實限制了也沒用佩谷。
錄屏+聲音
ffmpeg -f avfoundation -i 1:0 -r 29.97 -c:v libx264 -crf 0 -c:a libfdk_aac -profile:a aac_he_v2 -b:a 32k out.flv
- -i 1:0 冒號前面的 "1" 代表的屏幕索引號旁壮。冒號后面的"0"代表的聲音索相號。
- -c:v 與參數 -vcodec 一樣谐檀,表示視頻編碼器抡谐。c 是 codec 的縮寫,v 是video的縮寫桐猬。
- -crf 是 x264 的參數麦撵。 0 表式無損壓縮。
- -c:a 與參數 -acodec 一樣溃肪,表示音頻編碼器免胃。
- -profile 是 fdk_aac 的參數。 aac_he_v2 表式使用 AAC_HE v2 壓縮數據惫撰。
- -b:a 指定音頻碼率羔沙。 b 是 bitrate的縮寫, a是 audio的縮與。
錄視頻
ffmpeg -framerate 30 -f avfoundation -i 0 out.mp4
- -framerate 限制視頻的采集幀率厨钻。這個必須要根據提示要求進行設置扼雏,如果不設置就會報錯。
- -f 指定使用 avfoundation 采集數據莉撇。
- -i 指定視頻設備的索引號呢蛤。
視頻+音頻
ffmpeg -framerate 30 -f avfoundation -i 0:0 out.mp4
錄音
ffmpeg -f avfoundation -i :0 out.wav
錄制音頻裸數據
ffmpeg -f avfoundation -i :0 -ar 44100 -f s16le out.pcm
分解與復用
流拷貝是通過將 copy 參數提供給-codec選項來選擇流的模式。它使得ffmpeg省略了指定流的解碼和編碼步驟棍郎,所以它只能進行多路分解和多路復用其障。 這對于更改容器格式或修改容器級元數據很有用。 在這種情況下涂佃,上圖將簡化為:
由于沒有解碼或編碼励翼,速度非瞅诟遥快,沒有質量損失汽抚。 但是抓狭,由于許多因素,在某些情況下可能無法正常工作造烁。 應用過濾器顯然也是不可能的否过,因為過濾器處理未壓縮的數據。
抽取音頻流
fmpeg -i input.mp4 -acodec copy -vn out.aac
- acodec: 指定音頻編碼器惭蟋,copy 指明只拷貝苗桂,不做編解碼。
- vn: v 代表視頻告组,n 代表 no 也就是無視頻的意思煤伟。
抽取視頻流
ffmpeg -i input.mp4 -vcodec copy -an out.h264
- vcodec: 指定視頻編碼器,copy 指明只拷貝木缝,不做編解碼便锨。
- an: a 代表視頻,n 代表 no 也就是無音頻的意思我碟。
轉格式
ffmpeg -i out.mp4 -vcodec copy -acodec copy out.flv
上面的命令表式的是音頻放案、視頻都直接 copy,只是將 mp4 的封裝格式轉成了flv矫俺。
音視頻合并
ffmpeg -i out.h264 -i out.aac -vcodec copy -acodec copy out.mp4
處理原始數據
提取YUV數據
ffmpeg -i input.mp4 -an -c:v rawvideo -pixel_format yuv420p out.yuv
ffplay -s wxh out.yuv
- -c:v rawvideo 指定將視頻轉成原始數據
- -pixel_format yuv420p 指定轉換格式為yuv420p
YUV轉H264
ffmpeg -f rawvideo -pix_fmt yuv420p -s 320x240 -r 30 -i out.yuv -c:v libx264 -f rawvideo out.h264
提取PCM數據
ffmpeg -i out.mp4 -vn -ar 44100 -ac 2 -f s16le out.pcm
ffplay -ar 44100 -ac 2 -f s16le -i out.pcm
PCM轉WAV
ffmpeg -f s16be -ar 8000 -ac 2 -acodec pcm_s16be -i input.raw output.wav
濾鏡
在編碼之前卿叽,ffmpeg可以使用libavfilter庫中的過濾器處理原始音頻和視頻幀。 幾個鏈式過濾器形成一個過濾器圖形恳守。 ffmpeg區(qū)分兩種類型的過濾器圖形:簡單和復雜考婴。
簡單濾鏡
簡單的過濾器圖是那些只有一個輸入和輸出,都是相同的類型催烘。 在上面的圖中沥阱,它們可以通過在解碼和編碼之間插入一個額外的步驟來表示:
簡單的filtergraphs配置了per-stream-filter選項(分別為視頻和音頻使用-vf和-af別名)。 一個簡單的視頻filtergraph可以看起來像這樣的例子:
請注意伊群,某些濾鏡會更改幀屬性考杉,但不會改變幀內容。 例如舰始。 上例中的fps過濾器會改變幀數踱承,但不會觸及幀內容悟民。 另一個例子是setpts過濾器咐熙,它只設置時間戳捐名,否則不改變幀。
復雜濾鏡
復雜的過濾器圖是那些不能簡單描述為應用于一個流的線性處理鏈的過濾器圖。 例如萎坷,當圖形有多個輸入和/或輸出凹联,或者當輸出流類型與輸入不同時,就是這種情況哆档。
復雜的過濾器圖使用-filter_complex選項進行配置蔽挠。 請注意,此選項是全局性的瓜浸,因為復雜的過濾器圖形本質上不能與單個流或文件明確關聯(lián)澳淑。
-lavfi選項等同于-filter_complex。
一個復雜的過濾器圖的一個簡單的例子是覆蓋過濾器插佛,它有兩個視頻輸入和一個視頻輸出偶惠,包含一個視頻疊加在另一個上面。 它的音頻對應是amix濾波器朗涩。
添加水印
ffmpeg -i out.mp4 -vf "movie=logo.png,scale=64:48[watermask];[in][watermask] overlay=30:10 [out]" water.mp4
- -vf中的 movie 指定logo位置。scale 指定 logo 大小绑改。overlay 指定 logo 擺放的位置谢床。
刪除水印
先通過 ffplay 找到要刪除 LOGO 的位置
ffplay -i test.flv -vf delogo=x=806:y=20:w=70:h=80:show=1
使用 delogo 濾鏡刪除 LOGO
視頻縮小一倍
ffmpeg -i out.mp4 -vf scale=iw/2:-1 scale.mp4
- -vf scale 指定使用簡單過濾器 scale,iw/2:-1 中的 iw 指定按整型取視頻的寬度厘线。 -1 表示高度隨寬度一起變化识腿。
視頻裁剪
ffmpeg -i VR.mov -vf crop=in_w-200:in_h-200 -c:v libx264 -c:a copy -video_size 1280x720 vr_new.mp4
crop 格式:crop=out_w:out_h:x:y
- out_w: 輸出的寬度≡熳常可以使用 in_w 表式輸入視頻的寬度渡讼。
- out_h: 輸出的高度《担可以使用 in_h 表式輸入視頻的高度成箫。
- x : X坐標
- y : Y坐標
如果 x和y 設置為 0,說明從左上角開始裁剪。如果不寫是從中心點裁剪旨枯。
倍速播放
ffmpeg -i out.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" speed2.0.mp4
- -filter_complex 復雜濾鏡蹬昌,[0:v]表示第一個(文件索引號是0)文件的視頻作為輸入。setpts=0.5*PTS表示每幀視頻的pts時間戳都乘0.5 攀隔,也就是差少一半皂贩。[v]表示輸出的別名。音頻同理就不詳述了昆汹。
- map 可用于處理復雜輸出明刷,如可以將指定的多路流輸出到一個輸出文件,也可以指定輸出到多個文件满粗。"[v]" 復雜濾鏡輸出的別名作為輸出文件的一路流辈末。上面 map的用法是將復雜濾鏡輸出的視頻和音頻輸出到指定文件中。
對稱視頻
ffmpeg -i out.mp4 -filter_complex "[0:v]pad=w=2*iw[a];[0:v]hflip[b];[a][b]overlay=x=w" duicheng.mp4
- hflip 水平翻轉
如果要修改為垂直翻轉可以用vflip。
畫中畫
ffmpeg -i out.mp4 -i out1.mp4 -filter_complex "[1:v]scale=w=176:h=144:force_original_aspect_ratio=decrease[ckout];[0:v][ckout]overlay=x=W-w-10:y=0[out]" -map "[out]" -movflags faststart new.mp4
錄制畫中畫
ffmpeg -f avfoundation -i "1" -framerate 30 -f avfoundation -i "0:0"
-r 30 -c:v libx264 -preset ultrafast
-c:a libfdk_aac -profile:a aac_he_v2 -ar 44100 -ac 2
-filter_complex "[1:v]scale=w=176:h=144:force_original_aspect_ratio=decrease[a];[0:v][a]overlay=x=W-w-10:y=0[out]"
-map "[out]" -movflags faststart -map 1:a b.mp4
多路視頻拼接
ffmpeg -f avfoundation -i "1" -framerate 30 -f avfoundation -i "0:0" -r 30 -c:v libx264 -preset ultrafast -c:a libfdk_aac -profile:a aac_he_v2 -ar 44100 -ac 2 -filter_complex "[0:v]scale=320:240[a];[a]pad=640:240[b];[b][1:v]overlay=320:0[out]" -map "[out]" -movflags faststart -map 1:a c.mp4
音視頻的拼接與裁剪
裁剪
ffmpeg -i out.mp4 -ss 00:00:00 -t 10 out1.mp4
- -ss 指定裁剪的開始時間本冲,精確到秒
- -t 被裁剪后的時長准脂。
合并
首先創(chuàng)建一個 inputs.txt 文件,文件內容如下:
file '1.flv'
file '2.flv'
file '3.flv'
然后執(zhí)行下面的命令:
ffmpeg -f concat -i inputs.txt -c copy output.flv
hls切片
ffmpeg -i out.mp4 -c:v libx264 -c:a libfdk_aac -strict -2 -f hls out.m3u8
- -strict -2 指明音頻使有AAC檬洞。
- -f hls 轉成 m3u8 格式狸膏。
視頻圖片互轉
視頻轉JPEG
ffmpeg -i test.flv -r 1 -f image2 image-%3d.jpeg
視頻轉gif
ffmpeg -i out.mp4 -ss 00:00:00 -t 10 out.gif
圖片轉視頻
ffmpeg -f image2 -i image-%3d.jpeg images.mp4
直播相關
推流
ffmpeg -re -i out.mp4 -c copy -f flv rtmp://server/live/streamName
拉流保存
ffmpeg -i rtmp://server/live/streamName -c copy dump.flv
轉流
ffmpeg -i rtmp://server/live/originalStream -c:a copy -c:v copy -f flv rtmp://server/live/h264Stream
實時推流
ffmpeg -framerate 15 -f avfoundation -i "1" -s 1280x720
-c:v libx264 -f flv rtmp://localhost:1935/live/room
ffplay
播放YUV 數據
ffplay -pix_fmt nv12 -s 192x144 1.yuv
播放YUV中的 Y平面
ffplay -pix_fmt nv21 -s 640x480 -vf extractplanes='y' 1.yuv