サーバーでWeb画面のスクリーンショットを取る

テストをしていて不具合を見つけたときなど、Web画面のスクリーンショットをとって資料に貼りつけたりすることがよくありますが、キャプチャツールを起動して画面ショットをとってファイルを保存してというのは結構面倒です。

サーバー側で画面ショットがとれたら、URLから画面ショットの画像を生成してダウンロードするようなものを作って、それを叩くブックマークレットを作って…とか夢が広がります。というわけで調べてみました。

既存のサービス

URLからサムネイルを作成するようなサービスは色々あるみたいですが、スクリーンショットを撮りたいのは公開していない検証環境みたいなページだったりするので、サムネイル作成サービスみたいなのはちょっと違いました。

Xvfb (X Virtual Frame Buffer)

X Windows Systemがインストールされていないシステムで、仮想的なフレームバッファを実現するXvfbというソフトウェアがあるみたいです。「フレームバッファ」というのが何だかわからなかったのですが、どうやらディスプレイに描画されるドットの集まりをフレームと呼んで、そいつをバッファリングして高速にディスプレイへの出力を行うとかそんな感じのものだと思います。つまり、よくわかりません><

よくわかりませんが、このXvfbを使えばXが入ってない環境でも仮想的なディスプレイを作ることができ、この仮想ディスプレイにWebプラウザを立ち上げて、ページのスクリーンショットを撮ることができるみたいです。

とりあえず手元のUbuntuで試してみます。

Xvfbを使ってみる Ubuntu

まずはXvfdをインストールします。画面ショットをpng形式に変換するためにImageMagickという画像ライブラリもインストールしておきます。

makoto@hp-laptop:~$ sudo apt-get install xvfb imagemagick

インストールしたXvfbを起動します。これで仮想ディスプレイが起動するわけです。目には見えないけど、ディスプレイのようなものが1つ増えた感じでしょうか。

makoto@hp-laptop:~$ Xvfb :1

なにかエラーメッセージが出ていますが気にしないことにします。フォントが初期化できない?リストから削除する?英語はよくわかりません。

[dix] Could not init font path element /usr/share/fonts/X11/cyrillic, removing from list!

仮想ディスプレイが起動したので、次はfirefoxを起動してこの仮想ディスプレイ上に表示します。「表示します」といっても仮想ディスプレイなので目には見えません。
DISPLAY環境変数にディスプレイ番号をセットしてからfirefoxを起動すると、そのディスプレイ上にfirefoxが表示されるみたいです。firefoxに限らずX Windows Systemで動くGUIアプリケーションは実行時のDISPLAY環境変数に指定されたディスプレイに表示される気がする。そんな気がする。

makoto@hp-laptop:~$ DISPLAY=:1; firefox

またすごい勢いでメッセージが出ました。最後の方にfailedとか書いてありますが、プロセスは終了せずに走り続けているので気にしないことにします。

5 XSELINUXs still allocated at reset
SCREEN: 0 objects of 84 bytes = 0 total bytes 0 private allocs
DEVICE: 4 objects of 24 bytes = 96 total bytes 0 private allocs
CLIENT: 0 objects of 128 bytes = 0 total bytes 0 private allocs
WINDOW: 0 objects of 16 bytes = 0 total bytes 0 private allocs
PIXMAP: 1 objects of 8 bytes = 8 total bytes 0 private allocs
GC: 0 objects of 44 bytes = 0 total bytes 0 private allocs
CURSOR: 0 objects of 4 bytes = 0 total bytes 0 private allocs
CURSOR_BITS: 0 objects of 4 bytes = 0 total bytes 0 private allocs
DBE_WINDOW: 0 objects of 12 bytes = 0 total bytes 0 private allocs
TOTAL: 5 objects, 104 bytes, 0 allocs
4 DEVICEs still allocated at reset
DEVICE: 4 objects of 24 bytes = 96 total bytes 0 private allocs
CLIENT: 0 objects of 128 bytes = 0 total bytes 0 private allocs
WINDOW: 0 objects of 16 bytes = 0 total bytes 0 private allocs
PIXMAP: 1 objects of 8 bytes = 8 total bytes 0 private allocs
GC: 0 objects of 44 bytes = 0 total bytes 0 private allocs
CURSOR: 0 objects of 4 bytes = 0 total bytes 0 private allocs
CURSOR_BITS: 0 objects of 4 bytes = 0 total bytes 0 private allocs
DBE_WINDOW: 0 objects of 12 bytes = 0 total bytes 0 private allocs
TOTAL: 5 objects, 104 bytes, 0 allocs
1 PIXMAPs still allocated at reset
PIXMAP: 1 objects of 8 bytes = 8 total bytes 0 private allocs
GC: 0 objects of 44 bytes = 0 total bytes 0 private allocs
CURSOR: 0 objects of 4 bytes = 0 total bytes 0 private allocs
CURSOR_BITS: 0 objects of 4 bytes = 0 total bytes 0 private allocs
DBE_WINDOW: 0 objects of 12 bytes = 0 total bytes 0 private allocs
TOTAL: 1 objects, 8 bytes, 0 allocs
[dix] Could not init font path element /usr/share/fonts/X11/cyrillic, removing from list!
Xlib:  extension "RANDR" missing on display ":1".

(firefox-bin:9312): LIBDBUSMENU-GTK-CRITICAL **: dbusmenu_menuitem_property_set_shortcut: assertion `gtk_accelerator_valid(key, modifier)' failed

次に「xwd」というコマンドで仮想ディスプレイのスクリーンショットを撮ります。これまで目に見えなかった仮想ディスプレイですが、スクリーンショットを撮ることで中の様子を見ることができるわけです。

makoto@hp-laptop:~$ xwd -display :1 -root -out test.xwd
-display ディスプレイ番号
-root ディスプレイ全体を撮る
-out 出力ファイル名

出力されたxwdファイルは、最初にインストールしたImageMagickのconvertコマンドで変換することができます。

makoto@hp-laptop:~$ convert test.xwd test.png

こんなスクリーンショットが撮れました。
たしかにfirefoxの姿が撮影できています。素晴らしいです。

まとめるとこうなります。

  • Xvfbをインストールする
  • ディスプレイ番号を指定してXvfbを起動
  • 起動した仮想ディスプレイ上にfirefoxを起動
  • xwdで仮想ディスプレイのスクリーンショットを撮る
  • ImageMagickをインストールしてconvertコマンドで画像形式を変換
  • 変換した画像を眺めてニヤニヤする

Xvfbを使ってみる CentOS

CentOSでもやってみました。Xvfbのパッケージ名が長いです。「X Windows Systemがインストールされてない環境でも」っていうのは間違いだったようです。Xがない状態ではXvfbは起動してくれませんでした。

# 必要なソフトをインストール
sudo yum groupinstall "X Window System"
sudo yum install xorg-x11-server-Xvfb
sudo yum install ImageMagick
sudo yum install firefox

# Xvfbとブラウザを起動
export DISPLAY=:1
Xvfb :1 &
firefox &

# スクリーンショットをとって変換
xwd -root -display :1 -out test.xwd
convert test.xwd test.png

こんなスクリーンショットがとれました。

まとめ

とりあえずCUICentOS上でFirefoxスクリーンショットを撮ることができました。
でも色々と課題が残ってます。

  • 毎回スクリーンショット撮って確認するのは面倒。リモートデスクトップみたいに操作したい
  • 画質がよくない
  • firefoxのウィンドウだけ撮れればいいのにフルスクリーンになっちゃう
  • URLを指定してページを開きたい
  • firefoxのウィンドウサイズを指定して起動したい
  • firefoxを起動するといつもクラッシュから立ち直ったような画面になってるのがイヤ

この辺を調べてみようと思います。