ActionScript のみで作った SWF をコマ落ちせずに動画にする手法

世の中には SWF を動画に変換するツールがいくつかある。

これらのツールは、SWF を再生しておいて、次々と画面をキャプチャしていって、最後に動画に変換する、というものがほとんどのようだ。変換の再現性は高い一方、どうしてもコマ落ちが発生してしまう。

これではちょっと悲しいので、ActionScript のみで作成した SWF に限って使えるコマ落ちせずに動画に変換するテクニックを解説する。前提条件は、ソースコードが手元にあり、Flash IDE を利用していないこと、ActionScript の知識があること。

wonderfl の作品を動画にする、と説明するとイメージが沸きやすいかもしれない。

enterFrame だけで描画するパターン

比較的簡単に変換できるのが、enterFrame イベントが発生するごとに描画するパターンのときである。

変換例

試しに、過去に wonderfl に投稿した キラキラ3D Typography を動画に変換してみた。

ソースコードについて

ソースは https://gist.github.com/3885010 に上げている。

肝は PngOutput という自作クラスだ。enterFrame のイベントごとに、PngOutput.output() メソッドを呼んで、表示している内容を png ファイルで書き出している。

    // ループ処理
    PngOutput.init(stage);
    addEventListener("enterFrame", function(event:Event):void{
        // ここで描画処理をしている

        PngOutput.output();
        counter++;
        if (counter % 120 == 0) { f = !f; }
    });

画像のサイズは stage のサイズを利用しているので、SWF メタタグやコンパイルオプションでサイズを指定できる。

ファイルを扱うために、AIR アプリとして実行している。amxmlc でビルドして、adl app.xml で画像出力を開始してくれるようになっている。出力先のパスは PngOutput クラスに直接書いてあるので、適切に変更して利用してほしい。

よくあるキャプチャして動画にするツールとは違って、コマ落ちは発生しない。というのも、1 フレームずつ、順番に「描画+画像に変換」を実行しているからだ。変換中は、ゆっくり 1 フレームずつ再生しながら画像出力しているが、できあがった画像をつなぎ合わせればコマ落ちが発生しない動画になっている。ソースコードが手中にあるからこそできる技である。

連番画像ファイルから動画への変換は AviUtil を使った。先頭の画像をドロップして、エンコードすればいいだけなのでお手軽だった。たいがいの動画変換ソフトが連番画像ファイルに対応しているだろうから、慣れているものを使って変換すればよいだろう。

タイマーを参照するパターン

さて、もう少し厄介なのが、各フレームでタイマーを参照するパターンの作品だ。そのようなコードを意識して書いていなかったとしても、トゥイーン系ライブラリでは内部的にタイマー系の関数を利用している。

このパターンの作品を、1つ目と同じように enterFrame で 1 フレームずつ画像出力していると、早送りの動画が出来上がってしまう。というのも、描画して画像を出力している間に、1 / frameRate 以上の時間が経過してしまうので、飛び飛びの画像しか出力できないのだ。

これを防ぐためには、トゥイーン ライブラリで利用しているタイマー系の関数を置き換えて騙すしかない。

変換例

過去に wonderfl に投稿した Hello World!!! を動画にしてみた。

ソースコードについて

ソースは https://gist.github.com/3885404 に上げている。

Hello World!!! は Tweener を使ってアニメーションしている。Tweener は、ライブラリの内部で flash.utils.getTimer() を使って、時間管理を実施している。この部分を書き換えて、自前で定義した getTimer() 関数を呼ぶようにした。

enterFrame で 1 フレームごとに画像を出力する点は以前のものと変わらない。ただ、画像を 1 枚出力するごとに、自前の getTimer() が返す値が 1 / frameRate だけ増えるように細工している。結果、出力した秒数に応じた位置で Tweener のアニメーションが停止するようになる。よって、コマ落ちが発生しない。

フレームレートは stage.frameRate を利用しているので、コンパイルオプションや SWF メタタグでカスタマイズすれば、デフォルト以外のフレームレートでも出力できる。

自前の getTimer() をトップレベルのパッケージとして定義しているが、これは flash.utils.getTimer() を利用するライブラリを一緒にビルドしようとしたときに、ビルドエラーにさせるためである。flash.utils.getTimer() を利用している箇所を grep して見つけ出してもいいんだけど、コンパイラに見つけさせよう、という魂胆である。

まとめ

ActionScript のソースが手元にあるときに、コマ落ちなく動画に変換する方法を説明した。

今回は簡単なソースコードで説明したが、setInterval() を使ってるようなケースではさらに複雑になる。マウスインタラクションがあったり、外部 SWF をロードしていると太刀打ちできなくもなる。

応用事例になるが、リアルタイムではとてもじゃないけど再生できないような劇重 Flash を作成したとしても、この方法を使って動画に変換はできる。パーティクルをいくつ配置しようが、ポリゴンをいくつ配置しようが、HD 画質にしようが、動画にしてしまえばコマ落ちの心配はない。Flash Player では得られない高画質な動画を作ることもできるだろう。

ここで紹介した 2 つの作品は、ActionScript Beautifl Code〜Beautifl: Flash Gallery of wonderfl〜 で解説してもらっているので、興味がある人はそちらもどうぞ。

ActionScript Beautifl Code〜Beautifl: Flash Gallery of wonderfl〜

ActionScript Beautifl Code〜Beautifl: Flash Gallery of wonderfl〜

  • 作者: 池田泰延
  • 出版社/メーカー: ワークスコーポレーション
  • 発売日: 2011-06-08
  • メディア: 単行本
  • Amazon のレビューを見る