在整理想要發布的影片時,你是否曾發現精采的畫面想要作為封面,卻總是被媒體播放器的框架或元素干擾,影響了截圖的整體美感和清晰度呢?別擔心!我們現在能夠快速且精確地擷取畫面,獲得完全乾淨的高品質截圖!
素材取用
影片:雲端下載 <影片來源 – Bad Apple by あにら | ニコニコ >
字幕:雲端下載
- 完成本篇教學將會使用 629 MB 之檔案空間
實作過程
時間定位 Seeking
正如其名,定位的概念則是在指定的時間位置進行單時間戳的截圖,且是當下秒數的開端,並無法取得到畫格在毫秒間的微小變動。此時根據參數 -ss HH:MM:SS 的擺放位置,我們可以分為兩種模式。
Input Seeking
首先我們使用的是極為高速的 Input Seeking,其概念是從頭透過關鍵幀 (Keyframe) 向後推到指定時間。觸發條件是 -ss 需要在 -i 之前,而我們在 49 秒時裁切一張圖片並輸出。
ffmpeg -ss 00:00:49 -i ./test.mp4 -frames:v 1 "screenshot_inputseeking.png"
Output Seeking
Output Seeking 則相對是放在 -i 的後方。雖然在我們的測試上可能不明顯,但由於其運作方式是從開頭 解譯 向後尋找,所以需要更多的時間處理圖片資訊,但透過這方式可以獲得更精準的切片。
ffmpeg -i ./test.mp4 -ss 00:00:49 -frames:v 1 "screenshot_outputseeking.png"
然而,隨著 FFmpeg 技術的不斷進步和改進,Input Seeking 和 Output Seeking 這兩種方式之間的實際效能差異已經逐漸縮小。在大多數日常使用情境下,Input Seeking 的功能和效率都已經相當充足,能夠滿足一般使用的需求。


不過,在某些特殊的使用場景中,特別是當影片附帶外部字幕檔案時,可能會遇到字幕時間軸無法完全對齊,甚至出現字幕消失的問題。
ffmpeg -ss 00:00:49 -i ./test.mp4 -vf subtitles=test.srt -frames:v 1 "screenshot_inputseeking_sub.png"
ffmpeg -i ./test.mp4 -ss 00:00:49 -vf subtitles=test.srt -frames:v 1 "screenshot_outputseeking_sub.png"


選取規則 Select Rules
接著我們進階到 -vf (Video Filter) 之中的 select 表示式,坦白說要記上所有的語法擁有相對的難度,我們就簡略看看,此處範例透過時間的範圍限制與影格位置,讀取前 10 秒每 30 格擷取一次。有需要者可以到 參考 [6] 詳細參閱官方範例。
if not exist frames_on_f30_in_10s mkdir frames_on_f30_in_10s
ffmpeg -i test.mp4 -vf "select='between(t\,0\,9)*eq(mod(n\,30)\,0)'" -vsync vfr frames_on_f30_in_10s/output_%%04d.png
pause

特色判斷 Thumbnail
這套工具包天然帶有一個方式,可以自動幫你篩選整部影片的精彩片段,或者是每個區間的代表圖像。如果不想人工審核的可以嘗試,但可能不合每個人的獨特口味。
如果我們今天偷懶,讓他直接蒐尋整個影片。大多數情況其實結果都不盡人意。比如下方的畫格甚至還是開端,而且其實連哪個角色都還沒顯現出來。
ffmpeg -i ./test.mp4 -vf thumbnail,scale=480:360 -frames:v 1 thumbnail_%%04d.png

接者我們嘗試看看每 300 格 (10 秒) 尋找一次,而方法很簡單,只要在 thumbnail 後方加上 =X 就可以了,等同於每多少格取一次。但這邊我們必須套用剛剛在 select 沒有特別講解的 -vsync vfr 來跳過無需處理的影格,否則你的資料夾還是會有六千多張照片。
if not exist thumbnails_every_10s mkdir thumbnails_every_10s
ffmpeg -i ./test.mp4 -vf thumbnail=300,scale=480:360 -vsync vfr thumbnails_every_10s/thumbnail_%%04d.png
pause

頻率擷取 Frame Extraction by Rate
就像先前講過,如過能夠將影片畫格切出,完全可以壯大我們的圖片資料庫。那除了先前幾個指定時間或少量圖片的情況,我們這次則是透過每秒幾張的方式處理整個影片。
兩種參數
if not exist frames_by_r1 mkdir frames_by_r1
ffmpeg -i ./test.mp4 -r 1 ./frames_by_1/output_%%04d.png
pause
我們首先嘗試如果我們用 -r 1 這個方式,以每秒一張的速率擷取。完成時我們資料夾內應該會有 221 張照片,但稍微回想一下,有沒有發現什麼事情怪怪的?
沒錯!我們的影片明明就有 03:39 等同於 219 秒,怎麼少了幾張?這是因為在處理過程中,-r 這個方法會在編譯的動作之前發生,並且為了適應固定速率 (Constant Frame Rate, CFR), 可能導致影格的減少或增多。因此嚴謹的方式,我們需要透過 -vf "fps=X" 來做指定,才能獲取到完整的格數。
if not exist frames_by_fps1 mkdir frames_by_fps1
ffmpeg -i ./test.mp4 -vf "fps=1" ./frames_by_fps1/output_%%04d.png
pause
接者根據我們之前的檢查,我們的範例影片只有 30 FPS,如果這時故意超出這個範圍使用 60 FPS 將會如何呢?我們首先要想到他們的原理都來自關鍵幀。
if not exist frames_by_fps60 mkdir frames_by_fps60
ffmpeg -i ./test.mp4 -vf "fps=60" ./frames_by_fps60/output_%%04d.png
pause
所以這個時候呢,我們每個畫格會拿到整整 2 張一模一樣的圖樣。關於這點證明說上述方法並不會自動去推算物體的變化。但是我們可以追加一個功能,讓 FFmpeg 試著進行動態偵測,去預估圖片間的落點。
動態推算 Motion Interpolation
想當然,這次還要加上影格的運算時間,肯定超級無敵久,這邊各位看著我做就好,或者睡覺時掛機體驗看看也行。關於模式的操作文件,在文末也有紀錄在參考 [5] 之中,有興趣能看看其他的運算模式。
if not exist frames_by_fps60_mi mkdir frames_by_fps60_mi
ffmpeg -i ./test.mp4 -vf "minterpolate='mi_mode=mci:mc_mode=aobmc:me_mode=bidir:fps=60'" ./frames_by_fps60_mi/output_%%04d.png
pause

(1253 跟 54 相同)

(1254 稍微移動)
知曉這項功能,我們如果有需要的話完全可以用它來提高影片流暢度。但代價就是,如果變化距離過大時,可能會有誤判的情境,或者產生扭曲的狀態。
後話
在擁有畫面截圖的情況下,我們可以運用這些影像資源來達成各種不同的目標。這些截圖不僅可以透過人工篩選的方式來豐富我們的資料庫,更可以用來製作影片預覽封面。透過精心挑選的畫面,我們能夠更好地展現影片的核心內容,由此提高影片的統整性或吸引力。
但理所當然,還需要個魔法讓我們將封面套用到影片檔上。
參考
[1] Create a thumbnail image every X seconds of the video — FFmpeg Bug Tracker and Wiki
https://trac.ffmpeg.org/wiki/Create%20a%20thumbnail%20image%20every%20X%20seconds%20of%20the%20video
[2] Seeking — FFmpeg Bug Tracker and Wiki
https://trac.ffmpeg.org/wiki/Seeking
[3] Subtitle — FFmpeg Bug Tracker and Wiki
https://trac.ffmpeg.org/wiki/HowToBurnSubtitlesIntoVideo
[4] Changing Frame Rate — FFmpeg Bug Tracker and Wiki
https://trac.ffmpeg.org/wiki/ChangingFrameRate
[5] Motion Interpolation — FFmpeg
https://ffmpeg.org/ffmpeg-all.html#minterpolate
[6] Select — FFmpeg
https://ffmpeg.org/ffmpeg-filters.html#select_002c-aselect