DEV Community

douzatan
douzatan

Posted on

Our Tutorial Videos Rotted Every Release, So We Stopped Filming Them

Every release used to break a video.

We maintain a developer tool, and the short explainer videos attached to it stayed accurate for about six weeks. Then a flag got renamed, a panel moved, the default changed, and the video was quietly wrong. Nobody volunteered to re-record it, because re-recording meant blocking an afternoon, setting up a mic, and doing five takes to get ninety seconds without stumbling over the word "idempotent." So the wrong video stayed up until a user pointed it out in an issue, and then it usually got deleted rather than remade.

The docs never had this problem. A doc changes in a pull request. Someone reviews the diff, it merges, and the site rebuilds. Video had no equivalent of that loop, so video rotted, and after the second round of rot we stopped making it. That is how a team ends up with docs that are current and a YouTube playlist that is a museum.

What eventually fixed it was not better recording discipline. It was removing the recording step entirely, so the video became something we regenerate from text like everything else we ship.

Why we wanted a presenter and not just a screencast

The obvious answer is a screencast with a voiceover. We had those. They are fine for "here is the sequence of clicks," and they are genuinely better than a talking head for anything where the user needs to see the actual interface respond.

They are worse for the conceptual half. When the video is explaining why a feature exists, what the mental model is, or which of two approaches you should pick, a cursor moving around a screen while a disembodied voice talks is hard to stay with. I notice it in my own viewing: I keep the tab open, I stop watching, I skim the transcript instead. A face delivering the explanation holds me longer. I do not have clean numbers from our own content to prove this, and I am suspicious of anyone who claims they do, but the pattern was consistent enough that we kept wanting the presenter format and kept failing to produce it.

The reason we failed was mundane. A talking head requires a specific human being to be available, on camera, on a schedule. On a small team, that human is also the person shipping the feature the video is about. Their time is the constraint, and video loses to shipping every single time. The format was not too hard for us. It was too dependent on a calendar.

Generating the presenter from the script instead

The change was using an AI talking head generator to produce the presenter, so the input is a script rather than a recording session.

The mechanics are dull, which is the point. You paste the script, pick a presenter from the built-in library, choose a voice, and it generates the talking-head video with lip sync. There is a setting for more natural expression so the delivery does not come out flat. You can also generate an avatar from a single photo if you want a consistent face that is specifically yours rather than one from the library, and you can put your own background behind it or drop in a brand kit so the clips in a series match. Output is an MP4 you download, plus a hosted link if you want to embed it.

The part that mattered for us: fixing a line means editing text and regenerating. Not booking a re-record. Not asking a teammate to sit down again for one sentence. That single property is what turned video from a project into a build step. When we renamed a flag last quarter, updating the video was a two-line diff in a script file and a regenerate, and it was done before the release notes were finished.

Scripts live in the repo now

Once video generation takes text as input, the script is source, so we treat it that way.

docs/
  videos/
    01-getting-started.script.md
    02-config-file.script.md
    03-ci-integration.script.md
    README.md          # voice, presenter, aspect ratio per series
Enter fullscreen mode Exit fullscreen mode

Scripts get reviewed in a pull request like anything else. If a PR changes a CLI flag and there is a script mentioning that flag, the reviewer sees both in the same diff, which is the thing that never happened when video lived in a folder on someone's laptop. We do not have automated generation wired to CI, and I would not pretend otherwise: someone still opens the browser, pastes the updated script, and regenerates. But the expensive part is gone, and the cheap part is a five minute chore rather than an afternoon.

A few things we learned about writing these scripts, none of which are obvious the first time:

Write for the ear, not the eye. Sentences you would happily publish in a doc are often too long to listen to. Read the script out loud once before generating and cut anything you run out of breath on.

Do not read code aloud. A synthesized voice narrating --max-retries=3 is unpleasant, and it is unpleasant when a human does it too. Say what the flag does, show the code on screen, and let the two work together.

Say numbers the way people say them. Written "v2.4.0" gets voiced in ways you will not like. Spell it out phonetically in the script and let the doc keep the clean version.

The scripts also gave us something we did not plan for. Because our docs are translated, we can generate the same video in other languages from a translated script with the same presenter, which is a lot more approachable than asking someone to re-record a tutorial in a language they do not speak.

Where it is genuinely not good

This puts a synthetic face on screen, so being straight about it matters more than usual for a dev audience, which is not a crowd that responds well to being sold to.

It reads as generated. Not badly, but if you look at it with intent, you can tell it is not filmed. For routine explanatory content that is fine and nobody has complained. For anything where you are the point, a conference talk, a project announcement you want to feel personal, a video where a user is deciding whether to trust you as a maintainer, film yourself or do not make the video.

It does not show your interface. The presenter explains, it does not demonstrate. For the click-by-click sections we still capture the screen with our own recorder and upload that footage, then shrink the avatar into a corner so the interface has the frame. Anyone expecting the tool to record their screen for them is expecting the wrong tool.

The output is only as good as the script. Our first attempt was lifeless because we fed it a doc page verbatim, and a doc page is written to be scanned, not spoken. Rewriting it as something a person would actually say fixed it. The tool has no idea what your users are confused about unless the script says so.

And on likeness: only build an avatar from an image you have the right to use. If it is a teammate's face, that needs their explicit yes, and the yes needs to cover the videos you are actually going to make with it. Putting a colleague's face on a video they never agreed to is not a shortcut worth taking.

If you want to try this

Do not migrate a whole channel. Pick the one video you already know is out of date and have been avoiding for a month, write the script as a real script rather than a pasted doc page, and generate a couple of versions on a free tier. Watch them with someone who has not read the script.

If the presenter reads as a deliberate choice rather than an accident, keep it for that format. If it reads as off, you have lost an hour and learned something. For us the test case was the getting-started video, the one that broke on literally every release, and it has been current for three releases running, which it never managed when it depended on somebody being free to film.

Top comments (0)