Source: https://jimbir.ch/blog/screencast-skills/

[Back to blog](https://jimbir.ch/blog) AI

# Automating screen recordings using Screencast Skills

By Jim Birch Jul 31, 2026 4 min read

![Automating screen recordings using Screencast Skills](https://jimbir.ch/assets/blog/screencast-skills.avif)

Marcus Johansson published a Claude Code skill called [`drupal-tutorial-video`](https://github.com/ivanboring/drupal-skills/blob/main/skills/drupal-tutorial-video/SKILL.md). You point it at a Drupal module and it produces a narrated 1920×1080 MP4 of the setup: a real browser, a visible cursor, text typed character by character, an ElevenLabs voice-over, a caption bar across the bottom, all concatenated into one video. I watched the output and had two thoughts at once. First: this is great. Second: why is this only for Drupal?

## What Marcus built

The clever part of the original is how it makes the cursor look human. It runs a headless browser inside the ddev web container on a virtual display, and it splits the work between two tools. One is `agent-browser`, the *brain*. It reads the page’s accessibility tree and hands back the on-screen coordinates of an element, but its clicks are synthetic and invisible.

The other is `xdotool`, the *hands*. It moves the real X11 pointer to those coordinates in small steps, clicks, and types with a per-keystroke delay. Because the pointer is real, `ffmpeg` captures it. What moves on screen is exactly what clicks.

It has a second good idea baked in: it records one *beat* at a time, a sentence of narration and its matching action, and it length-fits each beat’s video to its narration so the words never drift out of sync with the picture. Terminal commands it won’t record at all; those become still “command cards” instead. And it’s Drupal all the way down. It reads `.info.yml` files and config forms to derive the real setup steps, and pre-seeds Drupal’s AJAX forms with `drush` so they behave on camera.

## A great foundation and example, but different than my needs

My job is different. I make short training videos about AI tooling. How to add an MCP server in Claude Code, how to use one in Claude Desktop, etc. And for that, Marcus’s skill was the wrong shape in three specific ways:

-   It **refuses to record terminals**. But Claude Code *is* a terminal. The thing I most need to show is the exact thing it turns into a static card.
-   It records the browser **only inside a ddev Linux container**. Claude Desktop is a native macOS app. It can’t live in that container.
-   It’s **Drupal-specific** end to end: the reads, the pre-seeding, the assumptions.

So I did what you do when a tool is 80% right: I kept the ideas and rebuilt the shape. The result is two skills.

**`screencast-storyboard`** is the authoring half. You tell it what the demo should cover; it reads the tool’s *real* README, install command, and config, drafts a storyboard, and then stops at an approval gate.

**`screencast-tutorial-video`** is the production half, and it runs natively on the macOS host with no container. The core insight I took from Marcus is that you don’t need one recording rig. You need the right engine per surface:

-   **Terminal** → a [VHS](https://github.com/charmbracelet/vhs) `.tape` file. Declarative typing, deterministic, and it re-renders in seconds.
-   **Native app** (Claude Desktop) → ffmpeg still-motion: a screenshot with an optional zoom and a highlight box.
-   **Browser** → Playwright to locate and drive, recorded at 1080p.
-   **Abstract command** → a command card, same as the original.

I also expanded the option to use ElevenLabs *or* OpenAI for the voice-over.

## Using presets for theming

Once it worked, I wanted the *next* video to start where this one left off. I wanted to be able to define the same voice, same pronunciation, same intro card without re-deriving any of it.

So the skill loads a **preset**: a small file of house defaults (engine, voice, tone, resolution) plus a brand-notes doc for the parts that can’t be an environment variable, like the pronunciation lexicon and the intro/outro pattern.

Point it at a different preset and you get a different client’s or team’s style. There’s a short guide in the repo for writing your own.

## See it in action

Here is the demo video, produced end to end by the skills themselves:

## Credits and code

Thanks to [Marcus (ivanboring)](https://github.com/ivanboring/drupal-skills) for the original `drupal-tutorial-video`. I tried a few months ago to build a skill like this and failed spectacularly.

The skill is on GitHub, MIT-licensed, and works on a stock macOS setup: **[github.com/kanopi/screencast-skills](https://github.com/kanopi/screencast-skills)**.
