Creating Terminal Based Screencast Movies With VHS

Via a fun blogpost from Leigh Dodds — Recreating sci-fi terminals using VHS — and the fascinating repo behind it, I come across charmbracelet/vhs, a nifty package for creating animated gif based screencasts / movies of terminal based interactions.

Ar first, I thought this was just about creating fake replays from a canned script, which obviously has issues if you are looking to create a reproducible and true video of an actual terminal interaction…

But then, looking at Leigh’s repo, it suddenly became clear to me that this was just a hack based on using a real terminal, and that the script can be used to script, and record, actual terminal interactios. Doh!

So for example, Leigh’s .tape script to create the above video looks like this:

Output gifs/jurassic-park-nedry.gif
Output gifs/jurassic-park-nedry.mp4

Set FontSize 14

Set Width 800
Set Height 600

Set Theme { "name": "Neo", "black": "#0D0208", "red": "#ef6487", "green": "#5eca89", "yellow": "#fdd877", "blue": "#65aef7", "magenta": "#aa7ff0", "cyan": "#43c1be", "white": "#ffffff", "brightBlack": "#0D0208", "brightRed": "#ef6487", "brightGreen": "#5eca89", "brightYellow": "#fdd877", "brightBlue": "#65aef7", "brightMagenta": "#aa7ff0", "brightCyan": "#43c1be", "brightWhite": "#ffffff", "background": "#203085", "foreground": "#ffffff", "selection": "#000000", "cursor": "#5eca89" }

# Change the default prompt before we start the script
Type "source" Enter
Type "export PS1=''" Enter
Type "Jurassic Park, System Security Interface" Enter

Type@100ms "access security"
Sleep 1s
Sleep 1s
Type@100ms "access security grid"
Sleep 1s
Type@100ms "access main security grid"

Sleep 5s

Those are actual commands, as you can see from the source typed command. What that does is load in a script that creates definitions for “commands” that appear later in the tape script (i.e. commands that might not be recognised by the terminal, or that we might want to override:

Jurassic() {
 export PS1='> '
 echo "Version 4.0.5, Alpha E";
 echo "Ready...";

access() {
 sleep 0.5;
 case $1 in
     echo "access: PERMISSION DENIED.";
     echo "access: PERMISSION DENIED....and....";
     for i in {1..100}
        sleep 0.1;

So for example, when the command Jurassic is entered into the real terminal, we want a particular echoed response. Similarly when the access commands are Typed.

If you have Docker installed, the simplest way to run vhs is probably via a container. For example, hacking the following simple .tape script together:

Output demo.gif

# Set up a 1200x600 terminal with 46px font.
Set FontSize 46
Set Width 1200
Set Height 600
Set TypingSpeed 100ms

# Type a command in the terminal.
Type "echo 'A simple VHS demo...'"

# Pause for dramatic effect...
Sleep 2s

# Run the command by pressing enter.

Type "mkdir -p demo"
Sleep 500ms
Sleep 1s

Type@100ms "ls demo"
Sleep 500ms
Sleep 1s

Type "echo 'Hello world' > demo/test.txt"

Sleep 500ms

Type@1s "ls demo"
Sleep 2s

Type "cat demo/test.txt"

Sleep 500ms

Type "echo '....and that is the end of the demo...'"

Sleep 1s

Sleep 3s

I can generate an animated gif as easily as typing docker run --rm -v $PWD:/vhs MYTAPE.tape

I’ve also started wondering about using a Jupyter notebook to draft the interaction, then some sort of simple script to convert the notebook code cells to .tape instrcutions, perhaps with suitable delays…

It might also be possible to spoof the notebook interaction, by echoing the commands in the code cell as if they wer real commands and then echoing the code cell output? Then you could use a pre-run notebook as the basis for a tape that replayed the “mocked” taped console commands from the notebook and the actual outputs from the notebook code cells?

Author: Tony Hirst

I'm a Senior Lecturer at The Open University, with an interest in #opendata policy and practice, as well as general web tinkering...

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: