# Terminal Animator Turn terminal screenshots into polished short video animations (15-30s) where commands type themselves and responses appear instantly. ## When to Use Use this skill when a user asks to: - Animate a terminal screenshot - Create a CLI demo video - Turn a command-line screenshot into a video/animation/GIF - Make a terminal recording from a screenshot or text ## Requirements The following must be available in the agent's environment: - **Node.js** (v18+) - **ffmpeg** (static binary works; needs libass for subtitle rendering) - **canvas** npm package (`npm install canvas`) - A monospace font (DejaVu Sans Mono or similar) If ffmpeg is not installed, download a static arm64/amd64 binary from https://johnvansickle.com/ffmpeg/ ## Workflow ### Step 1: Get the terminal content If the user sends a **screenshot image**: 1. Use the `image` tool to transcribe every line of text, preserving prompts, commands, output, and special characters 2. Save the transcription to a text file If the user sends **text** (copy-pasted terminal output): 1. Save directly to a text file ### Step 2: Identify the structure Parse the content into **command/response blocks**: - **User input lines**: what the user typed (may have a prompt like `$`, `>`, `❯`, or no prompt at all) - **Response lines**: system output, including styled lines (arrows, status messages, ASCII art) - **Special blocks**: ASCII art, logos, status lines that need special treatment For each line, determine: - **Style**: input (white), arrow/accent (green `▶` prefixed), normal response (gray), dim/muted, ASCII art (white) - **Timing**: user inputs get typed character-by-character; responses appear instantly ### Step 3: Identify colors and theme Sample the screenshot to determine: - Background color (sample from empty areas) - Text colors for each element type - Whether there's window chrome (titlebar with traffic light dots) or plain terminal - Font size relative to the content density Common terminal themes: - **Dark teal/slate**: bg `#292C35`, white input, green accents, gray responses - **Catppuccin Mocha**: bg `#1e1e2e`, pastel accents - **Dracula**: bg `#282a36`, purple/green accents ### Step 4: Handle ASCII art / logos ASCII art with Unicode box-drawing characters (██╗║═╚╝) does NOT render correctly in ASS subtitles because libass doesn't maintain monospace character widths for these glyphs. **Solution**: Render ASCII art as a PNG image using `node-canvas` (which handles monospace correctly), then overlay it on the video. Use the script at `scripts/make-art-overlay.mjs`: ```bash node scripts/make-art-overlay.mjs \ --text "line1\nline2\nline3" \ --bg "rgb(39,44,51)" \ --fg "#FFFFFF" \ --font-size 32 \ --output .art-overlay.png ``` The background color MUST exactly match the video background after ffmpeg encoding. To find the exact color: 1. Render a test frame: `ffmpeg -f lavfi -i "color=c=#292C35:s=100x100:d=0.1:r=1" -frames:v 1 test.png` 2. Sample the pixel: `convert test.png -crop 1x1+50+50 -format "%[pixel:u.p{0,0}]" info:` 3. Use that exact RGB value for the art overlay background ### Step 5: Generate the ASS subtitle file Create an ASS (Advanced SubStation Alpha) subtitle file with: - Styles for each text type (Input, Arrow, Normal, Dim, Cursor) - Alignment 7 (top-left) with MarginV for Y positioning - Timed dialogue events for typing animation and response appearance - Blinking cursor at the end Key ASS settings: - `PlayResX`/`PlayResY` must match the video dimensions - Colors are in `&HBBGGRR&` format (BGR, not RGB!) - Font: DejaVu Sans Mono (available on most Linux systems) ### Step 6: Render with ffmpeg ```bash ffmpeg -y \ -f lavfi -i "color=c=#292C35:s=960x920:d=6.0:r=30" \ -filter_complex "[0:v]ass=demo.ass[bg];movie=.art-overlay.png[art];[bg][art]overlay=x=18:y=520:enable='gte(t,3.0)'" \ -c:v libx264 -preset fast -crf 18 -pix_fmt yuv420p \ output.mp4 ``` If there's no ASCII art overlay, simplify to: ```bash ffmpeg -y \ -f lavfi -i "color=c=#292C35:s=960x920:d=6.0:r=30" \ -vf "ass=demo.ass" \ -c:v libx264 -preset fast -crf 18 -pix_fmt yuv420p \ output.mp4 ``` ### Step 7: Review and iterate Extract a frame to verify: `ffmpeg -i output.mp4 -ss 4.0 -frames:v 1 check.png` Use the `image` tool to verify: - All text is visible and not cut off - Colors match the original screenshot - ASCII art is properly aligned - Background colors blend seamlessly (no visible rectangles) Send the video to the user. Iterate on timing, colors, and content based on feedback. ## Timing Guidelines | Element | Default | Range | |---------|---------|-------| | Typing speed | 35ms/char | 25-80ms | | Response delay | 150ms | 100-300ms | | Response line delay | 30ms | 20-50ms | | Pause between commands | 500ms | 300-1000ms | | Initial delay | 400ms | 200-600ms | | Final pause | 2500ms | 1500-3000ms | Target total duration: 15-30 seconds for social media clips. ## Output Formats - **MP4**: Best for Twitter/LinkedIn/Telegram. Use `-c:v libx264 -crf 18` - **GIF**: For README/docs. Use `ffmpeg ... -vf "fps=15,scale=480:-1" output.gif` - **WebM**: For web embedding. Use `-c:v libvpx-vp9 -crf 30` ## Reference Files - `references/ass-format.md` - ASS subtitle format reference - `scripts/make-art-overlay.mjs` - Generate ASCII art PNG overlays - `scripts/setup-deps.sh` - Install ffmpeg + ttyd + canvas