Skip to main content
A demo shows the screen behavior for each acceptance criterion as its own chapter. A spoken line says what happens. The chapter lists the checks the recording ran. Each chapter is an ordinary video artifact. It is the video proof for its criterion, so no proof rule changes. A chapter with a failed check is never bound to its criterion. You record the demo in three steps:
  1. Write a Playwright test with @outerlayer/playwright.
  2. Run the test. It writes a video and a manifest.
  3. Run outerlayer emit demo on the manifest.
Demos cover browser apps. A runner build image has everything the command needs. On your own machine, install ffmpeg and espeak-ng first.

Write the test

Install the package next to your Playwright setup. It needs @playwright/test 1.50 or later.
Import test and expect from the package, not from @playwright/test. Add one demo.chapter for each criterion.
demo.chapter(criterionId, title, narration, body) takes these arguments: The chapter starts when body starts and ends when body ends. Each expect that runs inside body is recorded as a check of the chapter. A failed expect fails the test, as it does without this package. The failed check is still in the manifest. Follow these rules for chapters:
  • Give each criterion one chapter.
  • Put a chapter with no criterion first. Only the first chapter may have none.
  • Keep the narration short. The speech must end before its chapter does. See Fit the narration.
  • Do not use a viewport larger than you need. A clip over 8 MiB is refused.

Run the test

Run the test as usual.
The package turns video recording on. When the test ends, its output folder holds a demo folder with two files:

Emit the demo

Run the command on the manifest.
The command does these steps:
  1. It checks the manifest, the video and the programs it needs. It refuses here, before it uploads anything.
  2. It turns each narration line into speech on your machine.
  3. It cuts the video into one clip for each chapter. Each clip is WebM with VP9 video and Opus audio.
  4. It emits each clip as a video artifact.
  5. It emits the manifest as the demo record, with the artifact id of each clip added.
A chapter whose checks all passed is bound to its criterion. A chapter with a failed check, and a chapter with no criterion, is stored with no criterion bound. When a chapter has a failed check, the command stores everything and then exits 1. It names the chapter and the failed check. Fix the app, record again and run the command again. You can run the command again with the same manifest, video, item and pull request. This also applies after an upload failed part way. A clip that is already stored keeps its artifact id, and the command does not store it a second time. Inside a recorded session, the clips and the record are queued. They upload on the next outerlayer sync. Outside a session they upload at once. The full flags are in outerlayer emit demo.

Fit the narration

Speech starts 0.2 seconds into its chapter and ends at least 0.2 seconds before the chapter ends. Speech that is too long for its chapter is sped up, to at most 1.3 times. Speech that is still too long makes the command refuse. It names the chapter and says by how many seconds the line is too long. To fix a refusal, shorten the line or lengthen the chapter. The command never stretches the video.

Install the programs

The command runs ffmpeg and espeak-ng as separate programs. ffprobe comes with ffmpeg. A narrated run needs both. A run with --no-narration needs only ffmpeg.

Linux

Use your package manager.
On Fedora, ffmpeg comes from the RPM Fusion repository. See the Fedora documentation to enable it.

macOS

Use Homebrew.

Windows

Install ffmpeg with winget, then install eSpeak NG from its Windows installer.
Download the eSpeak NG installer from the eSpeak NG releases page. Open a new terminal after both installs. Then check that each program is on PATH.
If a command is not found, add its folder to PATH. The ffmpeg folder is the bin folder of the winget package. The eSpeak NG folder is C:\Program Files\eSpeak NG.

Download the voice pack

The first narrated run downloads the voice pack to ~/.outerlayer/voice/. It is about 400 MB. It holds the Kokoro-82M speech model, one voice and the ONNX Runtime that runs the model. The command shows progress and resumes a broken download. The command checks every file of the pack against a pinned sha256 on each narrated run. When a file does not match, the command refuses and names the file. Delete that file to download it again. After the first run, narration needs no network, no account and no key. To work offline from the start, set OUTERLAYER_VOICE_MIRROR to the address of a server that holds the pack files. The pinned hashes still apply to every file the mirror serves.

Skip the narration

Pass --no-narration to store silent clips.
This needs no espeak-ng and no voice pack. It downloads nothing.

Run in a build

The runner build image holds ffmpeg, espeak-ng and the voice pack. A build records and narrates a demo with no network and nothing else to install. The evidence skill tells an agent to record a demo for the criteria whose behavior shows on screen. See also: Prove the work, outerlayer emit demo.