影片剪輯軟體的時間軸畫面,顯示多軌影片與音訊片段

← INSIGHTS & PERSPECTIVES | 後端開發

使用 FFmpeg 濾鏡功能做影片合成

用 FFmpeg 疊字、綠幕去背合成與低延遲推流的實際指令範例,附參數逐項解說。

FFmpeg 除了轉檔,也能直接用濾鏡疊字、去背合成、推流測試延遲。以下整理幾個實際會用到的指令:疊上即時時鐘文字、把虛擬攝影機畫面推到 RTMP 伺服器、做綠幕去背疊加,以及設定低延遲播放。指令來自 官方下載頁 對應版本的 FFmpeg,在 Windows 環境下用 DirectShow 抓攝影機畫面測試過。

如何用 FFmpeg 疊上即時時鐘文字並推流?

用 `drawtext` 濾鏡搭配 `setpts` 計算時間戳,就能在畫面上疊一個會跳動的時鐘文字,常用來檢查串流延遲:

```bash

ffmpeg -f lavfi -i color=c=0x00ff00:s=800x450 -vf "settb=AVTB, setpts='trunc(PTS/1K)1K+st(1,trunc(RTCTIME/1K))-1Ktrunc(ld(1)/1K)', drawtext=text='STREAM2-%{localtime}.%{eif\:1Mt-1Ktrunc(t*1K)\:d}':x=100:y=100:fontsize=32:fontcolor=white" -c:v libx264 -f flv rtmp://192.168.189.11/live/test2

```

逐段拆解:

  • `-f lavfi -i color=c=0x00ff00:s=800x450`:用 lavfi 產生一個純色輸入源,`c=0x00ff00` 是綠色填充,`s=800x450` 是解析度。
  • `settb=AVTB, setpts=...`:設定時間基準並重新計算時間戳,依 PTS(顯示時間戳)與 RTCTIME(實際時鐘時間)換算,讓疊字反映真實時間而不是影格編號。
  • `drawtext=text='STREAM2-%{localtime}...'`:在畫面 (100,100) 位置畫出白色文字,`%{localtime}` 帶入本地時間,`%{eif:...}` 補上格式化後的毫秒數。
  • `-c:v libx264`:以 H.264 編碼。
  • `-f flv rtmp://...`:輸出為 FLV 格式並推到指定 RTMP 位址。

這種畫面常拿來做端到端延遲量測——比較畫面上的時鐘文字和播放端實際看到的時間差。

如何把虛擬攝影機畫面推流到 RTMP?

Windows 下用 DirectShow 抓 OBS 虛擬攝影機的畫面,編碼後推到 RTMP:

```bash

ffmpeg -f dshow -rtbufsize 200M -i video=OBS-Camera -pix_fmt yuv420p -c:v libx264 -profile:v baseline -level:v 3.1 -preset:v ultrafast -s 480x270 -g 240 -an -f flv -y rtmp://172.16.46.89/live/0101_dealerPC1

```

參數重點:

參數用途
`-f dshow -rtbufsize 200M -i video=OBS-Camera`用 DirectShow 抓 "OBS-Camera" 這個裝置,緩衝區設 200MB 避免掉幀
`-pix_fmt yuv420p`輸出像素格式為 4:2:0,相容性最好
`-profile:v baseline -level:v 3.1`串流用的保守 profile/level 組合,播放器相容性較高
`-preset:v ultrafast`編碼速度優先,犧牲一點壓縮率換取低延遲
`-g 240`每 240 幀插一個關鍵幀(GOP size),24fps 時約等於 10 秒一個 I 幀
`-an`不擷取音訊
`-y`直接覆蓋已存在的輸出檔案

如何用 FFplay 做極低延遲播放測試?

推流端調整完,播放端也要關掉緩衝才能驗證真實延遲:

```bash

ffplay -fflags nobuffer -flags low_delay -rtmp_buffer 0 -rtmp_live live -framedrop -infbuf %desc%

```

  • `-fflags nobuffer`、`-infbuf`:都是關閉輸入緩衝,減少排隊等待的時間。
  • `-flags low_delay`:啟用低延遲解碼模式。
  • `-rtmp_buffer 0`、`-rtmp_live live`:RTMP 緩衝設為 0,並告知這是即時直播流而非點播。
  • `-framedrop`:解碼跟不上時主動丟幀,避免畫面越拖越慢。
  • `%desc%`:換成實際的串流網址或占位變數。

如何用 FFmpeg 把虛擬攝影機和線上串流做綠幕合成?

這是本文的重點案例:把本機虛擬攝影機畫面去背(colorkey)之後,疊加到另一路 RTMP 串流上,再用 GPU 編碼輸出:

```bash

ffmpeg -f dshow -rtbufsize 1M -i video="OBS Virtual Camera" -f flv -i rtmp://172.17.22.89/live/test1 -filter_complex "[0:v]colorkey=0x00ff00:0.3:0.2[keyed];[1:v][keyed]overlay[o]" -map "[o]" -c:v h264_nvenc -f flv rtmp://127.0.0.1/live/test3

```

這裡有兩個輸入源:`[0:v]` 是本機虛擬攝影機,`[1:v]` 是另一路 RTMP 串流。`-filter_complex` 做了兩件事:

  1. `[0:v]colorkey=0x00ff00:0.3:0.2[keyed]`:對輸入 0 套用 colorkey,去除綠色(`0x00ff00`)背景,`0.3` 是相似度容忍度,`0.2` 是邊緣模糊程度,結果存成 `[keyed]` 這個帶透明背景的影像流。
  2. `[1:v][keyed]overlay[o]`:把 `[keyed]`(去背後的虛擬攝影機畫面)疊在輸入 1(線上串流)之上,輸出成 `[o]`。

再用 `-map "[o]"` 指定要輸出的是合成後的畫面,`-c:v h264_nvenc` 則交給 NVIDIA GPU 硬體編碼,減輕 CPU 負擔,最後推到 `rtmp://127.0.0.1/live/test3`。

這個做法適合把講者去背後疊加在簡報畫面或另一路遠端串流上,不需要額外的合成軟體。

串流參數速查

實務上常需要動態調整編碼參數,以下是一份 Windows batch 範例,把常用選項抽成變數方便替換:

```bash

set ffmpegBin=C:\apps\ffmpeg\

set PATH=%PATH%;%ffmpegBin%

set camName="OBS Virtual Camera"

set camBufferSize=1000

set desc=rtmp://127.0.0.1:1935/live/demo

set codec=libx264

set fps=24

set /a "keyint=%fps%*5"

set x264opts=keyint=120:min-keyint=%fps%:scenecut=0

set preset=medium

set profile=baseline

set level=3.1

set resolution=800x450

set bitrate=700

:: publish stream

ffmpeg -f dshow -rtbufsize %camBufferSize%M -i video=%camName% ^

-vf format=yuv420p ^

-vcodec %codec% -x264-params %x264opts% ^

-preset %preset% -profile:v %profile% -level:v %level% ^

-tune:v zerolatency ^

-s %resolution% ^

-r %fps% ^

-b:v %bitrate%k -minrate %bitrate%k -maxrate %bitrate%k -bufsize %bitrate%k ^

-an ^

-f flv %desc%

```

常用參數對照:

參數說明
`-r`輸出 fps
`-y`覆蓋既有輸出檔案,不詢問
`-i`輸入來源
`-c:v`影片編碼器
`-profile:v`編碼 profile,串流建議用 `baseline`
`-level:v`編碼 level,串流建議用 `3.1`
`-preset:v`編碼速度,串流建議用 `ultrafast`
`-b:v`目標 bitrate,例如 `700k`
`-s`輸出解析度
`-g`GOP size(關鍵幀間隔),`-r 24 -g 240` 約等於每 10 秒一個關鍵幀
`-an`不處理音訊
`-f flv`輸出容器格式
`-f dshow -i video=OBS-Camera`Windows 上用 DirectShow 抓攝影機畫面
`-rtbufsize 200M`加大輸入緩衝,避免掉幀
`-re`依原始檔案的 frame rate 讀取,會拖慢即時轉發,不需要延遲時應拿掉

`FFREPORT` 環境變數設定後,FFmpeg 會依設定自動存 log,方便事後排查問題。更完整的 restream 設定可參考 Wowza 的官方文件

如何檢查 FFmpeg 輸出的關鍵幀分佈是否正確?

推完流之後,想確認關鍵幀間隔有沒有照設定跑,可以用 `ffprobe` 直接看:

```bash

ffprobe -v quiet -show_streams -select_streams v:0 input.flv

```

抓出所有 I-frame(關鍵幀):

```bash

ffprobe -show_frames input.flv | grep pict_type | grep -n I

```

例如設定 24fps、關鍵幀間隔 10 秒(`-g 240`),理想狀況下輸出會是:

```

1:pict_type=I

241:pict_type=I

481:pict_type=I

721:pict_type=I

961:pict_type=I

1201:pict_type=I

```

每 240 幀出現一次 I-frame,跟 `-g 240` 的設定吻合。如果間隔亂掉,通常代表編碼器參數或串流服務端有重新協商過 GOP,值得回頭檢查 `-g`、`x264-params` 裡的 `keyint`/`min-keyint` 是否一致。

常見問題

Qcolorkey 去背邊緣有雜色殘留怎麼辦?

可以調整 `colorkey=0x00ff00:0.3:0.2` 裡的相似度(第二個數字)和模糊程度(第三個數字)。相似度太低會留下綠邊,太高則會吃掉主體邊緣的細節,通常要來回試個幾次才找到剛好的數值。

Q為什麼串流延遲還是很高?

先確認推流端有沒有用 `-tune:v zerolatency`、`-preset ultrafast`,播放端則檢查 `ffplay` 是否加了 `-fflags nobuffer -flags low_delay -rtmp_buffer 0`。中間如果經過額外的 CDN 或轉推服務,那段的緩衝設定也要一併確認,單邊調整不一定看得出效果。

Q`-g 240` 這個數字怎麼決定?

GOP size 通常抓 fps 乘上想要的關鍵幀間隔秒數。範例中 24fps、間隔 10 秒,`-g` 就設 240。間隔越短,隨機跳轉(seek)越流暢但檔案越大;直播場景通常抓 2-10 秒之間。

參考資料

FFmpeg 官方文件,Filters Documentation(`drawtext`、`colorkey`、`overlay` 等濾鏡參數說明),存取日期:2026-08-27。https://ffmpeg.org/ffmpeg-filters.html

延伸閱讀

關於作者 {#author}

Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。

首次發布:2023-08-23