しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

C# と FFmpeg を使って動画のサムネイルを生成してみた

ちょっと前になりますが WPF を使って動画のサムネイルを生成してみた - しばやん雑記 で書いた通り WPF を使って動画のサムネイルを自動的に生成するコードを書いてみたのですが、これが Azure Web サイト上で動いてくれなくて困りました。

やはりサーバー OS はクライアント OS とは勝手が違ってきますね。なので、今回は有名な FFmpeg を使ってサムネイルを生成してみることにします。

https://www.ffmpeg.org/download.html

FFmpeg はクロスプラットフォームですが、Windows 版はビルド済みなものが公式サイトからは配布されていないので "Zeranoe FFmpeg Builds." というものを使いました。

Zeranoe FFmpeg - Builds

f:id:shiba-yan:20140707223124p:plain

色んな種類がありますが、今回は 32bit 版の Static ビルドを使いました。このバイナリは実行に必要な様々なライブラリがスタティックリンクされているバージョンで、Azure Web サイトなどのサーバー上で実行するには非常におあつらえ向きです。

f:id:shiba-yan:20140707223738p:plain

ダウンロードした 7z を展開して、bin フォルダまで辿ると 3 つ実行ファイルがありますが、必要なのは ffmpeg.exe だけになります。

この段階で一度 ffmpeg.exe を使って動画のサムネイルを作成するコマンドを叩いておきます。

ffmpeg.exe -ss 20 -i claudia.mp4 -vframes 1 -f image2 claudia.jpg

パラメータを簡単に説明すると -i は入力ファイルのパス、-ss は秒数、-vframes は切り出すフレーム数、そして -f image2 は画像として保存するオプションになります。

なので、実際に先ほどのコマンドを実行すると以下のような画像が出力されます。

f:id:shiba-yan:20140707225857j:plain

とてもいいシーンを切り出すことが出来ましたね。

とまあ、コマンドを叩けば FFmpeg がとても良い感じに出力してくれるので、今回は C# から ffmpeg.exe を実行するコードを書くだけです。

var input = "claudia.mp4";
var output = "claudia.jpg";

var seek = 20;

var arguments = string.Format("-ss {1} -i \"{0}\" -vframes 1 -f image2 \"{2}\"", input, seek, output);

var process = Process.Start(new ProcessStartInfo("ffmpeg.exe", arguments)
{
    CreateNoWindow = true,
    UseShellExecute = false,
});

process.WaitForExit();

単純にさっきのコマンドを C# の Process クラス使って書き直しただけです。Stream 使いたいですがファイルでやり取りしないといけないのが、やはりちょっとめんどくさいところですね。

f:id:shiba-yan:20140707231527p:plain

当初の目的であった Azure Web サイト上での動作も FFmpeg が各種デコーダーなどを内蔵しているからか問題ありませんでした。

サーバー上で動画のサムネイルを作成する機会はあまりないと思いますが、参考までに。

追記

Twitter で ffmpeg.exe に渡すパラメータの順番を変えることで、無駄にデコードをせずに高速に処理できると教えてもらいました。ありがとうございます。

テストしてみたところ確かに高速にサムネイルを切り出せました。なので、本文中のパラメータを修正しておきました。