SWF バイナリ加工 python ライブラリを公開しました

こんにちは、gumi 元エンジニアの鎌谷です。
gumi では解析システムの開発や、今回紹介する SWF バイナリ加工ライブラリの開発を行っていました。

SWF バイナリ加工について

ガラケー向けにインタラクティブなコンテンツを配信したい場合は、ほぼ全ての携帯機種に対応した Flash Lite 1.1 が用いられます。
ただし、この Flash Lite 1.1 は非常に多くの制約があります。
一度パブリッシュした SWF を動的に加工したい場合、バイナリをサーバーサイドで直接いじるという荒技が用いられているようです。

gumi でも SWF バイナリを動的に加工する必要があり、python ライブラリ Tomato が開発されました。

Tomato によって、

  • パラメータの注入
  • 画像の置き換え
  • MovieClip の置き換え

が python で行えるようになります!

Tomato

http://github.com/buhii/tomato/

  • Tomato ドキュメント

http://buhii.github.com/tomato/

Tomato は python 2.5 以上で動作します(python 3 には対応していません)。
Tomato の画像置き換え機能を用いるためには、PIL(1.1.7 以上)が必要になります。
MovieClip 置き換え機能には、bitarray(0.3.5 以上)と、msgpack-python(0.1.8 以上)が必要になります。

また、Windows では正常に動作しておらず、これは次期リリースで解決したいと考えています。

Tomato 開発で苦労した所

現在、SWF の仕様書は公開されており、誰でも自由に閲覧し、SWF を読み書きするプログラムを開発することができます。
また、画像置き換えについては、エンジニアの畠さんから紹介して頂いた、よやさんの SWF 解析記事を参考にしました。
http://pwiki.awm.jp/~yoya/?Flash/SWF
よやさんの記事のおかげで、SWF の構造を把握することができ、またエンジニアの中神さんのご協力の元、画像置き換えプログラムを開発することができました。


しかし、MovieClip の置き換えは苦労しました。
難しい箇所は、python によるビットフィールドの操作でした。
SWF バイナリはできる限りファイルサイズを小さくするために、ビットフィールドを用いて座標データ等を格納しています。最初に自前でビットストリームを処理するクラスを作成して処理を行っていたのですが、とても遅くて使い物になりませんでした。
エンジニアの田村さんと一緒に python で効率的にビットストリームを扱えるライブラリを探したところ、bitarray という C-extension が高速で良さそうでしたので用いることにしました。
ビットストリーム処理に bitarray を用いることで python による自前クラスよりも3倍程高速になりましたが、依然として SWF のパース処理は遅いままでした。


そこで、今度は SWF ファイルをパースしたものをあらかじめシリアライズしてしまい、それを動的合成の際に用いる方法を考えました。そうすれば、SWF ファイルを最初からパースすることなく、あらかじめ Python オブジェクトの形式で操作できるようになるので、パースするコストが削減されます。
ここでは、gumiStudy#7 で発表された古橋貞之さんの開発された msgpack を採用することにしました。
実際には、gumi のエンジニアもお世話になっている「エキスパート Python プログラミング」の翻訳者の一人である稲田直哉さんが python 向けにポーティングした msgpack-python を採用しました。


このような高速化を行った結果、Tomato はほぼ問題なく使用できるようになりました。
現在 Tomato は gumi の「メイド×メイド」や1月27日に発表されたばかりの「Zoo パラ」にて使用されており、問題なく動作しています。

Tomato の今後

Tomato は MIT License で公開されることになりました。
オープンソース化をご快諾頂いた gumi 国光社長、そして堀内 CTO に深く感謝いたします。
現在、Tomato は鎌谷がメンテナンスを行っております。問題や要望等ございましたら、gumi 宛ではなく鎌谷宛か、もしくは tomato-python Google Groupsに送って頂ければと思います。
最後に、Tomato の開発にご協力頂いた gumi エンジニアの皆様に深く感謝いたします。
ありがとうございました!