先日 ターミナル操作の記録(ttyrec)からGIFアニメを生成するツールを作った - すぎゃーんメモ を書いたところ、思っていた以上に反響があって。
自分的にも結構便利だなーと思っていたのだけど、
ttygifとその系列、端末マニアではない人の95%くらいのユースケースでは端末に依存するシーケンスとか流さないだろうし、色とかが微妙に違ってもそこが主眼じゃないと思うので、単純に内部に端末を持ってダイレクトにGIFを吐ければ良くて、いちいちスクリーンショト取るの筋悪ではないの?
という意見をいただいて。うーん 確かに、と。
C版
で、はやくもそういうのを実現するものが作られました。すごい。
エスケープシーケンスの処理なんかも内部の仮想端末でちゃんとやってくれる。
その他、オプションで端末サイズや色の調整なども出来るようで。
Go版
せっかくなのでGoでもそういうの作れないか?と調べてみたところ、端末のエミュレートできるライブラリがちゃんとあった。
これを使って入力を流し込むことで見事にttyrecordの再生を内部で再現することができた。便利!
各状態でfunc (t *State) Cell(x, y int) (ch rune, fg Color, bg Color)
を使ってy行目のx列目の文字、色、背景色が取得できるので、ひとつひとつ描画していけば良い。
code.google.com/p/freetype-go/freetype を使うことで画像への文字の描画ができる。 go-bindata を使って適当なmonospace fontを埋め込んで、それを読んで使う。
ということで内部での再生&描画ができたのでGoでもスクリーンショット撮ることなくttyrecordからGIFアニメを作ることができた。
「ttyrecordからGIFを作る」というのは前回書いた ttygif と同じではあるのだけど、アプローチが全然違うので「ttyrec2gif」という名前で別のpackageとして分けておいた。
すごく特殊な再生内容があったりターミナルのフォントなどの見た目とかにこだわりがあってスクリーンショットを使った方が良い場合は ttygif を使えば良いと思うし、そうでない場合は こっちを使えば良い、んじゃないかな。
コマンドの入出力もseq2gif
に倣ってstdin, stdoutの方が良かったかなぁ…。
ちなみにseq2gif
の方がこのttyrec2gif
より圧倒的に早い。
まぁでも いちおうttyrec2gif
でもそれなりにエスケープシーケンスとか扱って描画できている、と思う。
(余談: このslの再生しようとしてvirtual termianlが固まる事象があってハマった。調べたら ものすごい単純なバグ だった)
今後?
もうちょっと文字色・背景色の設定とか弄れるように、とかも考えたけど、この先はまた別のUIで出来たら面白いのでは?ということで Web上でJSを使って同様のことが出来ないか調べてみようと思ってる。