跳轉到內容

FFMPEG 中級指南/影像序列

來自華夏公益教科書

FFMPEG 具有強大的功能集,與從影像建立影片或從影片生成影像序列有關。

要從一組影像建立影片

 ffmpeg -i image-%03d.png video.webm

要從影片建立一組影像

 ffmpeg -i video.webm image-%03d.png

如果沒有給出更多引數,將使用一組預設值。例如,幀速率將為 25,編碼將從檔名推斷得出。

image-%03d.png 部分是一個檔名模式。此特定模式對應於 image-000.pngimage-001.pngimage-002.png,一直到 image-999.png。“%03d”表示三個零填充的十進位制數字的序列。關於檔名模式還有更多內容將在後面的部分中解釋。

使用影像序列工作的規範形式是使用 -f image2 引數,如下所示

 ffmpeg -f image2 -i image-%03d.png video.webm

 ffmpeg -i video.webm -f image2 image-%03d.png

但是 ffmpeg 在推斷這些資訊方面非常出色,因此本章將在所有示例中省略該引數,除非絕對必要。


從影像序列製作影片

[編輯 | 編輯原始碼]
 ffmpeg -i image-%03d.png video.webm

這將建立一個名為 video.webm 的影片,它來自名為 image-000.png、image-001.png、image-002.png 的影像檔案,一直到最後一個按順序編號的三位數影像檔案。

影像和影片的編碼是從副檔名推斷出的。預設幀速率為 25 fps。影片寬度和高度取自影像。影像必須都具有相同的尺寸。

檔名編號

[編輯 | 編輯原始碼]

Ffmpeg 預計編號從 0(在本例中為 000)開始。如果您的檔案沒有從 000 開始,請使用引數 -start_number 告訴 ffmpeg 您的檔案的第一個數字

 ffmpeg -start_number 100 -i image-%03d.png video.webm

同一個引數可以用來跳過一定數量的檔案並從某個數字開始。

編號必須是連續的。Ffmpeg 將在最後一個連續編號的檔名處停止。

例如,如果您有以下檔案

 image-000.png
 image-001.png
 image-002.png
 image-005.png

那麼 ffmpeg 只會處理前三個檔案,忽略最後一個檔案。如果您有缺失的編號,您可以使用 glob 模式 或將所有剩餘檔案重新命名以填補空白。

幀速率

[編輯 | 編輯原始碼]

預設幀速率為 25 fps。這意味著每張圖片顯示 1/25 秒。對於大多數人類的眼睛來說,這是一種速度,可以創造出流暢動畫的錯覺。如果您仍然希望每秒有更多幀,請使用 -framerate 引數

 ffmpeg -framerate 60 -i image-%03d.png video.webm

如果您想製作幻燈片,則必須降低輸入幀速率。以下命令將顯示每張圖片 5 秒長

 ffmpeg -framerate 1/5 -i image-%03d.png video.webm

可能需要強制提高影片幀速率

 ffmpeg -framerate 1/5 -i image-%03d.png -r 30 video.webm

具有不同持續時間的幻燈片

[編輯 | 編輯原始碼]

您可以使用 zoompan 過濾器製作每張圖片持續時間不同的幻燈片。在下面的示例中,每張圖片顯示 1 秒(25 幀),除了第 4 張圖片(列舉從 0 開始)顯示 3 秒(25+50 幀),第 6 張圖片顯示 5 秒(25+100 幀)。

 ffmpeg -i image-%3d.jpg -vf "zoompan=d=25+'50*eq(in,3)'+'100*eq(in,5)'" test.mp4

影像之間交叉淡入淡出的幻燈片

[編輯 | 編輯原始碼]

您可以使用 zoompan 和 framerate 過濾器的組合來製作影像之間交叉淡入淡出的幻燈片。“A”是每張圖片顯示多長時間(不包括交叉淡入淡出持續時間)的持續時間(以秒為單位),“B”是交叉淡入淡出持續時間(以秒為單位)。

*此示例完全錯誤,只包含前 3 張圖片*

ffmpeg -i IMG_%3d.jpg -vf zoompan=d=(A+B)/B:fps=1/B,framerate=25:interp_start=0:interp_end=255:scene=100 -c:v mpeg4 -maxrate 5M -q:v 2 out.mp4


建立 mp4[1]

ffmpeg -framerate 60 -r 60 -i image%06d.png -pix_fmt yuv420p -profile:v high -level:v 4.1 -crf:v 20 -movflags +faststart output.mp4
  • 對於 60 fps 以外的情況,更改幀速率和 r
  • 輸入為 image000001.png、image000002.png、...、%06d 表示一個帶有六位數字的零填充數字,如果您的輸入影像命名方式不同,請更改
  • -pix_fmt yuv420p 是大多數播放器相容所需的(預設值為 yuv444 甚至 rgb,大多數播放器根本無法很好地處理)
  • -profile:v、-level:v 也會控制相容性設定,4k 可能需要更高的級別設定
  • -crf:v 是質量與大小的控制,數字越小,質量越高,檔案大小越大,數字越大,質量越低,檔案大小越小,crf 20 的質量非常高,據我所知,每改變 6 個數字就會使檔案大小改變 2 倍
  • -movflags +faststart 是流式傳輸所需的(否則,整個檔案必須下載才能開始播放)
  • 如果您需要,ffmpeg 還可以新增/編碼音訊軌

從影片製作影像序列

[編輯 | 編輯原始碼]
 ffmpeg -i video.webm image-%03d.png

這將從 video.webm 檔案中每秒提取 25 張圖片,並將其儲存為 image-000.pngimage-001.pngimage-002.png,一直到 image-999.png。如果幀數超過 1000 幀,則最後一幀將被剩餘幀覆蓋,只保留最後一幀。

影像和影片的編碼是從副檔名推斷出的。預設幀速率為 25 fps。影像寬度和高度取自影片。

每秒提取一張圖片

 ffmpeg -i video.webm -vf fps=1 image-%03d.png

從特定時間提取一張圖片

 ffmpeg -i video.webm -ss 00:00:10 -vframes 1 thumbnail.png

檔名模式

[編輯 | 編輯原始碼]

通常 ffmpeg 只有一個輸入檔案和一個輸出檔案,但是當我們要從一組影像建立影片時,我們就有一組輸入檔案。同樣,當從影片檔案提取影像時,也會有一組輸出檔案。檔名模式是一個偽檔名,用於描述一組檔名。

檔名模式大致有三種類型

模式型別 對應的檔名 描述
image-%03d.png
 image-000.png
 image-001.png
 image-002.png
 ...
 image-999.png
帶前導零的編號
image-%d.png
 image-1.png
 image-2.png
 ...
 image-9.png
 image-10.png
 image-11.png
 ...
 image-99.png
 image-100.png
 ...
不帶前導零的編號
image-*.png

(需要一個引數來啟用)

 image-a.png
 image-b.png
 image-c.png
 ...
 image-foo.png
 image-bar.png
 ...
 image-.png
 ...
未編號或無規律模式

從技術上講,還有第四種形式:單個影像形式。但這只是一個簡單的特殊情況,在本節中將不再討論。

帶前導零的編號

[編輯 | 編輯原始碼]

此模式

 image-%03d.png

對應於以下檔名

 image-000.png
 image-001.png
 image-002.png
 ...
 image-999.png

換句話說:字串 image- 後面跟著三位數字,後面跟著字串 .png

檔名擴充套件機制的核心是字元 % 開始並以字元 d 結束的子字串。% 之前的部分和 d 之後的部分被逐字接收。%d 之間的所有內容都將被替換為一個或多個數字。

一般形式為 %0Nd,其中 N 是一個大於零的數字,用於確定數字的數量。

注意:%0Nd 符號在許多程式語言中很常見。該符號之所以複雜是因為它被設計用來適應許多不同的用例。FFmpeg 開發者借用了這個符號並將其簡化為一個用例:數字位數。因此,它可能顯得過於複雜。

檔名中的百分號

[編輯 | 編輯原始碼]

如果檔名本身包含 % 字元,則存在一個特殊情況。因為 % 字元在模式中具有特殊含義,因此需要小心。模式中的單個 % 字元將被解釋為要由數字替換的子字串的開頭。要指定文字 %,必須在模式中將其加倍。這在技術術語中稱為“轉義”字元。

例如,這個模式

 image-%02d%%.png

對應於以下檔名

 image-00%.png
 image-01%.png
 image-02%.png
 ...
 image-99%.png

不帶前導零的編號

[編輯 | 編輯原始碼]

如果檔名中的數字沒有用前導零填充,則模式為 %d

此模式

 image-%d.png

對應於以下檔名

 image-1.png
 image-2.png
 ...
 image-9.png
 image-10.png
 image-11.png
 ...
 image-99.png
 image-100.png
 ...

未編號或無規律模式

[編輯 | 編輯原始碼]

如果檔名沒有使用數字編號或沒有以其他方式定期格式化,則可以使用 glob 模式。glob 模式必須使用引數 -pattern_type glob 啟用。請注意,這在 Windows 上不受支援。

帶有 glob 模式啟用的示例 ffmpeg 命令

 ffmpeg -pattern_type glob -i "image-*.png" video.webm

此模式

  "image-*.png"

對應於以下檔名

 image-a.png
 image-b.png
 image-c.png

但也適用於以下檔名

 image-foo.png
 image-bar.png

也適用於

 image-.png

以及任何以字串 image- 開頭、後面跟著任何內容、最後以字串 .png 結尾的檔名。

一般來說,模式 * 對應於任何長度的任何內容,這意味著即使是空字串也是如此。

還有更多 glob 模式。例如,? 對應於任何單個字元。但我們這裡不會深入探討。感興趣的讀者可以在維基百科關於 glob (程式設計) 的頁面中找到更深入的資訊。

引用 glob 模式

[編輯 | 編輯原始碼]

將 glob 模式放在引號中是必要的,否則 shell 會在執行命令之前擴充套件 glob。

例如,此命令中的 glob 模式

 ffmpeg -pattern_type glob -i image-*.png video.webm

將由 shell 擴充套件為

 ffmpeg -pattern_type glob -i image-foo.png image-bar.png video.webm

然後才執行。請注意,此命令具有不同的含義,因為現在 image-bar.png 是第二個檔名引數,而 video.webm 是第三個檔名引數。

當放在引號中時,shell 不會擴充套件 glob 模式

 ffmpeg -pattern_type glob -i "image-*.png" video.webm

來自 glob 模式的檔案順序

[編輯 | 編輯原始碼]

編號檔案具有明確定義的排序方式。在大多數情況下,人和計算機都一致同意如何對數字進行排序。對於帶有前導零的數字尤其如此。015 顯然比 110 先。沒有前導零會變得更加複雜。大多數計算機將 15 排在 110 之後。但這個問題可以透過 %d 符號解決。

當檔案不再使用數字編號或沒有定期編號時,事情會變得非常奇怪。例如,ae 應該排在 aaa 之前還是之後?計算機是確定性的,並且總是對如何排序事物有一個概念,但這種排序概念對於人類來說不一定有意義。

來自 glob 模式的檔案順序由 glob 系統呼叫決定。在大多數系統上,可以透過名為 LC_COLLATE 的環境變數來操作 glob 系統呼叫的排序概念。但這本書不會討論這一點。

對於少量檔案,可以透過讓 shell 擴充套件 glob 來檢查 glob 返回的順序。這是因為大多數 shell 使用與 ffmpeg 相同的 glob 系統呼叫。

在 shell 中鍵入此命令

 echo image-*.png

將列印一個檔名列表。相同順序的相同列表將是 ffmpeg 處理的檔案列表,如果給定 glob 模式。

如果順序不令人滿意或數量過大,無法讓人類檢查,則最好的解決方法是將檔案重新命名為定期編號,然後使用 %0Nd 模式。

位於以下位置的精美 ffmpeg 手冊和維基

更具體地說,以下頁面

  1. fractalforums.org : 建立影片
華夏公益教科書