本文為作者原創,轉載請注明出處:https://www.cnblogs.com/leisure_chn/p/10434209.html
1. overlay 技術簡介
overlay 技術又稱視頻疊加技術。overlay 視頻技術使用非常廣泛,常見的例子有,電視屏幕右上角顯示的電視台台標,以及畫中畫功能。畫中畫是指在一個大的視頻播放窗口中還存在一個小播放窗口,兩個窗口不同的視頻內容同時播放。
overlay 技術中涉及兩個窗口,通常把較大的窗口稱作背景窗口,較小的窗口稱作前景窗口,背景窗口或前景窗口里都可以播放視頻或顯示圖片。FFmpeg 中使用 overlay 濾鏡可實現視頻疊加技術。
overlay 濾鏡說明如下:
描述:前景窗口(第二輸入)覆蓋在背景窗口(第一輸入)的指定位置。
語法:overlay[=x:y[[:rgb={0, 1}]]
參數 x 和 y 是可選的,默認為 0。
參數 rgb 參數也是可選的,其值為 0 或 1,默認為 0。
參數說明:
x 從左上角的水平坐標,默認值為 0
y 從左上角的垂直坐標,默認值為 0
rgb 值為 0 表示輸入顏色空間不改變,默認為 0;值為 1 表示將輸入的顏色空間設置為 RGB
變量說明:如下變量可用在 x 和 y 的表達式中
main_w 或 W 主輸入(背景窗口)寬度
main_h 或 H 主輸入(背景窗口)高度
overlay_w 或 w overlay 輸入(前景窗口)寬度
overlay_h 或 h overlay 輸入(前景窗口)高度
overlay 濾鏡相關參數示意圖如下:
2. 命令行用法
可先參考 "FFmpeg 使用基礎" 了解 FFmpeg 命令行基本用法。
overlay 命令行基本格式如下:
ffmpeg -i input1 -i input2 -filter_complex overlay=x:y output
input1 是背景窗口輸入源,input2 是前景窗口輸入源。
2.1 視頻中疊加圖標
背景窗口視頻素材下載(右鍵另存為):ring.mp4
視頻分辨率是 768x432(此分辨率適用於平板電腦,寬高比為 16:9),上下黑邊的像素高度是 56,播放時長為 37.97 秒。關於分辨率與黑邊的相關內容可參考如下:
為什么很多人把視頻上下加黑條當做“電影感”?
用於編碼視頻文件的視頻預設
前景窗口圖標素材下載(右鍵另存為):ring_100x87.png
圖標分辨率是 100x87。圖標格式為 PNG 格式,當然選用其他格式的圖片作圖標也是可以的,但 PNG 圖標具有透明背景,更適合用作圖標。
2.1.1 直接疊加圖標
將圖標疊加於視頻右上角:("-max_muxing_queue_size" 參數的使用見參考資料[3])
ffmpeg -i ring.mp4 -i ring_100x87.png -filter_complex overlay=W-w:56 -max_muxing_queue_size 1024 ring_logo_t.mp4
效果如下:
將圖標疊加於視頻右下角:
ffmpeg -i ring.mp4 -i ring_100x87.png -filter_complex overlay=W-w:H-h-56 -max_muxing_queue_size 1024 ring_logo_b.mp4
效果如下:
2.1.2 延時疊加圖標
如下,背景窗口播放 8.6 秒后,圖標開始顯示。注意 “-itsoffset 8.6” 作為第二個輸入文件的輸入選項,參數位置不能放錯。
ffmpeg -i ring.mp4 -itsoffset 8.6 -i ring_100x87.png -filter_complex overlay=W-w:56 -max_muxing_queue_size 1024 ring_logo_delay.mp4
2.2 視頻中疊加視頻——畫中畫
視頻中疊加視頻即為畫中畫功能。注意兩個視頻僅圖像部分會疊加在一起,聲音是不會疊加的,有一個視頻的聲音會消失。
2.2.1 疊加計時器
找一個計時器小視頻,將之疊加到背景視頻上。我們可以從測試源中獲取這個計時器視頻。先運行如下命令:
ffplay -f lavfi -i testsrc
視頻無法貼在本文里,那運行截圖命令,從視頻中截取一張圖:
ffmpeg -ss 00:00:12 -f lavfi -i testsrc -frames:v 1 -f image2 testsrc.jpg
效果如下:
我們把計時器那一小塊視頻裁剪下來,運行如下命令:
ffmpeg -ss 00:00:10 -t 20 -f lavfi -i testsrc -vf crop=61:52:224:94 timer.h264
此命令主要用到了 crop 視頻濾鏡,說明一下:
"-vf crop=61:52:224:94" 表示裁剪一塊位於 (224,94) 坐標處寬為 61 像素高為 52 像素的視頻塊
"-ss 00:00:10 -t 20" 表示從 10 秒處開始裁剪,裁剪時長為 20 秒
將計時器視頻 timer.h264 疊加到背景視頻 ring.mp4 里:
ffmpeg -i ring.mp4 -i timer.h264 -filter_complex overlay=W-w:0 -max_muxing_queue_size 1024 ring_timer.mp4
效果如下:
看一下視頻疊加過程中 FFmpeg 在控制台中的打印信息,關注流的處理:
$ ffmpeg -i ring.mp4 -i timer.h264 -filter_complex overlay=W-w:0 -max_muxing_queue_size 1024 ring_timer.mp4
......
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'ring.mp4':
Metadata:
......
Duration: 00:00:37.97, start: 0.032000, bitrate: 515 kb/s
Stream #0:0(chi): Video: h264 (avc1 / 0x31637661), none, 768x432, 488 kb/s, 23 fps, 23 tbr, 23k tbn, 46k tbc (default)
Metadata:
handler_name : 1348358526.h264#video:fps=23 - Imported with GPAC 0.5.1-DEV-rev4127
Stream #0:1(chi): Audio: aac (HE-AAC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 95 kb/s (default)
Metadata:
handler_name : GPAC ISO Audio Handler
Input #1, h264, from 'timer.h264':
Duration: N/A, bitrate: N/A
Stream #1:0: Video: h264 (High 4:4:4 Predictive), yuv444p(progressive), 61x52 [SAR 1:1 DAR 61:52], 25 fps, 25 tbr, 1200k tbn, 50 tbc
Stream mapping:
Stream #0:0 (h264) -> overlay:main (graph 0)
Stream #1:0 (h264) -> overlay:overlay (graph 0)
overlay (graph 0) -> Stream #0:0 (libx264)
Stream #0:1 -> #0:1 (aac (native) -> aac (native))
......
看 "Stream mapping" 部分可以看出:
輸入源 1 視頻流 "Stream #0:0" 和輸入源 2 視頻流 "Stream #1:0" 疊加到輸出視頻流 "Stream #0:0"
輸入源 1 音頻流 "Stream #0:1" 拷貝到輸出音頻流 "Stream #0:1"
視頻開始幾秒處播放有些異常,聲音播放幾秒后圖像才開始播放,原因不太清楚。
3. API用法
使用濾鏡API編程,解析不同的濾鏡選項,以達到和命令行中輸入命令同樣的效果。
例程使用 "FFmpeg 濾鏡 API 用法與實例解析" 中第 4.2 節的示例程序,運行如下命令下載例程源碼:
svn checkout https://github.com/leichn/exercises/trunk/source/ffmpeg/ffmpeg_vfilter
下載之后進入源碼目錄,編譯生成 vf_file 可執行文件:
cd ffmpeg_vfilter
make vf_file
運行如下命令進行測試:
./vf_file ring.flv -vf "movie=ring_100x87.png[logo];[in][logo]overlay=W-w:56"
測試效果為:
因為例程尚不支持多輸入的方式,所以上述測試命令中借助了 movie 濾鏡來加載第二個輸入,這條命令和下面這條命令效果是一樣的
ffplay ring.mp4 -i ring_100x87.png -filter_complex overlay=W-w:56
4. 遺留問題
第 3 節例程不支持多輸入方式,借助了 movie 濾鏡變通實現,多輸入情況下 API 如何編程?待分析如下命令中多輸入選項的解析處理方式:
ffplay ring.mp4 -i ring_100x87.png -filter_complex overlay=W-w:56
5. 參考資料
[1] 為什么很多人把視頻上下加黑條當做“電影感”?
[2] 用於編碼視頻文件的視頻預設
[3] Too many packets buffered for output stream
6. 修改記錄
2019-02-16 V1.0 首次整理
2020-01-17 V1.0 修改資源文件下載地址錯誤
2020-02-23 V1.0 github 文件下載地址規則改變,修改資源文件無法下載問題