SimpleAPI の仕組みについて考察してみる

最近気になっているサービスと言えば、一躍有名になった「SimpleAPI その1.ウェブサイトサムネイル作成API β版」っていうサービス。その1って書いてあるくらいだから、作者の方はその2、その3を考案中と思われるわけですが、サイトのサムネイルを生成するってのはいろいろなところで役に立ちそうな気がします。

で、できれば自社で同じような仕組みを作って自社で解決したいと思われている方も多くいるのでは?と思います。僕的には会社の仕事からすれば何ら関連のないジャンルのサービスですが、個人的には非常に興味がそそられるサービスなので、その仕組みについて考察してみました。勝手な考察なので、全然違う可能性もあるので、あしからず・・・。

- スポンサーリンク -

どうやってサイトのサムネイルを生成しているのか?

自前で位置からブラウザの描画を模倣するプログラムってのは作るには敷居が高すぎると直感。特に CSS や JavaScript の挙動を模倣するのはかなりシンドイはず。とすれば、内部的にはブラウザを動かしているはず。サーバは恐らく Linux と思われるので、 mizilla や FireFox や Opera を動かしていると思われます。

とすると、ブラウザを起動する環境が必要なはず。X を起動して処理をしているはずがない。とするならば、

1.Xvfb - 仮想フレームバッファってのを使って X の仮想環境をつくって、そこでブラウザを起動する。

これで、仮想フレームバッファ内でブラウザを動作させて別途指定するURLを描画するってことができるようになるので、それをキャプチャして縮小する機能があればよい。

2.Image::Magick を使って仮想フレームバッファをキャプチャして縮小する

おそらく、キモはこの2点と思われます。後は Perl で実装するなら、Perl::Magick つかって 画像の編集とかしてサムネイル生成して、キャッシュ管理とかちゃんとやる感じかなぁ〜と勝手に想像。1つのサービスとして形成するのは結構骨がおれる仕事と思いますが。


で、試しに実験してみます。

Xvfb - 仮想フレームバッファのインストール

OS によって多少名称が異なりますが、XFree86-Xvfb もしくは、xorg-x11-Xvfb ってパッケージをインストールします。僕の環境は CentOS 4.2 で yum つかってパッケージ管理しているのでこんな感じで。Xvfb がインストール済みならここは読み飛ばしてOK。
yum grouplist
yum groupinfo "X Window System"
yum upgrade xorg-x11-xfs
yum upgrade xorg-x11
yum upgrade xorg-x11-devel
yum upgrade xorg-x11-libs
yum groupupdate "X Window System"
yum upgrade xorg-x11-libs
yum install xorg-x11-Xvfb
yum install firefox

これで、一通りパッケージの依存関係を解消しつつ Xvfb の環境が整うはず。やっぱ、OS インストール時にはフルインストールしておくのが便利かも。ブラウザはとりあえず FireFox を使用。JavaScript 関連とかマトモに表示できるんで。

つぎに、FireFox のプロファイルの設定。

firefox -createprofile webshot
mkdir /tmp/webshot/

つぎに、Xvfb を起動する init ファイルの作成。

echo '#!/bin/bash
#
# chkconfig: - 91 35
# description: Starts and stops XVfb. \
#              used to provide virtual frame buffer.

# Source function library.
. /etc/init.d/functions

prog=$"Xvfb"

# Xvfb program
XVFB=/usr/X11R6/bin/Xvfb

start() {
    echo -n $"Starting $prog: "
    daemon /usr/X11R6/bin/Xvfb :1 -screen 0 1024x1024x24 &
    echo
}

stop() {
    echo -n $"Shutting down $prog: "
    killproc Xvfb
    echo
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart|reload)
        stop
        start
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart}"
        exit 1
esac

exit 0
' > /etc/init.d/xvfb
chmod 755 /etc/init.d/xvfb
chkconfig xvfb on

これで、仮想フレームバッファとブラウザの環境は整う。ちなみに、起動の仕方は下記の通り。

export DISPLAY=:1.0
firefox -display :1 -width 800 -height 1024 -P "webshot" &
firefox -display :1 -remote "openurl(http://www.drk7.jp/)"

これで、仮想 X 上に http://www.drk7.jp/ を表紙しているはず。あ、ちなみに、DISPLAY 環境変数の設定は VNC とか使ってすでに :1 が使用済みなら適当に :2 とかで。

コマンドラインベースでサムネイルを生成するスクリプトの実験

取りあえず、コマンドラインベースで動作するヤツ。なんでコマンドラインベースかは下の方で。
#!/usr/bin/perl -w
use Image::Magick;

$ENV{DISPLAY} = ':1.0';
my $url = $ARGV[0] or die 'need url args..';
my $img_fname = 'sample.png';
my $thumb_fname = 'sample_thumb.png';

`firefox -display :1 -remote "openurl($url)"`;
`import -display :1 -window root -silent $img_fname`;

$img=Image::Magick->new;
$img->Read($img_fname);
$img->Crop('768x768+0+90');
$img->Set(quality=>90); 
$img->Scale( width=>128, height=>128 );
$img->Write($thumb_fname);

適当に test.pl とでも保存する。起動の仕方は以下の通り。適当な URL を引数で渡す。

perl test.pl http://www.yahoo.co.jp/

とかやれば、sample_thumb.png っていうサムネイルが生成できているはず。これを CGI 経由で動作させようとすると、何故か、fork して Firefox を実行する部分で Segmentation fault 。むむむ・・・

/usr/lib64/firefox-1.0.7/run-mozilla.sh: line 159: 16542 Segmentation fault "$prog" ${1+"$@"}

あと一歩が実は難しい。。。今日はここまで。 ってか、必要なら SimpleAPI 使えばいっか。良くできてるし。それにしても初めて Xvfb なんてものを知りました。Linux 道、奥が深い。。。

- スポンサーリンク -