8Examples / blog
Marketing · AI-assisted workflow

A Two-Minute Product Tour, Narrated by OpenAI's Voice

Nestled needed a walkthrough that shows both sides of the product in under two minutes. I did not record my screen and I did not record my voice. The narration was written, the voice was generated, and a browser drove the real site while a script filmed it.

By Sean Bennett · September 3, 2026 · 7 min read

Nestled is a daycare waitlist and matching platform. Families join their city’s waitlist once; daycares and dayhomes see who is looking and make real offers, with a start date and a monthly rate; families book a tour and say yes; Nestled invoices the provider a finder’s fee when a spot fills. Two sides, two dashboards, one story that only makes sense if you see both.

The finished tour is at daycare.fusenv.com/walkthrough: one minute fifty-six, 1280 by 720, English captions, and a chapter list under the player so you can jump to the part you care about.

The Nestled walkthrough page: a heading reading See Nestled in action, the video player, and a description of the two-minute narrated tour
The walkthrough page. The video, its captions track, and the chapter list all come out of the same script.

The narration comes first

The mistake I have made before is recording the screen and then trying to talk over it. The picture sets the pace, the words rush to keep up, and the result sounds like it. This time the words came first: twelve short lines, each one describing exactly one thing that will be on screen when it is spoken. The first and last, for the shape of it:

Welcome to Nestled, a daycare waitlist and matching platform. Families join their city’s wait list once, and daycares come to them with real offers.

And that’s Nestled. One wait list, real offers, tours, and invoicing, all in one place. Free for families. Providers pay only when a spot fills.

Twelve lines is 105 seconds of speech. A detail you can see in the captions: "wait list" is two words throughout. A synthetic voice reads "waitlist" a little too fast; splitting it made the voice slow down and land on the noun.

The voice

Each line went to OpenAI’s speech API on its own and came back as its own audio file. One request per line, not one for the whole script, because the length of each audio file is the length of its shot. The audio decides the timing of the video, not the other way round.

// One request per narration line. The instructions field is the
// direction you would give a voice actor; the model follows it.
const res = await fetch("https://api.openai.com/v1/audio/speech", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "gpt-4o-mini-tts",
    voice: "nova",
    input: line.text,
    instructions: "Warm, unhurried, like a friend showing you around.",
    response_format: "mp3",
  }),
});
await writeFile(`audio/${line.id}.mp3`, Buffer.from(await res.arrayBuffer()));
A Codex CLI session in the Nestled repository: the prompt asking for a narrated walkthrough with OpenAI text-to-speech, a five-step plan, and the narration script generating twelve audio files with their durations
The session, recreated from the transcript. Twelve lines in, twelve audio files out, each with its measured length.

The instructions field is the part worth knowing about. It takes plain direction, the kind you would give a person in a booth, and the model honours it. "Warm, unhurried" is a different read from "energetic, upbeat," and for a product about finding childcare the first one is right.

Filming the real site

The picture is not a mock-up. A Playwright script signs in to the live application against its seed data and records one clip per narration line with recordVideo at 1280 by 720. The seed data gives the tour its cast: Pat runs Sunny Days Daycare, Marisol is Ada’s mom. Each clip does the one thing its line describes, then holds the shot for the length of the line plus a beat.

Nestled provider dashboard: Sunny Days Daycare making an offer to a family on the waitlist with a start date, a monthly rate, and a note
0:38 · Pat makes Ada's family a real offer.
Nestled family dashboard: the offer from Sunny Days with the daycare's address on a map and directions from the family's postal code
1:00 · The family sees the offer, with the address and a map.
Nestled tour booking: picking an open time and confirming
1:10 · Booking a tour: pick an open time, confirm.
Nestled provider dashboard after acceptance: the offer marked accepted, contact details unlocked, and the tour on the calendar
1:39 · Back on the provider side: accepted, contact unlocked, tour booked.

Because every shot is the actual product, the video cannot drift from the truth. When the dashboard changes, the recording script runs again and the tour changes with it. There is no stale screenshot to notice six months later.

Fitting the picture to the voice

The last step is arithmetic. For each line, ffmpeg trims the clip to the length of that line’s audio plus a 0.6-second pause, concatenates the twelve clips, lays the twelve audio files over them with the same pauses, and encodes H.264 and AAC with the index at the front so the file streams. The same timings are written out as a WebVTT captions file, which is why the captions match the voice to the frame and why the page can build a chapter list from the cue start times.

WEBVTT

1
00:00:00.000 --> 00:00:09.300
Welcome to Nestled, a daycare waitlist and matching platform. Families join
their city's wait list once, and daycares come to them with real offers.

2
00:00:09.903 --> 00:00:15.903
Let's start on the provider side. Pat runs Sunny Days Daycare, and logs in
to their dashboard.

Look at the gap between cue one ending and cue two starting: 0.6 seconds, every time, all the way down. That is not an editor’s hand. It is a constant in a script.

The Codex CLI session continuing: the recording script listing twelve clips with their lengths, the assemble step running ffmpeg and writing the MP4, the VTT captions, and the poster, then the walkthrough page being added and committed
Record, assemble, publish. Recreated from the transcript; the line lengths, output sizes, and the page are the real ones.

What I would keep, and what I would change

Keep: words first. Everything downstream got easier because the narration was fixed before a single frame existed. The voice set the tempo, the recording matched it, the captions fell out for free.

Keep: the real site. A tour recorded from seed data is a regression test with a soundtrack. If a flow breaks, the recording script breaks, and you find out before a customer does.

Change: hold a little longer on the money. The offer card with the start date and monthly rate is the moment a provider decides Nestled is for them. It gets 12 seconds; it could take 15. That is a one-word change in the narration and a re-run.

Change: a second voice for the family side. The switch from Pat to Marisol is carried by one line of narration. Two voices would carry it in the sound as well, and the API makes that a per-line parameter.

Watch the whole thing at daycare.fusenv.com/walkthrough. Then notice that nobody in it ever picked up a microphone.

Comments 0

No comments yet. Start the conversation.

Leave a comment

Site author? Sign in to reply officially.

Commenting is temporarily unavailable while CAPTCHA is being configured.