NO IMAGE

FFmpeg

FFmpeg 基本用法

本課要解決的問題

1.FFmpeg的轉碼流程是什麼?

2.常見的視訊格式包含哪些內容嗎?

3.如何把這些內容從視訊檔案中抽取出來?

4.如何從一種格式轉換為另一種格式?

5.如何放大和縮小視訊?

6.如何旋轉,翻轉,填充,裁剪,模糊,銳化視訊?

7.如何給視訊加logo,刪除logo?

8.如何給視訊加文字,動態文字?

9.如何處理圖片?

10.如何錄影,新增動態logo,截圖,馬賽克視訊?

第一部分

基礎

術語

容器(Container)

容器就是一種檔案格式,比如flv,mkv等。包含下面5種流以及檔案頭資訊。

流(Stream)

是一種視訊資料資訊的傳輸方式,5種流:音訊,視訊,字幕,附件,資料。

幀(Frame)

幀代表一幅靜止的影象,分為I幀,P幀,B幀。

編解碼器(Codec)

是對視訊進行壓縮或者解壓縮,CODEC =COde (編碼) DECode(解碼)

複用/解複用(mux/demux)

把不同的流按照某種容器的規則放入容器,這種行為叫做複用(mux)

把不同的流從某種容器中解析出來,這種行為叫做解複用(demux)

 

 

簡介

 

FFmpeg的名稱來自MPEG視訊編碼標準,前面的“FF”代表“Fast Forward”,FFmpeg是一套可以用來記錄、轉換數字音訊、視訊,並能將其轉化為流的開源計算機程式。可以輕易地實現多種視訊格式之間的相互轉換。

 

FFmpeg的使用者有Google,Facebook,Youtube,優酷,愛奇藝,土豆等。

組成

1、libavformat:用於各種音視訊封裝格式的生成和解析,包括獲取解碼所需資訊以生成解碼上下文結構和讀取音視訊幀等功能,包含demuxers和muxer庫;

2、libavcodec:用於各種型別聲音/影象編解碼;

3、libavutil:包含一些公共的工具函式;

4、libswscale:用於視訊場景比例縮放、色彩對映轉換;

5、libpostproc:用於後期效果處理;

6、ffmpeg:是一個命令列工具,用來對視訊檔案轉換格式,也支援對電視卡實時編碼;

7、ffsever:是一個HTTP多媒體實時廣播流伺服器,支援時光平移;

8、ffplay:是一個簡單的播放器,使用ffmpeg 庫解析和解碼,通過SDL顯示;

 

FFmpeg處理流程

過濾器(Filter)

在多媒體處理中,filter的意思是被編碼到輸出檔案之前用來修改輸入檔案內容的一個軟體工具。如:視訊翻轉,旋轉,縮放等。

語法:[input_link_label1][input_link_label2]… filter_name=parameters [output_link_label1][output_link_label2]…

過濾器圖link label :是標記過濾器的輸入或輸出的名稱

1.視訊過濾器 -vf

如testsrc視訊按順時針方向旋轉90度

ffplay -f lavfi -i testsrc -vf transpose=1

如testsrc視訊水平翻轉(左右翻轉)

ffplay -f lavfi -i testsrc -vf hflip

2.音訊過濾器 -af

實現慢速播放,聲音速度是原始速度的50%

ffplay p629100.mp3 -af atempo=0.5

 

如何實現順時針旋轉90度並水平翻轉? 

過濾器鏈(Filterchain)

基本語法

Filterchain = 逗號分隔的一組filter

語法:“filter1,filter2,filter3,…filterN-2,filterN-1,filterN”

順時針旋轉90度並水平翻轉

ffplay -f lavfi -i testsrc -vf transpose=1,hflip

 

 

 

 

如何實現水平翻轉視訊和源視訊進行比較? 看過濾器鏈是如何實現的。

 

 

 

 

 

 

過濾器鏈(Filterchain)

第一步: 源視訊寬度擴大兩倍。

ffmpeg -i jidu.mp4 -t 10 -vf pad=2*iw output.mp4

第二步:源視訊水平翻轉

ffmpeg -i jidu.mp4 -t 10 -vf hflip output2.mp4

第三步:水平翻轉視訊覆蓋output.mp4

ffmpeg -i output.mp4 -i output2.mp4 -filter_complex overlay=w compare.mp4

是不是很複雜?

用帶有連結標記的過濾器圖(Filtergraph)只需一條命令。

過濾器圖(Filtergraph)

基本語法

Filtergraph = 分號分隔的一組filterchain

“filterchain1;filterchain2;…filterchainN-1;filterchainN”

 

 

Filtergraph的分類

1、簡單(simple) 一對一

2、複雜(complex)多對一, 多對多

過濾器圖(Filtergraph)

簡單過濾器圖處理流程:

 

 

複雜過濾器圖處理流程:

 

 

 

從圖中可以發現複雜過濾器圖比簡單過濾器圖少2個步驟,效率比簡單高,ffmpeg建議儘量使用複雜過濾器圖。

回答上面提的問題,實現水平翻轉視訊和源視訊進行比較

 

過濾器圖(Filtergraph)

用ffplay直接觀看結果:

ffplay -f lavfi -i testsrc -vf split[a][b];[a]pad=2*iw[1];[b]hflip[2];[1][2]overlay=w

 

 

 

 

F1: split過濾器建立兩個輸入檔案的拷貝並標記為[a],[b]

F2: [a]作為pad過濾器的輸入,pad過濾器產生2倍寬度並輸出到[1].

F3: [b]作為hflip過濾器的輸入,vflip過濾器水平翻轉視訊並輸出到[2].

F4: 用overlay過濾器把 [2]覆蓋到[1]的旁邊.

 

 

選擇媒體流

一些多媒體容器比如AVI,mkv,mp4等,可以包含不同種類的多個流,如何從容器中抽取各種流呢?

語法:

-map file_number:stream_type[:stream_number]

 

這有一些特別流符號的說明:

1、-map 0 選擇第一個檔案的所有流

2、-map i:v 從檔案序號i(index)中獲取所有視訊流, -map i:a 獲取所有音訊流,-map i:s 獲取所有字幕流等等。

3、特殊引數-an,-vn,-sn分別排除所有的音訊,視訊,字幕流。

 

注意:檔案序號和流序號從0開始計數。

選擇媒體流

第二部分

檢視幫助

幫助

FFmpeg工具有一個巨大的控制檯幫助。下表描述了可用的一些選項,斜體字表示要被替換的項,ffplay和ffprobe也有一些類似的選項。

 

幫助

可用的bit流 :ffmpeg –bsfs

可用的編解碼器:ffmpeg –codecs

可用的解碼器:ffmpeg –decoders

可用的編碼器:ffmpeg –encoders

可用的過濾器:ffmpeg –filters

可用的視訊格式:ffmpeg –formats

可用的聲道佈局:ffmpeg –layouts

可用的license:ffmpeg –L

可用的畫素格式:ffmpeg –pix_fmts

可用的協議:ffmpeg -protocals

 

第三部分

位元速率、幀率和檔案大小

概述

        位元速率和幀率是視訊檔案的最重要的基本特徵,對於他們的特有設定會決定視訊質量。如果我們知道位元速率和時長那麼可以很容易計算出輸出檔案的大小。

 

幀率:幀率也叫幀頻率,幀率是視訊檔案中每一秒的幀數,肉眼想看到連續移動影象至少需要15幀。

位元速率:位元率(也叫位元速率,資料率)是一個確定整體視訊/音訊質量的引數,秒為單位處理的位元組數,位元速率和視訊質量成正比,在視訊檔案中中位元率用bps來表達。

幀率

1、用 -r 引數設定幀率

ffmpeg –i input –r fps output

2、用fps filter設定幀率

ffmpeg -i clip.mpg -vf fps=fps=25 clip.webm

幀率的預定義值:

 

 

 

 

 

例如設定位元速率為29.97fps,下面三種方式具有相同的結果:

ffmpeg -i input.avi -r 29.97 output.mpg

ffmpeg -i input.avi -r 30000/1001 output.mpg

ffmpeg -i input.avi -r netsc output.mpg

 

位元速率、檔案大小

設定位元速率 –b 引數

-b 

ffmpeg -i film.avi -b 1.5M film.mp4

 

音訊:-b:a     視訊: – b:v

設定視訊位元速率為1500kbps

ffmpeg -i input.avi -b:v 1500k output.mp4

 

控制輸出檔案大小

-fs (file size首字母縮寫) 

ffmpeg -i input.avi -fs 1024K output.mp4

計算輸出檔案大小

(視訊位元速率 音訊位元速率) * 時長 /8 = 檔案大小K

 

 

第四部分

調整視訊解析度

調整視訊解析度

1、用-s引數設定視訊解析度,引數值wxh,w寬度單位是畫素,h高度單位是畫素

ffmpeg -i input_file -s 320×240 output_file

 

2、預定義的視訊尺寸

下面兩條命令有相同效果

ffmpeg -i input.avi -s 640×480 output.avi

ffmpeg -i input.avi -s vga output.avi

 

下表列出了所有的預定義尺寸

 

 

 

 

Scale filter調整解析度

Scale filter的優點是可以使用一些額外的引數

語法:

Scale=width:height[:interl={1|-1}]

下表列出了常用的額外引數

舉例

下面兩條命令有相同效果

ffmpeg -i input.mpg -s 320×240 output.mp4 

ffmpeg -i input.mpg -vf scale=320:240 output.mp4

 

對輸入視訊成比例縮放

改變為源視訊一半大小

ffmpeg -i input.mpg -vf scale=iw/2:ih/2 output.mp4

改變為原視訊的90%大小:

ffmpeg -i input.mpg -vf scale=iw*0.9:ih*0.9 output.mp4

 

舉例

在未知視訊的解析度時,保證調整的解析度與源視訊有相同的橫縱比。

寬度固定400,高度成比例:

ffmpeg -i input.avi -vf scale=400:400/a

ffmpeg -i input.avi -vf scale=400:-1

 

相反地,高度固定300,寬度成比例:

ffmpeg -i input.avi -vf scale=-1:300

ffmpeg -i input.avi -vf scale=300*a:300

 

第五部分

裁剪/填充視訊

裁剪視訊crop filter

從輸入檔案中選取你想要的矩形區域到輸出檔案中,常見用來去視訊黑邊。

語法:crop:ow[:oh[:x[:y:[:keep_aspect]]]]

 

舉例

裁剪輸入視訊的左三分之一,中間三分之一,右三分之一:

ffmpeg -i input -vf crop=iw/3:ih :0:0 output 

ffmpeg -i input -vf crop=iw/3:ih :iw/3:0 output 

ffmpeg -i input -vf crop=iw/3:ih :iw/3*2:0 output

裁剪幀的中心

當我們想裁剪區域在幀的中間時,裁剪filter可以跳過輸入x和y值,他們的預設值是

Xdefault  = ( input width – output width)/2 

Ydefault  = ( input height – output height)/2

ffmpeg -i input_file -v crop=w:h output_file

裁剪中間一半區域:

ffmpeg -i input.avi -vf crop=iw/2:ih/2 output.avi

 

舉例

比較裁剪後的視訊和源視訊比較

ffplay -i jidu.mp4 -vf split[a][b];[a]drawbox=x=(iw-300)/2:(ih-300)/2:w=300:h=300:c=yellow[A];[A]pad=2*iw[C];[b]crop=300:300:(iw-300)/2:(ih-300)/2[B];[C][B]overlay=w*2.4:40

 

 

自動檢測裁剪區域

cropdetect  filter 自動檢測黑邊區域

ffplay jidu.mp4 -vf cropdetect

 

 

 

 

然後用檢測到的值來裁剪視訊

ffplay jidu.mp4 –vf crop=672:272:0:54

 

 

填充視訊(pad)

在視訊幀上增加一快額外額區域,經常用在播放的時候顯示不同的橫縱比

語法:pad=width[:height:[:x[:y:[:color]]]]

 

 

舉例

建立一個30個畫素的粉色寬度來包圍一個SVGA尺寸的圖片:

ffmpeg -i photo.jpg -vf pad=860:660:30:30:pink framed_photo.jpg

?

 

 

 

同理可以製作testsrc視訊用30個畫素粉色包圍視訊

ffplay  -f lavfi -i testsrc -vf pad=iw 60:ih 60:30:30:pink

 

4:3到16:9

一些裝置只能播放16:9的橫縱比,4:3的橫縱比必須在水平方向的兩邊填充成16:9,

 

高度被保持,寬度等於高度乘以16/9,x(輸入檔案水平位移)值由表示式(output_width – input_width)/2來計算。

 

4:3到16:9的通用命令是:

ffmpeg -i input -vf pad=ih*16/9:ih :(ow-iw)/2:0:color output

 

舉例

ffplay  -f lavfi -i testsrc -vf pad=ih*16/9:ih:(ow-iw)/2:0:pink

 

16:9到4:3

為了用4:3的橫縱比來顯示16:9的橫縱比,填充輸入檔案的垂直兩邊,寬度保持不變,高度是寬度的3/4,y值(輸入檔案的垂直偏移量)是由一個表示式(output_height-input_height)/2計算出來的。

 

16:9到4:3的通用命令:

ffmpeg -i input -vf pad=iw :iw*3/4:0:(oh-ih)/2:color output

 

舉例

ffplay  -f lavfi -i testsrc=size=320×180 -vf pad=iw:iw*3/4:0:(oh-ih)/2:pink

 

 

第六部分

翻轉和旋轉

翻轉

水平翻轉語法: -vf hflip

ffplay -f lavfi -i testsrc -vf hflip

 

 

 

 

垂直翻轉語法:-vf vflip

ffplay -f lavfi -i testsrc -vf vflip

 

旋轉

語法:transpose={0,1,2,3}

0:逆時針旋轉90°然後垂直翻轉

1:順時針旋轉90°

2:逆時針旋轉90°

3:順時針旋轉90°然後水平翻轉

第七部分

模糊,銳化

模糊

語法:boxblur=luma_r:luma_p[:chroma_r:chram_p[:alpha_r:alpha_p]]

ffplay -f lavfi -i testsrc -vf  boxblur=1:10:4:10

注意:luma_r和alpha_r半徑取值範圍是0~min(w,h)/2, chroma_r半徑的取值範圍是0~min(cw/ch)/2

銳化

語法:-vf unsharp=l_msize_x:l_msize_y:l_amount:c_msize_x:c_msize_y:c_amount

所有的引數是可選的,預設值是5:5:1.0:5:5:0.0

l_msize_x:水平亮度矩陣,取值範圍3-13,預設值為5

l_msize_y:垂直亮度矩陣,取值範圍3-13,預設值為5

l_amount:亮度強度,取值範圍-2.0-5.0,負數為模糊效果,預設值1.0

c_msize_x:水平色彩矩陣,取值範圍3-13,預設值5

c_msize_y:垂直色彩矩陣,取值範圍3-13,預設值5

c_amount:色彩強度,取值範圍-2.0-5.0,負數為模糊效果,預設值0.0

舉例

使用預設值,亮度矩陣為5×5和亮度值為1.0

ffmpeg -i input -vf unsharp output.mp4

高斯模糊效果(比較強的模糊):

ffplay -f lavfi -i testsrc -vf unsharp=13:13:-2

 

第八部分

覆蓋(畫中畫)

覆蓋

語法:overlay[=x[:y]

所有的引數都是可選,預設值都是0

 

舉例

Logo在左上角

ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay pair1.mp4

 

舉例

右上角:

ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay=W-w  pair2.mp4

左下角:

ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay=0:H-h  pair2.mp4

右下角:

ffmpeg -i pair.mp4 -i logo.png -filter_complex overlay=W-w:H-h  pair2.mp4

 

刪除logo

語法:-vf delogo=x:y:w:h[:t[:show]]

x:y 離左上角的座標

w:h  logo的寬和高

t: 矩形邊緣的厚度預設值4

show:若設定為1有一個綠色的矩形,預設值0.

ffplay -i jidu.mp4 -vf delogo=50:51:60:60:100:0

第九部分

新增文字

新增文字

語法:

drawtext=fontfile=font_f:text=text1[:p3=v3[:p4=v4[…]]]

常用的引數值

x:離左上角的橫座標

y: 離左上角的縱座標

fontcolor:字型顏色

fontsize:字型大小

text:文字內容

textfile:文字檔案

t:時間戳,單位秒

n:幀數開始位置為0

draw/enable:控制檔案顯示,若值為0不顯示,1顯示,可以使用函式

簡單用法

1、在左上角新增Welcome文字

ffplay -f lavfi -i color=c=white -vf drawtext=fontfile=arial.ttf:text=Welcom

2、在中央新增Good day

ffplay -f lavfi -i color=c=white -vf drawtext=”fontfile=arial.ttf:text=’Goodday’:x=(w-tw)/2:y=(h-th)/2″

3、設定字型顏色和大小

ffplay -f lavfi -i color=c=white -vf drawtext=”fontfile=arial.ttf:text=’Happy Holidays’:x=(w-tw)/2:y=(h-th)/2:fontcolor=green:fontsize=30″

 

動態文字

用 t (時間秒)變數實現動態文字

1、頂部水平滾動

ffplay -i jidu.mp4 -vf drawtext=”fontfile=arial.ttf:text=’Dynamic RTL text’:x=w-t*50:fontcolor=darkorange:fontsize=30″

2、底部水平滾動

ffplay -i jidu.mp4 -vf drawtext=”fontfile=arial.ttf:textfile=textfile.txt:x=w-t*50:y=h-th:fontcolor=darkorange:fontsize=30″

3、垂直從下往上滾動

ffplay jidu.mp4 -vf drawtext=”textfile=textfile:fontfile=arial.ttf:x=(w-tw)/2:y=h-t*100:fontcolor=white:fontsize=30“

想實現右上角顯示當前時間?

 

 

動態文字

在右上角顯示當前時間 localtime

ffplay jidu.mp4 -vf drawtext=”fontfile=arial.ttf:x=w-tw:fontcolor=white:fontsize=30:text=’%{localtime\:%H\\\:%M\\\:%S}’“

 

每隔3秒顯示一次當前時間

ffplay jidu.mp4 -vf drawtext=”fontfile=arial.ttf:x=w-tw:fontcolor=white:fontsize=30:text=’%{localtime\:%H\\\:%M\\\:%S}’:enable=lt(mod(t\,3)\,1)”

 

第十部分

圖片處理

圖片支援

FFmpeg支援絕大多數圖片處理, 除LJPEG(無損JPEG)之外,其他都能被解碼,除了EXR,PIC,PTX之外,所有的都能被編碼。

擷取一張圖片使用 –ss(seek from start)引數.

ffmpeg -ss 01:23:45 -i jidu.mp4 image.jpg

從視訊中生成GIF圖片

ffmpeg -i jidu.mp4 -t 10 -pix_fmt rgb24 jidu.gif

轉換視訊為圖片(每幀一張圖)

ffmpeg -i clip.avi frame%4d.jpg

圖片轉換為視訊

ffmpeg -f image2 -i img%4d.jpg -r 25 video.mp4

 

裁剪、填充

和視訊一樣,圖片也可以被裁剪和填充

裁剪

ffmpeg -f lavfi -i rgbtestsrc -vf crop=150:150 crop_rg.png

填充

ffmpeg -f lavfi -i smptebars -vf pad=360:280:20:20:orange pad_smpte.jpg

 

翻轉,旋轉,覆蓋

和視訊一樣圖片同樣能翻轉,旋轉和覆蓋

翻轉

ffmpeg -i orange.jpg -vf hflip orange_hfilp.jpg

ffmpeg -i orange.jpg -vf vflip orange_vfilp.jpg

旋轉

ffmpeg -i image.png -vf transpose=1 image_rotated.png

覆蓋

ffmpeg -f lavfi -i rgbtestsrc -s 400×300 rgb .png 

ffmpeg -f lavfi -i smptebars smpte.png 

ffmpeg -i rgb .png -i smpte.png -filter_complex overlay= (W-w)/2:(H-h)/2  rgb_smpte.png

 

第十一部分

其他高階技巧

螢幕錄影

顯示裝置名稱

ffmpeg -list_devices 1 -f dshow -i dummy

呼叫攝像頭

ffplay -f dshow  -i video=”Integrated Camera”

儲存為檔案

ffmpeg -y -f dshow -s 320×240 -r 25 -i video=”Integrated Camera” -b:v 800K -vcodec mpeg4 new.mp4

 

新增字幕subtitles

語法 –vf subtitles=file

 

ffmpeg -i jidu.mp4 -vf subtitles=rgb.srt output.mp4

視訊顫抖、色彩平衡

視訊顫抖

ffplay –i jidu.mp4 -vf crop=in_w/2:in_h/2:(in_w-out_w)/2 ((in_w-out_w)/2)*sin(n/10):(in_h-out_h)/2 ((in_h-out_h)/2)*sin(n/7)

 

色彩平衡

ffplay -i jidu.mp4 -vf curves=vintage

色彩變幻

ffplay -i jidu.mp4 -vf hue=”H=2*PI*t: s=sin(2*PI*t) 1“

彩色轉換黑白

ffplay -i jidu.mp4 -vf lutyuv=”u=128:v=128″

設定音訊視訊播放速度

3倍視訊播放視訊

ffplay -i jidu.mp4 -vf setpts=PTS/3

?速度播放視訊

ffplay -i jidu.mp4  -vf setpts=PTS/(3/4)

2倍速度播放音訊

ffplay -i speech.mp3 -af atempo=2

 

問題:視訊和音訊同時3/4慢速播放

截圖

每隔一秒截一張圖

ffmpeg -i input.flv -f image2 -vf fps=fps=1 out%d.png

每隔20秒截一張圖

ffmpeg -i input.flv -f image2 -vf fps=fps=1/20 out%d.png

 

注意:ffmpeg version N-57961-gec8e68c版本最多可以每隔20s截一張圖。

多張截圖合併到一個檔案裡(2×3) ?每隔一千幀(秒數=1000/fps25)即40s截一張圖

ffmpeg? -i jidu.mp4 -frames 3 -vf “select=not(mod(n\,1000)),scale=320:240,tile=2×3” out.png

 

馬賽克視訊

馬賽克視訊

用多個輸入檔案建立一個馬賽克視訊:

ffmpeg -i jidu.mp4 -i jidu.flv -i “Day By Day SBS.mp4” -i “Dangerous.mp4” -filter_complex “nullsrc=size=640×480 [base]; [0:v] setpts=PTS-STARTPTS, scale=320×240 [upperleft]; [1:v] setpts=PTS-STARTPTS, scale=320×240 [upperright]; [2:v] setpts=PTS-STARTPTS, scale=320×240
[lowerleft]; [3:v] setpts=PTS-STARTPTS, scale=320×240 [lowerright]; [base][upperleft] overlay=shortest=1 [tmp1]; [tmp1][upperright] overlay=shortest=1:x=320 [tmp2]; [tmp2][lowerleft] overlay=shortest=1:y=240 [tmp3]; [tmp3][lowerright] overlay=shortest=1:x=320:y=240”
-c:v libx264 output.mkv

 

Logo動態移動

1、2秒後logo從左到右移動:

ffplay -i jidu.mp4  -vf movie=logo.png[logo];[in][logo]overlay=x=’if(gte(t\,2)\,((t-2)*80)-w\,NAN)’:y=0

 

2、2秒後logo從左到右移動後停止在左上角

ffplay -i jidu.mp4  -vf movie=logo.png[logo];[in][logo]overlay=x=’if(gte(((t-2)*80)-w\,W)\,0\,((t-2)*80)-w)’:y=0

3、每隔10秒交替出現logo。

ffmpeg -y -t 60 -i jidu.mp4 -i logo.png -i logo2.png -filter_complex “overlay=x=if(lt(mod(t\,20)\,10)\,10\,NAN ):y=10,overlay=x=if(gt(mod(t\,20)\,10)\,W-w-10\,NAN ) :y=10” overlay.mp4

 

資料

FFmpeg官網: http://www.ffmpeg.org

FFmpeg doc : http://www.ffmpeg.org/documentation.html

FFmpeg wiki : https://trac.ffmpeg.org/wiki

FAQ

Thanks!

 

 FFmpeg基礎: http://wenku.baidu.com/view/296eefcaf90f76c661371af1.html

原帖地址:http://derekzhan.iteye.com/blog/1989274