demo: commit the recording harness #8

Merged
claude merged 3 commits from demo/recording-harness into main 2026-09-22 19:42:00 -04:00
Contributor

The demo tooling only existed in a session scratch directory, which is temporary. This puts it in the repo so the video can be rebuilt.

Terminal only, no screen capture and no video editor:

tmux ──▶ asciinema ──▶ agg ──▶ ffmpeg ──▶ mp4
  │                                        ▲
  └─ left: driver   right: journal pane    │
     xAI /v1/tts ──▶ wav per beat ─────────┘

The left pane runs the loop against a live ZVM; the right pane polls the VPG journal so the tagged checkpoint appears on camera as it lands.

Narration stays in sync without being predicted

The driver writes marks.jsonl as it runs, one line per beat with the real elapsed time it started, and mux_vo.py delays each clip to its recorded mark. A slow API call or an FLR mount that takes longer than usual does not drift the audio.

Two constraints that are easy to get wrong, both written down in the README:

  • agg --idle-time-limit must exceed the longest pause (the scripts pass 3600). The default is 5s, which compresses idle time and silently breaks the mapping between wall clock and video time.
  • Each beat holds for its narration length, so no line is cut off mid-sentence.

Check alignment after a mux by measuring the FLR wait: speech sits near -22 dB, a correctly aligned gap reads about -91 dB.

Two narration corrections included

  • The script claimed the changed file's "only other copy is in last night's backup". That is false, and it gives away the argument the demo exists to make: Zerto has a copy from seconds before the change. d5 now draws the contrast instead of conceding it. d2 had the same problem in a quieter form and was cut.
  • The pronunciation map made the voice say "vem". The replace map takes a phrase and a pronunciation, so {"VM": "vee em"} is spoken as one run-together word. Expanded to "virtual machine".

Secrets

demo_win.json carries live guest credentials, so only an example with placeholders is committed and the real file is gitignored, along with the generated wav, cast, gif and mp4. The xAI key path and voice id come from the environment instead of being hardcoded to one machine. I grepped the committed tree for credentials before pushing.

🤖 Generated with Claude Code

https://claude.ai/code/session_016yVfC5nvZowoLFnEGWhLGn

The demo tooling only existed in a session scratch directory, which is temporary. This puts it in the repo so the video can be rebuilt. Terminal only, no screen capture and no video editor: ``` tmux ──▶ asciinema ──▶ agg ──▶ ffmpeg ──▶ mp4 │ ▲ └─ left: driver right: journal pane │ xAI /v1/tts ──▶ wav per beat ─────────┘ ``` The left pane runs the loop against a live ZVM; the right pane polls the VPG journal so the tagged checkpoint appears on camera as it lands. ## Narration stays in sync without being predicted The driver writes `marks.jsonl` as it runs, one line per beat with the real elapsed time it started, and `mux_vo.py` delays each clip to its recorded mark. A slow API call or an FLR mount that takes longer than usual does not drift the audio. Two constraints that are easy to get wrong, both written down in the README: - **`agg --idle-time-limit` must exceed the longest pause** (the scripts pass 3600). The default is 5s, which compresses idle time and silently breaks the mapping between wall clock and video time. - **Each beat holds for its narration length**, so no line is cut off mid-sentence. Check alignment after a mux by measuring the FLR wait: speech sits near -22 dB, a correctly aligned gap reads about -91 dB. ## Two narration corrections included - **The script claimed the changed file's "only other copy is in last night's backup".** That is false, and it gives away the argument the demo exists to make: Zerto has a copy from seconds before the change. `d5` now draws the contrast instead of conceding it. `d2` had the same problem in a quieter form and was cut. - **The pronunciation map made the voice say "vem".** The `replace` map takes a phrase and a pronunciation, so `{"VM": "vee em"}` is spoken as one run-together word. Expanded to `"virtual machine"`. ## Secrets `demo_win.json` carries live guest credentials, so only an example with placeholders is committed and the real file is gitignored, along with the generated wav, cast, gif and mp4. The xAI key path and voice id come from the environment instead of being hardcoded to one machine. I grepped the committed tree for credentials before pushing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016yVfC5nvZowoLFnEGWhLGn
claude added 3 commits 2026-09-22 19:41:54 -04:00
The demo tooling only existed in a session scratch directory, which is
temporary. This puts it in the repo so the video can be rebuilt.

Terminal only: tmux drives a two pane session, asciinema records it, agg
renders it, ffmpeg encodes it. The left pane runs the loop against a live
ZVM, the right pane polls the VPG journal so the tagged checkpoint appears
on camera as it lands.

Narration is synthesised per beat and aligned to marks the driver writes
while it runs, rather than to predicted timings, so a slow API call or an
FLR mount that takes longer than usual does not drift the audio. Two
things that has to respect are written down in the README: agg's
idle-time-limit must exceed the longest pause or it compresses idle time
and breaks the wall-clock mapping, and each beat holds for its narration
length so no line is cut off.

demo_win.json carries live guest credentials, so only an example with
placeholders is committed and the real file is gitignored, along with the
generated wav, cast, gif and mp4.

The xAI key path and voice id come from the environment now instead of
being hardcoded to one machine.

Also records the narration gotchas that cost time: mapping an acronym to
run-together phonetics ({"VM": "vee em"}) is spoken as one word, "vem";
prose written for the page sounds robotic read aloud; and volumedetect
reports no samples when aimed at a file whose first stream is video,
which makes a working audio track look silent.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016yVfC5nvZowoLFnEGWhLGn
The narration said the changed file's "only other copy is in last night's
backup". That is false, and it gives away the argument the demo exists to
make: Zerto has a copy from seconds before the change. That is the whole
point.

d5 now draws the contrast instead of conceding it. Backup has last night,
hours old. Zerto has seconds before the change.

d2 had the same problem in a quieter form, asserting there was "no other
copy of that file anywhere" while Zerto was already protecting the machine.
Cut, since d5 carries the comparison.

Also fixes the pronunciation map that made the voice say "vem". The
replace map takes a phrase and a pronunciation, so {"VM": "vee em"} is
spoken as one run-together word. Expanded to "virtual machine".

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016yVfC5nvZowoLFnEGWhLGn
zerto_recover_file no longer writes the file to this host and hands back a
path, because a path here means nothing to a caller elsewhere and letting
the caller choose it was an arbitrary write. Both drivers still read
rec["path"], so they broke.

They now use the returned content. A small recovered_bytes() helper in each
driver decodes the text or base64 form, so the Windows copy-back keeps
shipping exact bytes rather than letting PowerShell rewrite line endings,
which is the bug that put a stray CR in an earlier take.

The Linux driver writes the bytes to a local file before scp, since scp
needs something on disk to send.

Verified against a live recovery: the helper returns 164 bytes whose sha256
matches the one the server reported, and the keys the on-screen show()
filter uses are all still present.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016yVfC5nvZowoLFnEGWhLGn
claude force-pushed demo/recording-harness from 2d9322fa0f to 3e7b777e53 2026-09-22 19:41:54 -04:00 Compare
claude merged commit 5916cdf8a2 into main 2026-09-22 19:42:00 -04:00
claude deleted branch demo/recording-harness 2026-09-22 19:42:00 -04:00
Sign in to join this conversation.