要用 FFmpeg 從影片中擷取畫格,你只需要執行一道指令,指定輸入檔案、用時間參數或視訊濾鏡挑選要取用的畫格,並把每張圖片寫入一個有編號的輸出檔名;每秒一格這種常見模式的標準寫法是 ffmpeg -i input.mp4 -vf fps=1 frame_%04d.png,而在指定時間點擷取單一靜態畫面的寫法則是 ffmpeg -i input.mp4 -ss 00:00:05 -frames:v 1 output.png。FFmpeg 會讀取來源容器格式、解碼出符合條件的畫格,並依照輸出副檔名所代表的格式儲存每一張圖片,最常見的是 PNG、JPG 或 BMP。除非在處理鏈中加入縮放濾鏡,否則解碼出來的畫格會保留來源的像素尺寸;而時間戳記則會對應到最接近、可解碼的畫格,因為 FFmpeg 是定位到關鍵畫格,而不是精確的封包位置。這個「定位到關鍵畫格,再加上可選的畫格挑選」的單一行為,正是本指南每一種變化寫法的基礎,文章接下來會逐一說明四種最實用的模式、需要留意的限制,以及一個不需安裝、適合單張 PNG 的瀏覽器替代方案。

擷取畫格的常見 FFmpeg 指令
FFmpeg 的畫格擷取指令共用同一種結構:一個輸入旗標、一個用來挑選要解碼哪些畫格的可選定位或濾鏡,以及一個為每張圖片命名的輸出模式。下面四種模式涵蓋了大多數讀者會需要的情況,而且依你選擇的副檔名,每一種都會寫出有效的 PNG、JPG 或 BMP。
| 目標 | FFmpeg 指令 | 輸出結果 |
|---|---|---|
| 在已知時間點取出一張靜態畫面 | ffmpeg -i input.mp4 -ss 00:00:12.5 -frames:v 1 output.png | 寫出一張尺寸與解碼畫格相同的 PNG |
| 每秒擷取一格 | ffmpeg -i input.mp4 -vf fps=1 frame_%04d.png | 依序寫出 frame_0001.png、frame_0002.png,以此類推 |
| 擷取一段時間範圍 | ffmpeg -ss 00:00:10 -i input.mp4 -t 5 -vf fps=2 range_%03d.png | 寫出十張 PNG,檔名從 range_001.png 到 range_010.png |
| 每隔 N 個來源畫格儲存一張 | ffmpeg -i input.mp4 -vf "select='not(mod(n,30))'" -vsync 0 frame_%04d.png | 依來源畫格計數器,每 30 格寫出一張 |
fps 濾鏡與 select 濾鏡承擔了大部分的核心工作。fps=1 會把時間軸重新取樣為每秒一格,而 select='not(mod(n,30))' 則利用來源畫格計數器,只保留每第 30 格、捨棄其餘畫格。-frames:v 1 這個旗標是最簡單的單張靜態畫面捷徑,它會告訴 FFmpeg 在寫出第一個解碼出來的視訊畫格之後就停止,這正是單張靜態畫面指令能如此精簡的原因。放在 -i 之前的 -ss 旗標,會執行輸入端定位,在處理大檔案時速度較快;而放在 -i 之後的同一個旗標,則會執行更精確的輸出端定位。對大多數畫格擷取任務而言,輸入前定位的精確度已經足夠,並且能在長片段上節省時間。
如果需要更細緻的控制,你可以串接多個濾鏡。像 ffmpeg -i input.mp4 -vf "fps=1,scale=1280:-1" frame_%04d.png 這樣的指令,會重新取樣為每秒一格,並透過 -1 這個佔位符,在保持長寬比的同時,把每一格縮放到寬度 1280 像素。當你需要縮圖或較小的參考靜態畫面、又不想另外寫一個縮放步驟時,這種寫法很有用。
挑選正確的秒數時間點
FFmpeg 接受三種時間格式:整數或小數秒(12、12.5)、hh:mm:ss 形式(00:00:12.500),以及在支援的建置版本上可用的毫秒變體。對單張畫格擷取而言,小數秒是最容易閱讀的形式,因為你可以寫 -ss 12.5,而不必寫 -ss 00:00:12.500,結果是一樣的。
-ss 的位置會稍微改變它的意義。放在 -i 之前時,它是一次快速的輸入端定位,會跳到請求時間點之前或恰好在該點的最近一個關鍵畫格,然後向前解碼——速度快,但可能會落在目標點附近的幾格之內,而不是精確落點。放在 -i 之後時,它是一次精確的輸出端定位,會從解碼串流的起點掃描到請求的時間點——速度較慢,但落點更接近你選擇的那一刻。對於使用 fps=1 的批次擷取來說,這個差異通常看不出來,因為範圍內的每一格都會被寫出;但對於單一的 -frames:v 1 靜態畫面而言,這個差異可能意味著你到底拿到的是你想要的那一格,還是前一個關鍵畫格。
如果你還在決定該輸入哪一個時間戳記,關於picking the right time when extracting frames 的指南,說明了如何先在播放器中拖動影片、從拖動軸讀出時間戳記,好讓 FFmpeg 的 -ss 值,對應到你在畫面上實際看到的那一格。
如何在瀏覽器中擷取單張 PNG 畫格
如果你只需要從一段短片中取出一張靜態畫面,又不想安裝 FFmpeg 或開啟終端機,Video Frame Extractor 能在目前的分頁中完成同樣的工作。瀏覽器會解碼本機檔案,定位到你輸入的時間點,把解碼出來的畫格繪製到 canvas 上,再編碼成一張 PNG 供你下載。任何內容都不會離開你的機器,當這段影片是私人或有工作限制的內容時,這一點就很重要。
- 選擇一個支援的本機影片(MP4、WebM、MOV、M4V 或 Ogg),並等待其時長與預覽載入完成。
- 在零與顯示的總時長之間輸入一個畫格時間,當畫格落在整數秒之間時使用小數(例如,12.5 代表第十二點五秒那一格)。
- 選擇 Extract PNG frame,確認預覽中顯示的靜態畫面與你想要的那一刻相符,再下載工具在本機儲存的 PNG。
這張 PNG 的檔名會包含你輸入的時間,因此請求 12.5 秒會在你的下載資料夾中產生類似 frame-12.500.png 的檔案。因為這個工具是以解碼出來的尺寸繪製畫格,這張圖片的寬與高會和來源片段相同;過程中不會有任何縮放、裁切、銳化或濾鏡處理。透明度只有在編解碼器解碼出來的畫格本身就包含它時才會被保留,對一般的 MP4 與 MOV 檔案來說很少見,但對使用 alpha 通道的 WebM 來源檔案來說是可能的。
瀏覽器端的擷取,和 FFmpeg 一樣有相同的精確度但書:你要求的時間是媒體時間軸上的一個位置,而不是保證命中確切來源畫格的承諾。由於關鍵畫格、可變畫格率、剪輯清單與編解碼器四捨五入的緣故,瀏覽器可能會落在附近某個已解碼的畫格上,因此你拿到的可能是鄰近的解碼畫格,而不是你原本想要的那一格。對縮圖、參考圖或簡報用的靜態畫面來說,這樣已經足夠,而 Video Frame Extractor 頁面本身也建議,如果你需要畫格精確的剪輯工作,請改用專門的桌面工具。
這個流程背後的機制,記載於 MDN 的HTMLMediaElement currentTime 與Canvas drawImage 頁面中,這正是這個工具用來定位到選定時間戳記、並在編碼成 PNG 之前,把解碼出來的畫格複製進 canvas 的同一組瀏覽器 API。
影響畫格擷取的限制與編解碼器但書
FFmpeg 會很樂意嘗試開啟幾乎任何它編譯時支援的容器或編解碼器,這正是為什麼在遇到像 MKV、AVI、ProRes 或 DNxHR 這類不常見格式時,它是預設的首選工具。以瀏覽器為基礎的工具則窄得多:Video Frame Extractor 只能處理瀏覽器能解碼的 MP4、WebM、MOV、M4V 與 Ogg 檔案,即使副檔名看起來熟悉,也不保證容器內部的編解碼器受支援。一個內含 H.264 視訊的 MP4 通常能開啟;而一個內含 ProRes 或 HEVC、又沒有硬體解碼器的 MP4,在瀏覽器上則無法開啟。
| 限制 | FFmpeg | Video Frame Extractor |
|---|---|---|
| 容器支援 | 任何 FFmpeg 編譯時支援的格式,包括 MKV、AVI、ProRes、MOV | 瀏覽器編解碼器堆疊能解碼的 MP4、WebM、MOV、M4V、Ogg |
| 檔案大小上限 | 由你的磁碟與記憶體決定 | 500 MiB |
| 時長上限 | 由你的磁碟與記憶體決定 | 5 分鐘 |
| 每邊像素上限 | 命令列沒有限制 | 4096 像素 |
| 解析度上限 | 命令列沒有限制 | 3840 × 2160 |
| 處理位置 | 你機器上的本機執行檔 | 本機瀏覽器分頁,不上傳 |
| 輸出格式選項 | PNG、JPG、BMP、TIFF、RAW 等多種格式 | 僅限 PNG |
瀏覽器工具共用的影片安全政策,把上限設在 500 MiB 與五分鐘,目的是讓分頁保持回應;一旦檔案超過這些限制,把大型畫格解碼進 canvas 會阻塞主執行緒,分頁可能因此卡住。FFmpeg 沒有這樣的防護機制,這也是為什麼在處理長片段、大型 4K 母帶,以及不常見的編解碼器組合時,它仍然是正確選擇;而對於一段你想避免經過伺服器、時長在五分鐘以內的單一片段,瀏覽器工具則是正確選擇。
該用 FFmpeg 還是瀏覽器工具
這個決定通常取決於三個問題:你需要多少張畫格、來源片段有多長,以及這個檔案是否已經能在你的瀏覽器中開啟。如果你需要從一段長片段中取得數百甚至數千張畫格,FFmpeg 是明智的選擇,因為命令列能自動擴展、不需要手動操作,fps 濾鏡也會替你處理節奏。如果你只需要從一段五分鐘以內、已經能在瀏覽器中開啟的片段取出一張靜態畫面,Video Frame Extractor 能省下安裝步驟與命令列語法。
還有一種中間情況:你手上有一個長檔案,但只想在一個已知時間點取出單一張靜態畫面。對這種情況,你可以在 -i 之前使用 -ss,搭配 -frames:v 1,在寫出第一張圖片後就停止執行 FFmpeg,這大致上與開啟瀏覽器工具、跳過上傳步驟所需的工作量相當。差別在於,FFmpeg 版本會使用你機器的 CPU 與磁碟運算,不依賴瀏覽器是否能解碼該檔案;而瀏覽器版本除了最終那張 PNG 之外,完全不會碰觸你的磁碟。
一個實用的經驗法則:當編解碼器不常見、片段很長,或你需要一次取得許多畫格時,用 FFmpeg;當你想從一段你已經確定瀏覽器能播放的短片段中,快速取得一張 PNG 時,用瀏覽器工具。
輸出畫質、格式與透明度
當這張靜態畫面之後會被編輯、疊加到投影片上,或與另一張圖片合成時,PNG 是正確的格式選擇,因為 PNG 是無損的,並支援 alpha 通道。當這張靜態畫面要放進文件或網頁,而檔案大小比無損畫質更重要時,JPG 是正確的選擇。BMP 在今天很少是正確的選擇,但 FFmpeg 仍支援它作為輸出副檔名,以相容舊有的流程。
輸出結果的像素尺寸,會與解碼出來的畫格一致。除非你加入縮放或裁切濾鏡,否則 FFmpeg 不會調整畫格的大小、裁切或做濾鏡處理;瀏覽器工具也明確不會做縮放、裁切、銳化、內插,或套用濾鏡。如果你需要較小的版本,FFmpeg 的 -vf "scale=W:-1" 串接寫法,是一次到位完成的最乾淨做法。
透明度是唯一比較微妙的情況。PNG 支援 alpha 通道,但解碼出來的畫格只有在來源編解碼器本身有產生 alpha 資訊時才會帶有它;MP4 中的 H.264 視訊幾乎從不會有,而搭配 alpha 軌道的 VP8 或 VP9 WebM 則會有。這個瀏覽器工具只有在解碼出來的畫格本身包含透明度時,才會保留它。
排解擷取失敗的問題
下載結果為空,或解碼失敗,通常只有少數幾種常見原因。在 FFmpeg 中,「Invalid data found when processing input」這個錯誤通常代表容器格式能被辨識,但內部的編解碼器不受支援,解法是安裝或啟用該編解碼器,或用像 VLC 這樣的工具重新封裝該檔案。在瀏覽器工具中,同樣的情況會呈現為一個解碼錯誤,而不是一份空白的 PNG,解法是在重試之前,先用瀏覽器支援的編解碼器——例如 MP4 用 H.264、WebM 用 VP9——重新編碼這段片段。
如果取出的靜態畫面落在錯誤的畫格上,兩種工具的解法相同:為時間值加上一點小偏移,或先在播放器中拖動影片,找出最接近你想要那一格的整秒或半秒標記點。FFmpeg 的 -noaccurate_seek 旗標,以及瀏覽器顯示出你請求的時間,兩者都在提示解碼出來的位置只是近似值;基於同樣的原因,瀏覽器工具內部使用的八組時間測試樣本,涵蓋了起始點、毫秒值、小數秒、一般整秒、類似畫格率的小數、一分鐘,以及最大時長邊界。
超過瀏覽器工具 500 MiB 或五分鐘限制的檔案,會在開始解碼之前就被拒絕,這正是我們想要的行為,因為一個因為 10 GB 檔案而卡死的分頁,比一則清楚的錯誤訊息更糟。遇到這類情況時,解法是先用像 Video Trimmer 或 Video Resizer 這樣的工具,把來源檔案裁剪或縮小之後再擷取畫格,或者改用 FFmpeg,因為它沒有同樣的限制。
相關閱讀:Extract Audio from Video Explained: How It Works Locally。