TL; DR
X Windowを使った画像表示が重いとき(特にRaspberryPi ZERO),X Server等を立ち上げずにフレームバッファで画面表示をするとサクサクになりがち.
なにがしたいか
RaspberryPiを使ってデジタルサイネージっぽいものやってる例があったので(これとかこれとか)がうらやましかったので,ブラウザを全画面表示してやってみようとしたところ,RasPiZeroだとブラウザの処理が重く実用に耐えませんでした.
そこでX Windowサーバを立ち上げずに直接フレームバッファを使うことで,軽量化を図ってみました.
基本戦略
普通にブラウザを立ち上げるとブラウザがCPUを食い潰してしまうのでHTMLのレンダリングとレンダリング結果の表示を独立して行います.
具体的には
- ChromiumのHeadlessモードを使ってHTMLを画像に変換し
- 画像をfbiコマンドを使ってフレームバッファに表示
- 1から繰り返す
という流れになります.
(結論から言うと1.のHTMLのレンダリングが時間がかかりすぎてそんなに体感速度は出ませんでした・・・)
下準備
Chromium, fbiのインストールとfbiのパス無しsudoの許可
HTMLをPNGに変換するためにchromium-browser
を,PNG画像をフレームバッファに表示するためにfbi
を使うのでインストールします.
$sudo apt install chromium-browser fbi
また,fbiは実行時に/dev/ttyXにアクセスする必要があるのでsu権限での実行が必要ですが,
自動化する手前sudo
時にパスワードを聞かれるのは困るのでパスワード無しでsudo
可能にしておきます.
(参考:(sudo のパスワードを入力なしで使うには)[https://qiita.com/RyodoTanaka/items/e9b15d579d17651650b7])
visudo
して以下の一行をsudoersに追加します.
pi ALL = NOPASSWD: /usr/bin/fbi
/sys/class/graphics/fb0/blankの権限変更
RaspberryPiではHDMI出力のOn/Offを切り替えは
#echo 0 > /sys/class/graphics/fb0/blank
#echo 1 > /sys/class/graphics/fb0/blank
のようにすればいいっぽいんですが(画面スリープからの復帰も同様),一般ユーザからも操作したいので
$sudo chmod 666 /sys/class/graphics/fb0/blank
する必要があります.
ただ,毎回起動後にsudo
するのは現実的ではないので/etc/rc.local
に以下を追加して起動後に権限を変更するようにしておきます.(セキュリティ的にどうなの?的な問題はあるとは思いますが,たかが画面のON/OFFだし・・・)
chmod 666 /sys/class/graphics/fb0/blank
動作
HeadlessなChromiumを使ってHTML→PNG
ChromeのHeadlessモードの詳細は本家のヘッドレス Chrome ことはじめ に紹介をゆずりますが,端的に言えばコマンドライン上で動作が完結するモードです.
例えば,以下のようにすることで1920x1080のサイズのヤフー天気のページが取得できます.
--hide-scrollbar
を指定することでスクロールバーが表示されず見栄えが良くなります.
(なぜかコマンドを間違えた時にエラーが出ずに無視されるだけなので非常にtypoに気付きにくいです)
$chromium-browser --headless --disable-gpu --screenshot --hide-scrollbar --window-size=1920,1080 https://weather.yahoo.co.jp/weather//weather/
とすると,実行したディレクトリにYahooのお天気ページがscreenshot.pngとして保存されます.
(↓こんな感じ)
HDMI出力の有効化
イマイチ条件がわかってないんですが,放っておくとHDMI出力がOFFになりがちなので,
$echo 0 > /sys/class/graphics/fb0/blank
してHDMI出力を有効化します.
フレームバッファへの画像出力
以下のコマンドを実行することで,先ほど保存した画像が全画面表示されます.
$sudo fbi -T 1 -d /dev/fb0 -noverbose screenshot.png
以上の手順をスクリプトにまとめて無限ループさせることでX無しにデジタルサイネージっぽいことが可能になります.
感想
Chromiumのheadlessモードの利用法としてはかなり邪道な予感がするせいか,全くパフォーマンス的には改善が見られませんでした.
ただ,フレームバッファに画像を表示する動作自体は高速なので,サーバサイドで表示する画像を作ってあげてwgetして表示とか言う流れならもっとフレームレートが上げられる気はします.
まぁそもそもHTML→PNGが重いので,表示したい内容をSVGで作ってconvert(imagemagic)するとか,もっと他の画像作成方法を使うと言う手は十分に考えられそうです.
ただ,「Webベースのダッシュボードを作ってそれを定期的に更新しながら画面に表示する」的なアプリケーションなら今回の構成で十分実用可能そうです.
あとモニタを起動後に接続しても上手いこと解像度等設定してくれないので,プラグアンドプレイな状態を実現したいものです.