Coding4Fun - 將影片每一秒畫面匯出成圖檔
|
|
|
0 |
|
下面這張圖是我這次要做的事。

把影片每一秒畫面轉成圖檔,可以玩出好玩應用。例如,傳奇作品如甄嬛傳、少林足球、九品芝麻官,幕幕皆經典,幀幀能當梗,抓畫面可以做梗圖,像是甄嬛梗圖機器人背後就有 11,500 張照片作為圖庫。

另外,將影片轉成圖片後,可寫程式做靜態影像處理。甚至反過來,處理完再將圖片還原成影片,發展更多花式應用。
至於要將影片特定時點畫面另存圖片,我第一個想到的是強大的萬用開源工具 - FFmpeg,但如要批次處理加入客製邏輯,還是寫程式比較方便。
我查到一個好用的 .NET 程式庫 - Xabe.FFmpeg,基本上只是個 FFmpeg 的 Wrapper,方便以 .NET 函式 API 取代執行檔參數操作 FFmpeg。呼叫 API 傳入參數會轉為 FFmpeg 參數啟動 ffmpeg 執行檔,以外部程序執行。Xabe.FFmpeg 程式庫開源,非商業使用免費。
Xabe.FFmpeg 的 API 挺直覺好寫,本次要用的擷圖功能,核心是使用 ExtractEveryNthFrame() 函式,它能每隔 N 個 Frame 儲存一張 .png,若影片 FrameRate 為 24,每隔 24 幀存一次便相當於每秒存一張。Start() 後必須等外部程序的 ffmpeg 跑完,中間如想知道進度可實作 OnProgress 事件,顯示目前播放時間、總長度及播放比例。
這段將每秒畫面另存 .png 的程式碼很短也很簡單,應不需要大多解釋。
using System.Runtime.CompilerServices;
using Xabe.FFmpeg;
var mediaInfo = await FFmpeg.GetMediaInfo("English.webm");
/* 將聲音轉 MP3
var audioStream = mediaInfo.AudioStreams.FirstOrDefault();
var result = await FFmpeg.Conversions.New()
.AddStream(audioStream)
.SetOutput("extracted_audio.mp3")
.Start();
*/
const string outputFolder = "snapshots";
if (Directory.Exists(outputFolder)) Directory.Delete(outputFolder, true);
Directory.CreateDirectory(outputFolder);
var videoStream = mediaInfo.VideoStreams.FirstOrDefault()?.SetCodec(VideoCodec.png)!;
// 取得幀率
int framesPerSecond = (int)Math.Round(videoStream.Framerate);
Console.WriteLine($"Frames per second: {framesPerSecond}");
// 每隔每秒幀數存一張影像,等於一秒一張
var conversion = FFmpeg.Conversions.New()
.AddStream(videoStream)
.ExtractEveryNthFrame(framesPerSecond, (number) => Path.Combine(outputFolder, $"F_{number:000000}.png"));
// 取得進度資訊
conversion.OnProgress += (sender, args) =>
{
Console.Write($"\r[{args.Duration}/{args.TotalLength}] {args.Percent}% ");
};
await conversion.Start();
Console.WriteLine("\n匯出完成");
// 更名檔案將秒數轉為時分秒
foreach (var file in Directory.GetFiles(outputFolder, "F_*.png"))
{
var secs = int.Parse(Path.GetFileNameWithoutExtension(file).Split('_').Last());
TimeSpan time = TimeSpan.FromSeconds(secs);
string newFilePath = Path.Combine(outputFolder, $"{time.Hours:D2}_{time.Minutes:D2}_{time.Seconds:D2}#{secs:0000}.png");
File.Move(file, newFilePath);
}

另外,FFmpeg 處理過程是多工平行運算,我的 i5 CPU 難得一見火力全開。

搞了很久的智慧插座監測這回也派上用場,由圖表可知我的迷你工作機全速運轉的耗電量是 100W。

就醬,我們就能將影片轉成圖片,搞一些有趣的應用囉~
Demonstrates how to extract video frames as images using Xabe.FFmpeg for meme creation and image processing in .NET.
Comments
Be the first to post a comment