前言

FFMPEG是特彆強大的專門用於處理音視頻的開源庫。你既可以使用它的API對音視頻進行處理,也可以使用它提供的工具,如 ffmpeg, ffplay, ffprobe,來編輯你的音視頻文件。

本文將簡要介紹一下 FFMPEG 庫的基本目錄結構及其功能,然後詳細介紹一下我們在日常工作中,如何使用 ffmpeg 提供的工具來處理音視頻文件。

FFMPEG 目錄及作用

  • libavcodec: 提供了一系列編碼器的實現。
  • libavformat: 實現在流協議,容器格式及其本IO訪問。
  • libavutil: 包括了hash器,解碼器和各利工具函數。
  • libavfilter: 提供了各種音視頻過濾器。
  • libavdevice: 提供了訪問捕獲設備和回放設備的介面。
  • libswresample: 實現了混音和重採樣。
  • libswscale: 實現了色彩轉換和縮放工能。

FFMPEG基本概念

在講解 FFMPEG 命令之前,我們先要介紹一些音視頻格式的基要概念。

  • 音/視頻流

在音視頻領域,我們把一路音/視頻稱為一路流。如我們小時候經常使用VCD看港片,在裡邊可以選擇粵語或國語聲音,其實就是CD視頻文件中存放了兩路音頻流,用戶可以選擇其中一路進行播放。

  • 容器

我們一般把 MP4? FLV、MOV等文件格式稱之為容器。也就是在這些常用格式文件中,可以存放多路音視頻文件。以 MP4 為例,就可以存放一路視頻流,多路音頻流,多路字幕流。

  • channel

channel是音頻中的概念,稱之為聲道。在一路音頻流中,可以有單聲道,雙聲道或立體聲。

FFMPEG 命令

我們按使用目的可以將 FFMPEG 命令分成以下幾類:

  • 基本信息查詢命令
  • 錄製
  • 分解/復用
  • 處理原始數據
  • 濾鏡
  • 切割與合併
  • 圖/視互轉
  • 直播相關

除了 FFMPEG 的基本信息查詢命令外,其它命令都按下圖所示的流程處理音視頻。

_______ ______________
| | | |
| input | demuxer | encoded data | decoder
| file | ---------> | packets | -----+
|_______| |______________| |
v
_________
| |
| decoded |
| frames |
|_________|
________ ______________ |
| | | | |
| output | <-------- | encoded data | <----+
| file | muxer | packets | encoder
|________| |______________|

ffmpeg調用libavformat庫(包含demuxers)來讀取輸入文件並獲取包含編碼數據的數據包。 當有多個輸入文件時,ffmpeg會嘗試通過跟蹤任何活動輸入流上的最低時間戳來使其保持同步。

然後將編碼的數據包傳送給解碼器(除非為數據流選擇了流拷貝,請參閱進一步描述)。 解碼器產生未壓縮的幀(原始視頻/ PCM音頻/ …),可以通過濾波進一步處理(見下一節)。 在過濾之後,幀被傳遞到編碼器,編碼器並輸出編碼的數據包。 最後,這些傳遞給復用器,將編碼的數據包寫入輸出文件。

默認情況下,ffmpeg只包含輸入文件中每種類型(視頻,音頻,字幕)的一個流,並將其添加到每個輸出文件中。 它根據以下標準挑選每一個的「最佳」:對於視頻,它是具有最高解析度的流,對於音頻,它是具有最多channel的流,對於字幕,是第一個字幕流。 在相同類型的幾個流相等的情況下,選擇具有最低索引的流。

您可以通過使用-vn / -an / -sn / -dn選項來禁用某些默認設置。 要進行全面的手動控制,請使用-map選項,該選項禁用剛描述的默認設置。

下面我們就來詳細介紹一下這些命令。

基本信息查詢命令

FFMPEG 可以使用下面的參數進行基本信息查詢。例如,想查詢一下現在使用的 FFMPEG 都支持哪些 filter,就可以用 ffmpeg -filters 來查詢。詳細參數說明如下:

接下來介紹的是 FFMPEG 處理音視頻時使用的命令格式與參數。

命令基本格式及參數

下面是 FFMPEG 的基本命令格式:

ffmpeg [global_options] {[input_file_options] -i input_url} ...
{[output_file_options] output_url} ...

ffmpeg 通過 -i 選項讀取輸任意數量的輸入「文件」(可以是常規文件,管道,網路流,抓取設備等,並寫入任意數量的輸出「文件」。

原則上,每個輸入/輸出「文件」都可以包含任意數量的不同類型的視頻流(視頻/音頻/字幕/附件/數據)。 流的數量和/或類型是由容器格式來限制。 選擇從哪個輸入進入到哪個輸出將自動完成或使用 -map 選項。

要引用選項中的輸入文件,您必須使用它們的索引(從0開始)。 例如。 第一個輸入文件是0,第二個輸入文件是1,等等。類似地,文件內的流被它們的索引引用。 例如。 2:3是指第三個輸入文件中的第四個流。

上面就是 FFMPEG 處理音視頻的常用命令,下面是一些常用參數:

主要參數

視頻參數

音頻參數

了解了這些基本信息後,接下來我們看看 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作用相同,但實際測試時發現不同。-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省略了指定流的解碼和編碼步驟,所以它只能進行多路分解和多路復用。 這對於更改容器格式或修改容器級元數據很有用。 在這種情況下,上圖將簡化為:

_______ ______________ ________
| | | | | |
| input | demuxer | encoded data | muxer | output |
| file | ---------> | packets | -------> | file |
|_______| |______________| |________|

由於沒有解碼或編碼,速度非常快,沒有質量損失。 但是,由於許多因素,在某些情況下可能無法正常工作。 應用過濾器顯然也是不可能的,因為過濾器處理未壓縮的數據。

抽取音頻流

ffmpeg -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區分兩種類型的過濾器圖形:簡單和複雜。

簡單濾鏡

簡單的過濾器圖是那些只有一個輸入和輸出,都是相同的類型。 在上面的圖中,它們可以通過在解碼和編碼之間插入一個額外的步驟來表示:

_________ ______________
| | | |
| decoded | | encoded data |
| frames | _ | packets |
|_________| /||______________|
__________ /
simple _|| | / encoder
filtergraph | filtered |/
| frames |
|__________|

簡單的filtergraphs配置了per-stream-filter選項(分別為視頻和音頻使用-vf和-af別名)。 一個簡單的視頻filtergraph可以看起來像這樣的例子:

_______ _____________ _______ ________
| | | | | | | |
| input | ---> | deinterlace | ---> | scale | ---> | output |
|_______| |_____________| |_______| |________|

請注意,某些濾鏡會更改幀屬性,但不會改變幀內容。 例如。 上例中的fps過濾器會改變幀數,但不會觸及幀內容。 另一個例子是setpts過濾器,它只設置時間戳,否則不改變幀。

複雜濾鏡

複雜的過濾器圖是那些不能簡單描述為應用於一個流的線性處理鏈的過濾器圖。 例如,當圖形有多個輸入和/或輸出,或者當輸出流類型與輸入不同時,就是這種情況。 他們可以用下圖來表示:

_________
| |
| input 0 | __________
|_________| | |
_________ /| output 0 |
| | / |__________|
_________ | complex | /
| | | |/
| input 1 |---->| filter |
|_________| | | __________
/| graph | | |
/ | | | output 1 |
_________ / |_________| |__________|
| | /
| input 2 |/
|_________|

複雜的過濾器圖使用-filter_complex選項進行配置。 請注意,此選項是全局性的,因為複雜的過濾器圖形本質上不能與單個流或文件明確關聯。

-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 test.flv -vf delogo=x=806:y=20:w=70:h=80 output.flv

視頻縮小一倍

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 killer.mp4 -filter_complex "movie=./logo/daka.png,scale=64:48[w];[0:v]curves=vintage[o];[o][w]overlay=30:10[out]" -map "[out]" -map 0:a test1.mp4

一些比較有意思的濾鏡

  • 鏡像crop=iw/2:ih:0:0,split[left][tmp];[tmp]hflip[right];
  • 復古curves=vintage;
  • 光暈vignette=PI/4
  • 變暗colorlevels=rimin=0.058:gimin=0.058:bimin=0.058
  • 增加對比度fftfilt=dc_Y=0:weight_Y=exp(-4 * ((Y+X)/(W+H)))

  • 降噪hqdn3d=luma_spatial=15.0
  • 強對比度curves=strong_contrast
  • 變亮curves=lighter
  • 銳化fftfilt=dc_Y=0:weight_Y=1+squish(1-(Y+X)/100)
  • 低通濾波fftfilt=dc_Y=0:weight_Y=squish((Y+X)/100-1)

  • 高通濾波fftfilt=dc_Y=128:weight_Y=squish(1-(Y+X)/100)
  • 復古curves=vintage
  • 邊緣檢測edgedetect
  • 底片negate
  • 彩色底片curves = 『none』『color_negative』

音視頻的拼接與裁剪

裁剪

ffmpeg -i out.mp4 -ss 00:00:00 -t 10 out1.mp4

  • -ss 指定裁剪的開始時間,精確到秒
  • -t 被裁剪後的時長。

視頻合併

首先創建一個 inputs.txt 文件,文件內容如下:

file 1.flv
file 2.flv
file 3.flv

然後執行下面的命令:

ffmpeg -f concat -i inputs.txt -c copy output.flv

音頻合併

ffmpeg -i text.mp3 -i silenceall.mp3 -filter_complex [0:0] [1:0] concat=n=2:v=0:a=1 [a] -map [a] test.mp3

音頻混音

ffmpeg -i test.mp4 -i test.mp3 -filter_complex "[0:a] [1:a]amerge=inputs=2[aout]" -map "[aout]" -ac 2 mix_amerge.aac

ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex amix=inputs=3:duration=first:dropout_transition=3 OUTPUT

  • inputs: The number of inputs. If unspecified, it defaults to 2.//輸入的數量,如果沒有指明,默認為2.
  • duration: How to determine the end-of-stream.//決定了流的結束
  • longest: The duration of the longest input. (default)//最長輸入的持續時間
  • shortest: The duration of the shortest input.//最短輸入的持續時間
  • first: The duration of the first input.//第一個輸入的持續時間
  • dropout_transition: The transition time, in seconds, for volume renormalization when an input stream ends. The default value is 2 seconds.//輸入流結束時(音頻)容量重整化的轉換時間(以秒為單位)。 默認值為2秒。

註: amerge 與amix 的區別

amerge terminates with the shortest input (always) and amix terminates with the longest input, by default. So the former will always truncate when streams are of different length.

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

我的ffmpeg視頻課地址

課程主頁地址

作者:音視頻_李超鏈接:imooc.com/article/detai來源:慕課網本文原創發佈於慕課網 ,轉載請註明出處,謝謝合作

推薦閱讀:

暴露真實IP真的沒關係嗎?

30行Javascript代碼實現圖片懶載入

【前端乾貨整理】金九銀十,offer拿到手軟的秘密都在這兒!

Github上發布一天Star數破4K的項目了解一下

多線程並發的使用、學習與測試

為什麼程序員應該有一台Mac個人電腦

藏在正則表達式里的陷阱

推薦10個Java方向最熱門的開源項目

Git使用教程,最詳細,最傻瓜,最淺顯,真正手把手教


推薦閱讀:
查看原文 >>
相关文章