首页
/
每日頭條
/
生活
/
ffmpeg 特效
ffmpeg 特效
更新时间:2024-04-28 04:38:13

ffmpeg是許多音視頻入門書籍都會推薦學習的一套多媒體框架,其集封裝、解封裝、編碼、解碼、播放和濾鏡等多項功能于一身,堪稱音視頻領域的「瑞士軍刀」。

今天,我們将不再遵循常規教程的套路,而是将以表情包界名垂青史的名場面、電影《旺角卡門》中的經典片段——「吔屎啦你」為講解素材,通過GIF表情包創作的場景化教學,來講解FFmpeg命令行工具的實際運用。

若本教程成功地激起了你對FFmpeg命令行工具的探索興趣,記得說聲多謝老舅點贊、收藏、評論三連支持一下。

Hello, GIF!

首先,舉一個最簡單的例子,即,直接把一個任意格式的視頻片段轉為GIF圖像:

ffmpeg -i as_tears_go_by.mp4 as_tears_go_by.gif

-i 選項用于指定任意數量的輸入流,可以是本地文件也可以是網絡文件。

而輸出流也可以是任意數量的,其指定的方式則相對粗暴得多,隻要是命令行中無法解釋為「選項」的内容,都會被FFmpeg命令行工具視為輸出流

大多數情況下,FFmpeg命令行工具會根據輸入輸出流的擴展名去自動檢測格式,如果需要強制指定輸入或輸出流的格式,可以使用-f 選項,比如:

ffmpeg -i as_tears_go_by.mp4 -f gif as_tears_go_by.gif

效果都是一樣的。

名場面往往就是那幾秒

在誕生這些表情包名場面的電影中,你經常會發現有那麼一群“合影黨”,喜歡把播放進度拖動到表情包畫面出現的前後幾秒,然後在公屏上打上“合影留念”的彈幕(說的是不是你?),仿佛一開始就是奔着這幾秒去看這部電影的。

而我們創作表情包的第一步,自然也是先截取出這些全片中最精彩的片段。

要截取視頻中的特定位置與時長的片段,我們可以用以下命令行實現:

ffmpeg -i {input} -ss {position} -t {duration} {output}

其中,

-ss 選項用于定位到指定的視頻位置,可以是「HH:MM:SS」這種格式,也可以是「2.3」這種表示第2.3秒的格式。

-t 選項用于表示截取的視頻時長,也同樣支持以上2種時間格式。

例如,「吔屎啦你」這一名場面發生在上述視頻片段的第11秒,持續時間約為2.3秒,那我們就可以這樣子編寫命令行:

ffmpeg -i as_tears_go_by.mp4 -ss 00:11 -t 2.3 as_tears_go_by-trim.gif

到位了到位了哈!可是有一個問題出現了,盡管經過截取處理,轉出的GIF圖像文件仍有11.6MB,作為一個表情包來講,實在是太大了。

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)1

而相同時長的MP4視頻文件大小卻隻有664KB,為什麼兩者能相差這麼大呢?這其實跟二者采用的壓縮算法有關,後面系列文章中會專門講到,這裡就先不展開說了。

鬥圖,講究一個「快」字

你肯定有過這樣的經曆,本來和暧昧對象在微信上聊得好好的,不知怎的突然就沒話題了。與其繼續尬聊下去,我們更多會選擇開啟「鬥圖」模式,來緩解和過渡這一尴尬的時刻。

鬥圖除了考驗你表情包彈藥庫的存量之外,表情包連發的“攻速”也很重要。

想象一下,對方的表情包如機關槍般“哒哒哒”密集地發來,而你的表情包卻因為GIF格式下的文件過大,到了對方的聊天面闆還要轉圈下載好一陣,氣勢上就輸了一大截。

因此,壓縮表情包文件的大小,很重要。

壓縮大法第一式——縮放

ffprobe是FFmpeg提供的多媒體信息查看工具,我們可以先使用ffprobe來查看上一步中截取了名場面,并轉換了格式後的GIF圖像信息:

ffprobe as_tears_go_by-trim.gif

Input #0, gif, from 'as_tears_go_by-cut.gif':

Duration: 00:00:02.32, start: 0.000000, bitrate: 40101 kb/s

Stream #0:0: Video: gif, bgra, 1920x1080 [SAR 64:64 DAR 16:9], 25 fps, 25 tbr, 100 tbn

可以看到,由于我們是直接将視頻片段轉為GIF圖像的,文件的尺寸大小高達1920x1080!和一般的靜态圖片一樣,GIF格式的文件大小也是受尺寸大小影響的,尺寸越大相應的文件也就越大,但作為表情包我們往往不需要追求如此高清的效果。

因此,我們壓縮工作的第一步,就是縮減GIF文件的尺寸。

可以使用以下命令行來實現:

ffmpeg -i {input} -s {WxH} {output}

可以看到,由于我們是直接将視頻片段轉為GIF圖像的,文件的尺寸大小高達1920x1080!和一般的靜态圖片一樣,GIF格式的文件大小也是受尺寸大小影響的,尺寸越大相應的文件也就越大,但作為表情包我們往往不需要追求如此高清的效果。

【更多音視頻學習資料,點擊下方鍊接免費領取↓↓,先碼住不迷路~】

點擊領取→音視頻開發基礎知識和資料包

因此,我們壓縮工作的第一步,就是縮減GIF文件的尺寸。

可以使用以下命令行來實現:

ffmpeg -i {input} -s {WxH} {output}

-s 選項用于指定輸出文件的尺寸大小,格式上是「寬度(W)x高度(H)」

例如,我們可以拿到前面的GIF圖像文件,将其寬高均縮放至原先的1/6:

ffmpeg -i as_tears_go_by-cut.gif -s 320x180 as_tears_go_by-scale.gif

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)2

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)3

可以看到,經過縮放後的文件大小已減少至1.6M,約為原先大小的1/7,效果還是比較明顯的。

壓縮大法第二式——抽幀

GIF是連續的動态圖像,可以視作是一張一張完整的圖像按一定速率播放,然後利用人眼的視覺殘留效應所形成的效果。每秒鐘依次播放的圖像數量叫做幀率,單位是fps(frame per second,幀每秒)。

前面我們用ffprobe工具查看後可得知,輸出的GIF圖像的幀率是25fps,這是由于我們是直接将視頻片段轉為GIF圖像的,而電影中的常見幀率為24/25幀,因此輸出的GIF圖像也保留了相同的幀率。

幀率越高,GIF圖像的動效相對就越流暢,但相應的要儲存的圖片幀也會更多,可能導緻文件大小直線上升。通過減少幀數,犧牲一點連貫性,可以顯著優化文件的大小。

可以使用以下命令行來實現:

ffmpeg -i {input} -r {fps} {output}

-r 選項用于指定幀率,支持整數和分數格式。

例如,我們可以将上一步幀率為25fps的GIF圖像減少至8fps:

ffmpeg -i as_tears_go_by-scale.gif -r 8 as_tears_go_by-frameextract.gif

幀率減少後的GIF圖像效果如下:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)4

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)5

可以看到,經過抽幀處理後的GIF圖像大小得到了進一步的壓縮。

壓縮大法第三式——裁剪

裁剪同樣是為了縮減GIF圖像的尺寸,隻不過和單純的縮放相比,裁剪還有去除冗餘元素、突出目标主體的附加效果。

借助FFmpeg命令行工具實現對圖像/視頻的裁剪,我們需要用到Filter(濾鏡、過濾器)模塊。

濾鏡模塊提供了許多音視頻特效處理的功能,比如crop(裁剪)、scale(縮放)、overlay(疊加)、rotate(旋轉),trim(截取)等。可以說,前面幾個步驟提到的功能,都有相應的濾鏡可以實現。

如果要為視頻類型的輸入流指定使用的濾鏡,需要使用-vf 選項。可指定的濾鏡按輸入輸出流的數量和類型可分為「簡單濾鏡」和「複雜濾鏡」兩種。

所謂「簡單濾鏡」,指的是那種剛好隻有一個輸入流、一個輸出流的的濾鏡,且兩者都是同一類型的情況:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)6

相對的,「複雜濾鏡」指的則是那些具有多個輸入流/輸出流,或者輸出流類型與輸入流類型不同的情況:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)7

比如我們現在要實現的裁剪功能,就是一個典型的「簡單濾鏡」:

ffmpeg -i as_tears_go_by-frameextract.gif -vf "crop=180:180:100:0" as_tears_go_by-crop.gif

這條命令行的完整釋義如下:

  • 輸入一個名為“as_tears_go_by-frameextract”的GIF圖像文件
  • 創建一個提供裁剪功能的視頻濾鏡,用于過濾輸入流。
  • 裁剪區域的寬度為180,高度為180,從以左上角為原點、x軸向右偏移量為100、y軸向下偏移量為0的位置開始裁剪。
  • 将裁剪完成的内容輸出到一個名為“as_tears_go_by-cut”的GIF圖像文件

經過裁剪後輸出的GIF圖像效果如下:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)8

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)9

【更多音視頻學習資料,點擊下方鍊接免費領取↓↓,先碼住不迷路~】

點擊領取→C 程序員必看,抓住音視頻開發的大浪潮!沖擊年薪60萬

更騷的操作

FFmpeg濾鏡的強大之處,在于它可以通過不同濾鏡的排列組合,實現各種各樣複雜的功能

FFmpeg濾鏡共包含以下3個層級:

filter -> filterchain -> filtergraph 也即 濾鏡 -> 濾鏡鍊 -> 濾鏡圖

多個濾鏡可以串聯成一條濾鏡鍊,多條濾鏡鍊可以組合成一個濾鏡圖

我們可以基于FFmpeg的官方示例進行改造,實現“裁剪出視頻的左半部分,并鏡像疊加到視頻的右半部分”的效果,來演示一下三者的關系,以及如何結合使用,流程圖如下:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)10

  1. 首先,使用split濾鏡将輸入流分割為兩個流[main]和[tmp] (你可以理解為copy了一份);
  2. 将其中一個流[tmp]先通過crop濾鏡裁剪出左半部分;
  3. 将步驟2的輸出再經過hflip濾鏡進行水平翻轉,并輸出為[flip];
  4. 把步驟3的輸出[flip]疊加到[main]的右半部分。

這個流程使用命令行實現如下:

ffmpeg -i as_tears_go_by-crop.gif -vf "split[main][tmp];[tmp]crop=iw/2:ih:0:0,hflip[flip];[main][flip]overlay=W/2:0" as_tears_go_by-graph.gif

是不是看着這麼多的參數有點懵圈了?不要怕,這個涉及到濾鏡模塊的語法,我們一個一個來解釋:

首先,[main][tmp][flip]是為輸入輸出流所打的标簽,可以任意命名,打标簽是可選的,為了連接其他濾鏡時方便使用。

split、crop、hflip、overlay都是具體使用的濾鏡,濾鏡的各種參數在=号後面指定。

濾鏡的參數之間用冒号:分隔,可以是純值的形式,也可以是“鍵=值”的形式,還可以是二者混用的形式。

比如crop濾鏡的參數也可以這樣指定:crop=w=iw/2:h=ih:x=0:y=0,iw和ih這兩個變量分别指的是輸入幀的寬度和高度。

同一濾鏡鍊内的不同濾鏡之間用逗号,分隔。

比如[tmp]crop=iw/2:ih:0:0,hflip[flip]這一濾鏡鍊中就包含crop和hflip這兩個濾鏡,兩者之間使用逗号,分隔。

同一濾鏡圖内的不同濾鏡鍊之間用分号;分隔。

比如上面的濾鏡圖就包含split;crop,flip;overlay三條濾鏡鍊,彼此之間使用用分号;分隔。

最終輸出的效果如下——忍法·雙頭嘲諷:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)11

嗯......看着有點詭異呢!

表情包的經典二創

一個表情包之所以經久不衰,除了表情包本身很有“梗”之外,網友們富有想象力的“二次創作”,也是表情包能再次迸發出生命力的原因之一。

比如讓人忍俊不禁的「欲吔又止」:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)12

這種類似連環畫的表情包叙事感很強,如果采用FFmpeg來創作的話,可以分為以下幾步進行:

視頻截圖手動截圖

手動截圖的工作需要先借助前面提到的-ss 選項,定位到視頻片段指定的位置,然後再借助-vframe 選項來輸出指定數量的視頻幀,最後當然還要再對輸出的視頻幀的進行一波同樣的裁剪和縮放。

具體的命令行示例如下:

ffmpeg -i as_tears_go_by.mp4 -ss 00:13 -vframes 1 -vf "crop=ih:ih:iw/4:0" -s 180x180 as_tears_go_by-screenshot.jpg

得到的處理後的視頻截圖如下:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)13

定時截圖

【更多音視頻學習資料,點擊下方鍊接免費領取↓↓,先碼住不迷路~】

點擊領取→音視頻開發基礎知識和資料包

但如果你想偷一下懶,不想一張張手動去截,我們也可以借助fps濾鏡實現來定時截圖,然後再從輸出的圖片集裡找符合預期的截圖即可,命令行如下:

ffmpeg -i as_tears_go_by.mp4 -vf "fps=2,crop=ih:ih:iw/4:0" -s 180x180 screenshot/out%d.jpg

此命令行執行後,每過0.5秒就會生成一張JPG格式的圖片,并進行一波同樣的裁剪和縮放。

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)14

從中我們最終挑出以下四張截圖作為素材:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)15

添加文字

添加文字的工作同樣可借助濾鏡功能完成,使用到的濾鏡是「drawtext」濾鏡。

我們先拿前面經過裁剪之後生成的GIF圖像來做下實驗:

ffmpeg -i as_tears_go_by-crop.gif -vf "drawtext=fontsize=30:text='吔屎啦你':fontcolor=white:x=25:y=100:fontfile=JingNanYuanMoTi/KNFONTYUANMO-2.otf" as_tears_go_by-text.gif

添加文字後的效果如下:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)16

fontsize、fontcolor、text等從字面意義就可以知曉其作用的參數我就不再贅述了,這裡需要提到的是,如果默認的字體風格不符合預期,drawtext濾鏡也支持使用「fontfile」參數來指定所采用的字體文件,比如上面的otf文件。

以下是挑選出的4張截圖添加文字後的效果:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)17

多宮格處理

多宮格處理的工作實際就是前面所提到的「複雜濾鏡」的使用場景,我們需要整合多個輸入流(此處是靜态圖),并拼接到一個畫布上輸出。

先丢出處理的命令行:

ffmpeg -i 1.jpg -i 2.jpg -i 3.jpg -i 4.jpg -filter_complex "nullsrc=size=360x360[base];[base][0:v]overlay=0:0[tmp1];[tmp1][1:v]overlay=180:0[tmp2];[tmp2][2:v]overlay=0:180[tmp3];[tmp3][3:v]overlay=180:180" -frames:v 1 output.jpg

命令行很長,但是了解過前面的濾鏡語法以後,相信也不難理解,我們來一步步解釋:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)18

  • 首先,通過-i 選項輸入4張待處理的靜态圖素材;
  • 其次,通過-filter_complex 選項創建一個複雜濾鏡;
  • 該複雜濾鏡首先創建了一個360x360的空白畫布,并指定輸出流的标簽為[base];
  • [0:v]表示取第一個輸入流(第1張靜态圖),然後使用overlay濾鏡,将第1張靜态圖疊加到左上角原點的位置(也即左上角),并指定疊加處理輸出流的标簽為[tmp1];
  • 繼續使用overlay濾鏡,将第2張靜态圖疊加到以左上角原點,x軸向右偏移量為180、y軸向下偏移量為0的位置(也即右上角),并指定疊加處理輸出流的标簽為[tmp2];
  • 繼續使用overlay濾鏡,将第3張靜态圖疊加到以左上角原點,x軸向右偏移量為0、y軸向下偏移量為180的位置(也即左下角),并指定疊加處理輸出流的标簽為[tmp3];
  • 繼續使用overlay濾鏡,将第4張靜态圖疊加到以左上角原點,x軸向右偏移量為180、y軸向下偏移量為180的位置(也即右下角);
  • 将全部處理完成的内容輸出到一個名為“output.jpg”的文件
  • 【更多音視頻學習資料,點擊下方鍊接免費領取↓↓,先碼住不迷路~】
  • 點擊領取→C 程序員必看,抓住音視頻開發的大浪潮!沖擊年薪60萬

最終産出的效果圖如下:

ffmpeg 特效(FFmpeg創作GIF表情包教程來了)19

命令行的優勢

可能有人想說了,我幹嘛要去寫這麼一大串晦澀難懂的命令行呢?要創作表情包,使用有可視化界面的軟件操作不香嗎?

誠然,可視化界面有可視化界面的優勢,像前面添加文字的操作,鼠标或手指點點拖拖就可以完成了。但是别忘了,許多所謂的擁有可視化界面的軟件,其隻不過是在命令行工具上披一層皮而已

換句話說,隻要熟悉了FFmpeg命令行工具的使用之後,我們就完全可以自己做一個擁有可視化界面,而功能底層使用FFmpeg命令行來實現的軟件。

比如在Android平台上,我們就可以通過手動将FFmpeg源碼編譯成so庫,并抽取ffmpeg編解碼工具的相關文件,借助NDK開發自行封裝成一個FFmpeg命令行工具庫,然後集成到我們的App中去,從而實現一個功能豐富的視頻編輯工具App。(後續文章将講到,敬請關注)。

看到這裡,你還不想打開FFmpeg命令行工具實際操作一番嗎?

,
Comments
Welcome to tft每日頭條 comments! Please keep conversations courteous and on-topic. To fosterproductive and respectful conversations, you may see comments from our Community Managers.
Sign up to post
Sort by
Show More Comments
Copyright 2023-2024 - www.tftnews.com All Rights Reserved