GitHub README to video
The person gives you a GitHub repo (a link, or its README). You deliver a 30 to 60 s video that explains what the repo gives its users, in the repo's own brand: a generated, stylized world that acts out what the project does, a narrator, titles and motion graphics that name the real things it ships (commands, modules, skills, features), captions, and an end card with how to get it. Built for gift videos to open-source maintainers, launch videos for a repo, and "here's what this project does" explainers.
The backbone is recipe-script-to-video with voiceover only (nobody speaks on screen)
plus the compositor for every word on screen. Each stage below is gated on the person.
Steps
- Read the repo, not just the README. Fetch the README and anything it links that
carries the product (a
skills/ordocs/index, the main entry file, the latest release notes, the commit log of the area your pitch is about). Write down the facts you'll put on screen: the project's exact name and casing, the install or run command verbatim, counts (modules, skills, stars) with the date you read them, the licence, and the 5 to 8 named parts a viewer should remember. Check every claim the brief makes about the repo against the repo itself. A plan written last month that says "it has no X yet" is often wrong by the time you build: look for X before writing a line that pitches it. Save the README and the files you used insource/. - Capture the brand from the project's own site (the README's homepage link) or,
failing that, its social card. Pull the CSS tokens rather than eyeballing a
screenshot: background, text, accent colours as hex, the font families (often a
Google Fonts URL in the page head), and the site's one signature element (a terminal
window, a code card, a chip style). Take one screenshot of the hero for reference.
Write it all to
refs/brand.md. No site: use the repo's language colours and a mono plus a sans, and say so. - Script and shot list (gate). About 2.7 words per second: 110 to 120 words for 45 s. One idea per line; each line names a real part of the repo. A metaphor world carries the visuals (a town where each shop is a module, a workshop, a kitchen): each part of the repo gets a place or object in it, and one small recurring character plays the user's agent or the user. Shots of 2 to 6 s, one per line or half-line; three quick 2 s shots make a good "it does all of this" montage. Put the facts on screen, not in the pictures: stills carry no words.
- Look (gate): three style frames of the opening shot in three looks, one prompt
each with identical scene text (
nano-banana-prompt-format). Stylized, never photoreal. Then a turnaround sheet of the character from the picked frame, with anything you don't want (a mouth, a logo) stated as the clean state, and single views cut from it for every later reference. - Voice (gate,
guide-cast-a-voice): three auditions of the first two lines. Then voice the whole script in one take with the with-timestamps TTS endpoint, so the character alignment gives you word times for free. Spell out what the voice would misread (README as "read-me", CLI names, version numbers). Check the take with a free local transcript: every word, no tag read aloud. - Stills (gate): one per shot, the style frame and character views as references, the scene described with camera, positions and which way the character faces. Show all of them on one approval page with each shot's line beside it; flag what you'd change rather than silently re-rolling.
- Animate (H3 Max image-to-video,
h3-max-image-to-video, prompt perh3-prompt-format): every shot at once, a little longer than its window. Give the character a motion that fits its material (a wind-up toddle for a tin toy). Check each clip's first, middle and last frame on one sheet. A call that never lands: readhistoryfor its status (it may have failed and been refunded) and re-run it with a new seed rather than waiting. - Rough cut: cut each shot at the start of its phrase (alignment time minus about 0.1 s), hold a short clip on its last frame, lay the voice over the clips' own sound at about a fifth, normalize to -16 LUFS, and add a 2 s hold at the end for the card. Keep the cut in a script so a re-rendered shot drops in by re-running it.
- Titles, motion graphics and captions (gate,
hn4a-compositor-motion-graphics, captions perhn4a-compositor-in-scene-titles), one spec over the rough cut, written by a script that cues every layer from the word times:- Open on who and what: the maintainer's name, the project's name in its headline font, one line of what it gives the user with the number in the accent colour, and the install command in the brand's signature element.
- Name each part as the narrator says it: a chip with the part's real
identifier (
seo-audit,src/router,--watch) pops on just before the word. That is what makes it clear what the project actually provides. - Lists build on the words, one item per beat.
- Captions from the same word times, styled in the brand's mono or sans, in the lower third, kept clear of the chips. Leave them off only if the person says so.
- End card: a short headline, the install command again, the repo URL, and a credit line.
- Everything over the footage sits on the brand's card or chip background: bare text over a detailed stylized scene is unreadable. Check stills at every title, fix, then show the spec live on a review page before rendering.
- Render and deliver (
guide-prepare-renders-for-delivery): the 16:9 master, a small copy for chat, and a 9:16 cut if the person posts vertically. Draft the note that goes with it in the person's voice, leading with the video and with no claim the repo contradicts.
Choices this recipe makes
- The repo's own words and identifiers on screen, the metaphor in the pictures.
- The brand comes from the project's site CSS, not a guess.
- Word times from the TTS alignment, not a paid transcript.
- Stills and renders carry no text; every word is composited.
Dead ends
- Pitching a feature the repo "doesn't have yet" from an old plan: the repo had shipped it months earlier. Read the repo first.
- A compositor text layer whose type is all in
htmlstill needs a loaded family in its ownstyle.font, or it falls back to Times andstill/renderrefuse. - Arrow lists drawn straight over a busy toy scene: unreadable; on chips they read.
- A chip cued exactly on its word in a 2 s shot was on screen under a second: cue quick-montage chips from the shot's start instead.
- Character turnarounds sometimes come back as a 4x2 grid instead of 2x2; cut views by the grid you actually got.
- Waiting on
taskswhile many renders run from several sessions: it timed out for half an hour on a call that had already failed. Checkhistory.


