ひさしぶりにProcessingネタ。“Between breeze and calm”制作でパフォーマンスの低さに悲しくなったので、最近アップデートされた動画生成ライブラリVideo Exportを試してみました。
Video ExportはFFmpegのラッパーなので別途FFmpegの準備が必要ですが、それさえできていれば利用は簡単です。こんな感じ:
- setupメソッドでインスタンス生成、VideoExport#startMovieメソッドを呼びだして初期化
- drawメソッドで描画終了後VideoExport#saveFrameメソッドを呼びだして保存
stopメソッドで動画用画像描画が終わったらVideoExport#endMovieメソッドを呼びだして後処理
VideoExport#startMovieメソッド呼びだしで次のようなエラーが報告されるかもしれませんが:
java.lang.RuntimeException: Waited 5000ms for: <5ce1e52a, 522610c6>[count 2, qsz 0, owner <main-FPSAWTAnimator#00-Timer0>] - <main-FPSAWTAnimator#00-Timer0-FPSAWTAnimator#00-Timer1> at processing.opengl.PSurfaceJOGL$2.run(PSurfaceJOGL.java:410) at java.lang.Thread.run(Thread.java:748)
これはFFmpegを見つけそこねているためなので、VideoExport#setFfmpegPathメソッドでパスを明示的に指定すると解消されます。いったん認識させるとライブラリのディレクトリに設定ファイルが保存されるので明示指定は不要になります。
肝心のパフォーマンスのほうはどうでしょうか。期待して https://www.youtube.com/watch?v=I_dAmbUC0AE で試してみると……たいして速度が出ません。640x360だとTGAで保存するのと同じくらい、50ミリ秒弱。80ミリ秒だの100ミリ秒以上だのかかるときもあって、24fpsでの動画生成には力不足というしかありません。期待はずれじゃん、なんで?と思ってソースコードを覗いてみると:
こんなコードが:
int byteNum = 0; for (final int px : img.pixels) { pixelsByte[byteNum++] = (byte) (px >> 16); pixelsByte[byteNum++] = (byte) (px >> 8); pixelsByte[byteNum++] = (byte) (px); }
……バイト操作の苦手な高ビットCPUの高水準言語でこんな愚直なコードを実行していては速度は期待できません。だからといってByteBufferクラスを利用すれば速くなるとも思えませんが……
そんなわけでリアルタイム動画生成にはあまり向きそうにありませんが、中間生成物なしで動画(それも標準でMP4)を作成できる点は用途によってはおおきなメリットでしょう。FFmpegの引数指定によって柔軟な動画生成も可能です。私には向きませんでしたが、使いかたによっては充分実用的なライブラリだと思います。
以上、Video Exportの日本語情報は見あたらないようなので、参考になりましたら幸いです。
2018-04-01(Sun)追記: 使いかたの記述をすこし修正しました。Processingのstopメソッドはアプレットベースの古いバージョンでのみ有効だということをすっかり忘れていました。
2021-08-10(Tue)追記: 類似ライブラリの"FrameRecord"を公開しました。