ffmpeg + Mathematicaで動画ファイルを作成する
MathematicaのExport
でAVIなどの動画ファイルを作成することは簡単に可能だが、
いかんせんすべてのフレームの画像を作成してからファイルに書きだすので、フレーム数に比例してメモリの使用量が多くなってしまう。
そのため長いムービーの作成は困難であった。
そこで、ffmpegと併用することでメモリ使用量を抑えつつ、長編の動画ファイルを制作する。 具体的には、
- ffmpegで標準入力から読み込ませる
OutputStream
オブジェクトを作成する BinaryWrite
でそのストリームに各フレームの画像を書き込む- 終わったら
Close
でストリームを閉じる
とする。ここで、各フレーム画像の形式をPPMにしないとうまく動作しなかった(BMP、PNGなどではなぜか動作せず)。
例えば、以下のようにするとtest001.aviができあがる。
s = OpenWrite[
"!ffmpeg -y -vcodec ppm -f image2pipe -i - -vcodec rawvideo test001.avi", BinaryFormat -> True];
Do[
BinaryWrite[s, ExportString[
Plot[Sin[x + i], {x, 0, 2 Pi}
, ImageSize -> {640, 480}
, PlotRange -> {{0, 2 Pi}, {-1, 1}}
, Frame -> True]
, "PPM"]]
, {i, 0, 2 Pi, Pi/50}
];
Close[s]
Export
と同じような使い勝手の関数ExportMovie
を作るとこんな感じになる。
Options[ExportMovie] = {
"FrameRate" -> 25,
"VideoCodecOption" -> "-vcodec rawvideo",
"ExportOptions" -> {}
};
ExportMovie[outputfilepath_String,
expr_, {i_Symbol, imin_: 1, imax_, di_: 1}, OptionsPattern[]] :=
Module[{stream},
stream = OpenWrite[
ToString[
StringForm[
"!ffmpeg -y -vcodec ppm -f image2pipe -i - -r `` `` ``"
, OptionValue["FrameRate"]
, OptionValue["VideoCodecOption"]
, outputfilepath
]
]
, BinaryFormat -> True];
Do[
BinaryWrite[stream,
ExportString[expr, "PPM", OptionValue["ExportOptions"]]]
, {i, imin, imax, di}
];
Close[stream]
];
Attributes[ExportMovie] = {HoldAll};
SyntaxInformation[ExportMovie] = {
"ArgumentsPattern" -> {_, _, {_, _, _., _.}, OptionsPattern[]}
, "LocalVariables" -> {"Table", {3, 3}}
};
使い方の例としては以下。反復子を使ってTable
などと同様の表記で動画が作成できる。
また、ffmpegでサポートされていれば、Mathematicaでサポートされていない形式でも動画が作成可能。
ExportMovie["test002.avi"
, Plot[Sin[x + i], {x, 0, 2 Pi}
, ImageSize -> {640, 480}
, PlotRange -> {{0, 2 Pi}, {-1, 1}}
, Frame -> True]
, {i, 0, 2 Pi, 2 Pi/100}
, "FrameRate" -> 29.97
, "VideoCodecOption" -> "-vcodec huffyuv"]