evo.videostroll

The agent records the walkthrough itself.

Ask an AI agent for a walkthrough of a website and it writes you a list of steps. This gives it a camera instead: it drives a real browser, moves a visible cursor, speaks its narration aloud, and hands back an MP4 with captions already timed to the words.

Overview

evo.videostroll is two things that ship together. The MCP server is the engine — browser, cursor, recording, speech, captions, assembly — and any MCP client can call it. The Claude Code skill is the method: it teaches the agent how to make a walkthrough worth watching, which is the half a recorder cannot supply. The server without the skill is a capable but undirected recorder; the skill without the server has nothing to record with.

The agent decides what to show and what to say. The tool makes it a video — and because the whole run is described by a storyboard file, the same walkthrough re-renders when the site changes rather than being re-recorded by hand.

Its own output, not a screen capture of it: a tour of its documentation — twelve steps, seven chapters, a minute and three quarters, one Edge voice. The cursor is the agent's and the captions are burned in from the same words it spoke. Nothing was edited afterwards.

// Beta and open source as of 13 September 2026 — the commands below are the real ones, and the repository is public.

The problem

Ask an AI agent to show you around a product and it writes a list of steps. That is the wrong artefact: the person who needed the walkthrough is the person least able to follow a list of selectors, and the people a demo is actually for — a customer, a new hire, a hiring manager — watch rather than read.

Making the video by hand is three passes, not one. Record the screen, write and record narration against it, then time captions to both. Every pass has to be redone when the interface moves a button, so demo videos rot quietly and the honest ones get deleted rather than maintained.

The part nobody does is the checking. A recorded demo can be confidently wrong — the voice says “now we are on the settings page” over a screen that never navigated, and nothing in the pipeline disagrees. That failure is invisible to the person who made it, because they know what they meant. It is obvious to everyone else, and it is the one that costs credibility.

So the design goal was not “record a browser”. Plenty of tools do that. It was: let an agent decide what is worth showing, make it say it in sentences a person would say out loud, and then prove that what was said matches what was on screen — before anyone watches it.

What one run produces

One walkthrough leaves four files in a single output folder. The video is the deliverable; the other three are what make it maintainable.

File What it is
walkthrough.mp4 H.264 video with AAC narration, the cursor visible, captions optionally burned in.
walkthrough.srt / .vtt Captions with timestamps, one cue per narrated sentence.
walkthrough.json The manifest: every step with its start and end time, narration, action, URL and a thumbnail — the timestamps as data, for any other app to use.
walkthrough.storyboard.json The exact storyboard that was rendered, so the run reproduces.

How it works

Four decisions do most of the work, and each of them exists because the obvious alternative produces a video that looks fine and is quietly wrong.

  • Selectors come from the page, not from pixels. Every tool call returns the page's accessibility snapshot — roles and names — and the agent picks its target from what the page actually said: role=link[name="Projects"]. A coordinate would record a click on whatever moved into that spot.
  • The voice sets the pace. Narration is synthesised before the step is recorded, and the step is held until the speech finishes. Nothing is cut off mid-sentence, and the captions are timed from the speech engine's own word boundaries rather than estimated from length.
  • The cursor is part of the recording. It moves, hovers, and clicks where the narration points, so the viewer sees intent rather than a jump cut between two states.
  • No provider quietly falls back. A silent video where a voice was asked for is a wrong-looking success, so a failed voice fails the step with a message naming the alternatives.

Using it

1 — Build the server and register it

The server is a Node process an MCP client starts on demand. Chromium is Playwright's, installed once; FFmpeg ships with the package.

cd server
npm ci
npx playwright install chromium
npm run build

Then point a client at the built entry point — in Claude Code, a project's .mcp.json:

{
  "mcpServers": {
    "videostroll": {
      "command": "node",
      "args": ["C:/path/to/evo.videostroll/server/dist/index.js"]
    }
  }
}

2 — Install the skill

The skill is one Markdown file. Copied into the skills folder, it is what turns “record a walkthrough” into a method the agent follows.

mkdir -p ~/.claude/skills/videostroll
cp skill/SKILL.md ~/.claude/skills/videostroll/SKILL.md

3 — Ask for a walkthrough

From there the request is ordinary English — “record a two-minute walkthrough of the projects page for someone who has never seen the site” — and the skill puts the agent through four beats:

  • Reconnoitre. Open the site and read the snapshot. Observing records nothing, so it costs only time to look before deciding anything.
  • Storyboard. Four to ten steps, one idea each, drafted before a single one is recorded. If the goal will not fit on one line, there is no walkthrough yet.
  • Record. One call per step: the narration, and the action on screen that demonstrates that sentence.
  • Verify. Read the manifest back and check what was said against what was shown. A narration that names something the viewer cannot see is the defect this catches.

The tools behind those beats are videostroll_start, videostroll_observe, videostroll_step, videostroll_finish, videostroll_abort and videostroll_render.

4 — Or write the storyboard yourself

An interactive run emits the storyboard it just recorded, and that file re-renders to the same video from the command line. Edit the steps that changed and render again — there is no need to redo the walkthrough because one sentence was wrong.

cd server
npm run render -- ../examples/storyboards/www-evomedia.json ./output/www

A step is small enough to write by hand:

{
  "id": "projects",
  "chapter": "Projects",
  "narration": "The projects page lists every product in the fleet, each with a stage label.",
  "actions": [
    { "type": "goto", "url": "https://evomedia.net/projects.html" },
    { "type": "move", "target": { "selector": "role=heading" } },
    { "type": "scroll", "deltaY": 500, "durationMs": 1200 }
  ]
}

Choosing a voice

The default provider offers 322 voices, 47 of them English. Picking one from a list is guessing, so there is a picker: filter by locale, gender or character, type the sentence you actually intend to use, hear it at the rate you intend to use, and copy the finished line into a storyboard. The preview goes through the same provider the recorder does, so what you hear is what gets recorded.

The picker, filtered to English: 42 of 322 voices. The page binds to localhost only, and the preview endpoint refuses to speak anything credential-shaped.
Provider Cost Needs Word timing
edge (default) Free Network, no key Yes — captions timed from the engine
piper Free The binary and one voice model, offline No
silent Nothing Synthetic — what the test suite uses

A single walkthrough can use more than one. A step may name its own voice, the override lasts exactly that step, and anything it does not name it inherits — so two narrators can hand off mid-video.

Sites behind a login

Most things worth demonstrating are behind a sign-in, and the safe way to record them is the one where the tool never learns the password. It does not type one, and a storyboard never holds one. You sign in yourself, once:

npm run login -- https://app.example.com

A real browser window opens. Sign in however the site asks — password manager, second factor, SSO redirect — and press Enter. The session is written to a storage-state file that a storyboard then points at, and the recorder reuses it.

That file is a live session, and it is treated like a password. The helper only writes it where git already ignores it and refuses anywhere else; it prints hostnames and counts but never a cookie value; and it refuses to save a file that captured nothing, which is exactly what a half-finished sign-in produces. Sessions expire, so a check runs before a render rather than halfway through one:

npm run login -- --check auth/app.example.com.storage-state.json

Measured impact

The figures below are from the demo at the top of this page — one real walkthrough of the documentation site, recorded on 13 September 2026. They are measured, not estimated, and they come from the manifest the run wrote rather than from a benchmark built to flatter the tool.

  • One pass, 109 seconds — twelve steps, seven chapters, twenty-two caption cues. The MP4, a second MP4 with captions burned in, .srt and .vtt, a manifest and the storyboard, all from a single command.
  • The storyboard is 7.4 KB, and it is what makes a change cheap. That demo was cut twice in one afternoon and neither cut was a re-recording: correcting four lines of narration, and later inserting a thirteenth idea, were each one edit and one render.
  • Every step is checked against its own narration. The manifest records the URL, the page title and the frame count each step actually captured, so “now we are on the setup page” is verified against the page that was on screen. Frame counts ran 3 to 161; a step that captures only its two bookends never repainted, which is the tell that something was narrated over a dead screen.
  • 240 tests across 24 files, run on every pull request.

The honest framing matters more than a headline. This is not faster than a person with a screen recorder — a practised person is quick, and for one take they will beat it. What it buys is the second take and the twentieth: the walkthrough survives the site changing, because the storyboard is edited rather than the video re-shot, and a claim the narration makes is checked against what the browser actually did before anyone watches.

A worked example of the checking earning its keep. The narration rule said to write “M P four” so the voice would not read MP4 as a word. Measured against the speech service — total duration and the word boundaries it reports — the two forms turned out to be the same utterance, identical to the millisecond. The respelling changed nothing for the ear and put “M P four” in the captions, where a viewer reads it. The rule had been wrong since it was written, it looked reasonable, and only measurement said otherwise.

Technology stack

  • TypeScript / Node.js — the server, its tools, and the command-line renderer
  • Model Context Protocol — the tool surface, driven by any MCP client
  • Playwright — the browser, the accessibility snapshot, and the video capture
  • FFmpeg — assembly: video, narration track, and burned-in captions
  • Edge neural voices / Piper — speech, with word boundaries where the provider reports them
  • JSON Schema + Zod — the storyboard contract, validated at the tool boundary
  • Vitest — including a run driven end to end by a real MCP client over stdio

Want the whole picture? See my employment history, résumé, or get in touch — I'm available for new roles.