ターミナルセッションを録画するツールVHSでのtips
はじめに
こんにちは、AWSでデベロッパーアドボケイトをしているものです。一昨日、Expert Onlineという企画で久々にターミナル上で行うデモをする必要があったのですが、時間がかかるデモだったので事前収録することにしました。しかし、長い時間がかかるのと、たまにターミナルに戻ってきて操作しなければならず、放ったらかしに出来ないのは時間の無駄だったので、なにかいいツールがないかと探したらVHSに行き着きました。
これが非常に便利だったので、その紹介と、デモに使う(特にプレゼンテーションスライドに埋め込む)場合のtipsを共有します。
VHSとはなにか
ターミナルセッションを録画するためのツールで、有名なものにはasciinemaがあります。多くの開発者ツールはGitHubのREADMEや公式ドキュメントにその動作をアニメーションGIFでデモを録画して埋め込んでいたりします。数秒〜数十秒程度のデモであればasciinemaで良かったのですが、先日のデモは数十分に及ぶため、アニメーションGIFでは難しく、どうしても動画ファイルで録画する必要がありました。そこで調べたところVHSに行き着いたというわけです。
VHSの特徴は次のとおりです。
- 録画ファイルはアニメーションGIF、WebP、MP4 (H.264)のいずれかで選択可能
- フォントやそのサイズ、画面サイズの設定が可能
- カラーテーマの設定が可能
- 入力待ちやスリープが可能
- リッチな仮想的なターミナルウィンドウが設定可能
- SSH経由でリモートのターミナルも録画可能
使い方
インストール
macOSであればHomebrewのcoreに入ってるのですぐにインストール可能です。
$ brew info vhs
==> vhs: stable 0.9.0 (bottled), HEAD
Your CLI home video recorder
https://github.com/charmbracelet/vhs
Installed
/opt/homebrew/Cellar/vhs/0.9.0 (10 files, 21.7MB) *
Poured from bottle using the formulae.brew.sh API on 2025-03-25 at 00:02:42
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/v/vhs.rb
License: MIT
==> Dependencies
Build: go ✔
Required: ffmpeg ✔, ttyd ✔
==> Options
--HEAD
Install HEAD version
==> Caveats
zsh completions have been installed to:
/opt/homebrew/share/zsh/site-functions
==> Analytics
install: 250 (30 days), 1,051 (90 days), 3,939 (365 days)
install-on-request: 250 (30 days), 1,051 (90 days), 3,939 (365 days)
build-error: 0 (30 days)
$ brew install vhs
VHSはGo製なのでGoが入った環境であれば go install
で入れるのも楽です。ただし動作させるのにはttydとffmpegが必要。
$ go install github.com/charmbracelet/vhs@latest
ほかにもLinuxであればdebやrpmのフォーマットで配布されていたり、Windowsだとscoopで入れることもできるようです。
操作方法
VHSという名前はある年齢以上の人であればピンとくるわけですが、家庭用ビデオテープの規格名ですね。というわけで、録画したい操作を .tape
という拡張子の中に書いておくというのが慣例になっているようです。
操作の記述は専用DSLを使うわけですが、非常に単純なのでプログラムが書けない人でも問題なく記述できます。たとえば、macOS上で次のように sample.tape
書いて
Output sample1.webp
Set Shell zsh
Set FontSize 12
Set Width 600
Set Height 450
Set Framerate 60
Set Padding 10
Type "sw_vers"
Enter
Wait
Sleep 4s
Type "system_profiler SPHardwareDataType"
Enter
Sleep 3s
これを実行すると録画が開始されてどの操作をしているかが表示されていき、最後に録画ファイルを作るところまでが目視できます[1]。
で上のスクリプトで生成された動画ファイルはこうなります。
DSLの一覧はプロジェクトのREADMEに記載されています。実際のタイピングと同様にバックスペースやタブ、Ctrl-Rなんかも動作します。もちろん矢印キーも動作します。これは下を5回、右を4回、上を3回、左を2回押したのと同様の動きをします。
Down 5
Right 4
Up 3
Left 2
操作を記録する
自分でゼロから .tape
ファイルを記述するのが大変という場合には、下書きとして自分が入力したコマンドを記録してもらう record
というモードがあります。次のコマンドは一旦自分の操作を demo.tape
というファイルに保存して、それをあらためてVHSで録画しています。
vhs record > demo.tape
vhs demo.tape
これを使うことで冪等な操作であればそのままありのままを記録することも可能になります。
tips
好みの設定を固めておく
VHSではtapeファイルの中で他のtapeファイルを呼び出すことができます。
Output demo.mp4
Set WaitTimeout 10m
Source settings.tape
Type "echo $PATH"
Enter
ここで settings.tape
は次のような設定を書いておきます。
Set Shell zsh
Set FontSize 20
Set Width 1600
Set Height 900
Set WindowBar Colorful
Set BorderRadius 10
Set Framerate 60
Set Theme "nord"
Set TypingSpeed 80ms
それぞれの設定は次のとおりです
-
Shell
: 起動するシェルの種類を指定します -
FontSize
: デモ用なのでサイズを大きめに設定 -
Width
,Height
: スクリーンのサイズです。16:9で設定しておくとスライドに貼りやすい。 -
WindowBar
: なんかぱっとみmacOSのターミナルで動作してるように見える。好み。 -
BorderRadius
: 角丸のほうがかわいい -
Framerate
: 60FPSで十分だと思いますが、120や240がいい人はお好みで -
Theme
: 自分はターミナルもVS CodeもNordを使っているので合わせています -
TypingSpeed
: デフォルトのタイピングスピードは50msなのでちょっと速いと思うので遅くしています。
タイムアウト時間に注意
AIコーディングエージェントとかを使ってると、ざらに10分動きっぱなしになったりすることがあります。
そうするとプロンプトが帰ってこなくなるので、デフォルトだとタイムアウトしてしまいます。
自分はタイムアウトの設定値を伸ばして、コマンド実行中に終了してしまわないように変更してます。
Set WaitTimeout 10m
秘匿事項を入力しないといけない場合はHide
パスワードを入力しなければいけないような場合、HideとShowを使うことでそれを隠すことができます。さらにそれを別のtapeファイルに入れておけば使い回しも出来そうですね。たとえば login.tape
というファイルを用意します。
Type "foo command log in..."
Hide
Ctrl+A
Ctrl+K
Type "foo login --password deadbeef && clear"
Enter
Show
これで foo
コマンドのログイン動作中のパスワード入力などは録画されずにすみます。( login.tape
でパスワードが丸見えなのはまた後で考えることにする)
作業をファイルで分割しておく
長い作業のデモを録りたい場合はtapeファイルを分割しておくのも良いと思います。
Output all.mp4
Set WaitTimeout 10m
Source step1.tape
Source step2.tape
Source step3.tape
step1.tape
と step2.tape
と step3.tape
の作業に依存性がなければ別々に実行しても問題ないし、時間がないときは個々に録画しておくこともできます。
Output step1.mp4
Source step1.tape
動画ファイルはすべて同じコーデックで同じビットレートで作成されていて、VHSの動作条件としてffmpegが入ってる前提があるので、個々に実行してから最後に連結しても良いでしょう。
ここからはffmpegの話になってしまうけど、たとえば次のようなテキストファイル inputs.txt
を作成しておきます。
file './step1.mp4'
file './step2.mp4'
file './step3.mp4'
このファイルを使って次のコマンドでファイルを無劣化で連結できます。
$ ffmpeg -f concat -safe 0 -i inputs.txt -c copy all.mp4
おわりに
まだVHSを使い始めたばかりなので、もっと便利な使い方があればぜひ知りたいです。
-
これは
vhs
コマンドを実行するスクリプトをvhs
コマンドに流すというおしゃれなことをしています。 ↩︎
Discussion