preload
5月 19

SwfRuby 初の利用事例のご紹介です。(すみません!エントリタイトルなど一部ドリコム様社名を誤って表記してしまっていました。お詫びして訂正します。05/19 14:15)

先日、ふと swfruby でググってみたら検索結果に以下のような記事がありました(検索結果を定点観測するのを失念していたのです)。

デブサミ2011レポート 数十~数百億PVのトラフィックをさばく、ソーシャルアプリのインフラ現場の実情:CodeZine

Flash Liteの動的生成については、「FlamixierというPHP拡張モジュールを自社で開発して利用している」(安井氏)「swfmillやswfrubyで生成している」(大仲氏)。

で、気になって、 twitter でつぶやいてみたら、ドリコム様のなかのかたからお返事をいただけました!

ドリコムでFlashLite動的生成に使ってるswfrubyって僕のつくったやつかなあ。同名の別のライブラリがあったのかしらん。 http://bit.ly/l1eKvk
@tmtysk
tmtysk
@ あ,貴殿のです!大変お世話になっております><
@onk
Takafumi Onaka
@ わぁっ、ほんとですか!嬉しいです!がんばってメンテします!ご連絡ありがとうございます.よかったらブログなどでも紹介させてくださいませ
@tmtysk
tmtysk
@ はーい,ぜひお願いします!うちのアプリだと「ビックリマン」と「ソード×ソード」で使わせていただいています。今時点で GREE の全体ランキング 3 位と 12 位なので結構処理数多いと思う。
@onk
Takafumi Onaka

いやー、めちゃめちゃ嬉しいです。今みてみたら、「ビックリマン」と「ソードxソード」、全体ランキング4位と9位でした! 人気のゲームなのですね。

SwfRuby、マニアックなライブラリということもあってか、これまで一度も利用事例を聞いたことはなかったのですが.. こんな大規模なサービスでの利用実績が聞けるなんて、とても嬉しいです。

@onkさん、つぶやきにご丁寧にご返信くださいまして、ありがとうございました!

Tagged with:
4月 27

SwfRuby を version-0.2.0 にバージョンアップして、AS変数の値の書き換えと、ムービークリップの入れ替えをできるようにしてみました。$ gem install swf_ruby でインストール可能。ruby-1.8.7, 1.9.2 で動作確認をおこなっています。ライセンスの変更はありません(GPL2)。インタフェースレベルでの後方互換性は確保しているつもりですが、swf_dumper の出力フォーマットが変更されていますので、このコマンドの実行結果をパースするような実装をされている方はご注意ください。

今回のバージョンアップにより、新たなコマンド、swf_as_var_replace, swf_sprite_replace が利用可能となります。それぞれ、AS変数の置換とムービークリップの置換を SWF のバイナリレベルでおこないます。バイナリ書き換えなので、非常に高速に動作します。

それぞれのコマンドの実装を読んでいただければ、アプリケーション内で書き換えをおこなう際の実装方法も、なんとなく掴めるかとおもいます。基本的な使用方法は、これまでのバージョン同様、元の SWF バイナリと、SwfRuby::ReplaceTarget オブジェクトの配列を SwfRuby::SwfTamperer に渡すという流れになります。

なお、手元の VM 環境では、20KB程度のベース SWF に対し、2件のAS変数と3件のムービークリップ(1KB未満のビットマップが貼ってあるだけのもの)の書き換えを1000回連続実行し、実行時間を測定してみたところ、0.252sec という結果が得られました(書き換え前後の SWF 素材を読出/書込するためのファイルシステムとのI/O時間は含みません)。1件当たり 1msec 以下での書き換えが実現できていることになります。

また、ムービークリップの差し替えができるようになったことにより、Jpeg 素材やビットマップ素材を、swftools などの外部ツールで SWF に変換しておくことで、画像変換処理のオーバーヘッドを事前に解決しておくことができるようになりました。ムービークリップの置き換えは、ステージに設置する際のインスタンス変数名を指定して、対象のムービークリップを差し替えるという処理になっていますので、ベースの SWF を制作する際にうまくルール決めができれば、同期的にRMagick(ImageMagick)を使用する必要すらありません。画像素材差し替え処理のコストを大きく削減することができるとおもいます。

やりたいことだけを実現するために、SWF 内要素の細かいパース処理など端折ったり、仕様を割り切ったりしている部分も残っています。適当にお楽しみくださいませ。

Tagged with:
1月 13

遅ればせながら jeweler から bundler への移行をちゃんと経験しておくべく、何やらこしらえてみました。といっても、$ bundle gem <ライブラリ名> としてスケルトンを作ったら、あとは gemspec をごにょごにょ書くだけだったので、さして難しくはなかったのですが。

今回公開した SwfRuby (swf_ruby) は、SWFバイナリを解析したり、内部に含まれる画像などのリソースを置換したりするための Ruby ライブラリ(およびコマンドラインツール)です。ruby-1.8.7 と ruby-1.9.2 で動作確認をおこなっています。こちらのライブラリは、GPL2(the GNU GENERAL PUBLIC LICENSE Version 2)にて使用を許諾します。

swf_ruby | RubyGems.org | your community gem host

tmtysk/swf_ruby – GitHub

SwfRuby のメイン機能を司るクラスは2つあります。SWF に含まれるタグ群やタグの登場箇所(オフセット値)をダンプする SwfDumper と、SWF に含まれるリソースを置換する SwfTamperer です。

昨年は携帯向けソーシャルアプリのブームもあり、サーバサイドでの Flash(SWF) 操作のニーズが高かったように思います。このサイトでは、2009年4月ごろから、swfmill を使った SWF の解析方法や、swfmill の Ruby ラッパーである SwfmillRuby を紹介してきました。しかしながら、莫大なアクセス負荷のかかるソーシャルアプリサイトですから、こちらで紹介してきたやり方では機能要件は満たせども、swfmill の起動コストや XML の操作コストに頭を悩ませた開発者の方も多かったのではないでしょうか。

SwfRuby は冒頭で述べた通り、swfmill などの中間ソフトウェアを一切介在させず、SWF バイナリを直接操作するライブラリです。現時点では荒削りなのでお世辞にも使い易い状態とは言えませんが、SWF の仕組みを大体理解している人にとっては、それなりに便利に使える部分があると考えています。(SWF のバイナリ編集については、グリーエンジニアブログでの連載がとても丁寧に解説されているので、そちらを参考にすると良いでしょう。)

以下、簡単に使い方を紹介します。

SWF のバイナリを直接操作するに当たって、まず調べないといけないのは「置換対象のリソースがSWF中のどこ(オフセット位置)に含まれているか」です。SwfDumper を使った解析プログラムを書くのも良いですが、swf_ruby をインストール( $ gem install swf_ruby )すると、SwfDumper を使ったコマンドラインツール swf_dump が使えるようになりますので、今回はそちらのツールを使った方法を紹介します。swf_dump の引数として SWF ファイルパスを指定してください。

$ swf_dump samples/sample.swf
SetBackgroundColor, offset: 20, length: 5
DefineFont2, offset: 25, length: 34
DefineEditText, offset: 59, length: 50
PlaceObject2, offset: 109, length: 11
DefineBitsLossless2, offset: 120, length: 178
DefineShape, offset: 298, length: 55
:
DefineBitsJPEG2, offset: 623, length: 10986
:

このような形で、SWF 内部のタグ一覧と、個々のタグの登場位置/長さを得ることができます。ちなみに、タグ情報は最新の SWF 仕様書を取り込んでありますので、Flash Lite の SWF に限らず、(たぶん)どんな SWF を指定しても、こういったダンプ情報を得ることができます。

さて、上記のダンプ情報により、DefineBitsJPEG2 タグがオフセット位置 623 バイト目から始まることがわかりました。つまり 623 バイト目以降にある JPEG バイト列と関連する情報をよしなに書き換えてやれば、この JPEG を差し替えることができるということになります。SwfTamperer は、この「よしなに書き換える」操作を支援するクラスです。swf_ruby をインストールすると、SwfTamperer を使ったコマンドラインツール swf_jpeg_replace が使えるようになりますので、ここでは、その使い方を紹介します。swf_jpeg_replace の引数として、SWF ファイルパス、書き換えを行う JPEG のオフセット位置(swf_dumpで取得可能)、書き換え後の JPEG ファイルパスを指定してください。

$ swf_jpeg_replace samples/sample.swf 623 samples/bg.jpg > samples/sample2.swf

書き換え後の SWF は標準出力へ出力されますが、ここでは、ファイルへリダイレクトをおこなっています。

最後に、拙作 SwfmillRuby と SwfRuby とで、SWF 読み込み → SWF 中の JPEG 1 ファイルを置換 → ファイル書き出しする際の簡単な速度比較をおこないましたので、ご参考までに紹介します。それぞれのプログラムを手元の PC のターミナルから100回連続実行(つまり100件のSWFを合成)した際の処理時間は以下のとおりでした。比較に使用した Ruby バージョンは 1.8.7 です。

  • SwfmillRuby .. 11.697s
  • SwfRuby .. 5.301s

SwfRuby は SwfmillRuby の約半分といったところでしょうか。減少分は swfmill の起動や libxml による xml 処理、RMagick による画像処理のオーバーヘッド分かと考えられます(期待値的には、もうちょっと(桁ひとつくらいは)速くなって欲しかったところですが、SwfRuby 側にまだまだ改善の余地があるのかもしれません)。

以上、SwfRuby の概要とコマンドラインツールの簡単な使い方を紹介しました。SwfTamperer は現時点では JPEG と ActionScript 内変数の書き換え機能しか提供しておりませんが、これに DefineEditText や DefineBitsLossless 系の書き換え機能が付けば、それなりに有用なものになると思います。また、ご興味の方には、コマンドラインツールだけでなく、SwfDumper や SwfTamperer クラス群をうまいこと使ってみていただいても良いかも知れません。SwfmillRuby ともども、フィードバック、pull request は大歓迎ですので、ぜひともご意見ご感想などお聞かせいただけると嬉しいです!

Tagged with: