main
John Lauer Publish 1.2.4 21d335b 11d ago

name: demo-video-publishing description: >- The checklist for turning a screen recording into a video on a wiki page: brand-font labels and wrapped captions on a glow (gang-takes, never ffmpeg drawtext with a system font), adom-tts narration fitted to the cut (a demo video is never silent), the contact-sheet review, and the wiki README embedding rules that break on the first try (asset paths resolve from the page root even inside a sub-folder README, the sanitizer strips style so a video needs a width attribute, keyframes every second, verify the RENDERED page in a browser, never a curl of a URL you typed). Written on 2026-09-12 after a feature video shipped with DejaVu captions running off both edges, no narration, and a video tag pointing at files that did not exist. Trigger words: publish demo video, video on the wiki page, embed video in readme, sub-readme video, adom-video widget, captions for the wiki video, video captions font, captions cut off, caption overflow, add narration to the video, ffmpeg drawtext, brand fonts on video, video overflows the column, ralph test the wiki page, check the rendered page.

Parent skill: demo-authoring-skillpack

Publishing a demo video to a wiki page

Five rules. Each one was broken on 2026-09-12 by an AI that had the skills installed and did not open them; John's reaction was the reason this page exists.

1. Captions and labels: brand fonts, wrapped, on a glow. Use gang-takes.

  • Never ffmpeg drawtext with a system font (DejaVu, Arial, Liberation). The brand is Familjen Grotesk for labels, Satoshi for captions, JetBrains Mono for chips. gang_takes.py fetches them from wiki.adom.inc/static/fonts and converts woff2 to ttf itself; you do not need a TTF on disk.
  • Never a single unwrapped line: a caption longer than the frame runs off both edges. gang-takes wraps to a maximum width and stacks lines on a blurred dark halo so they read over busy UI.
  • A single recording is fine: split it into one clip per beat (ffmpeg -ss A -to B -c copy) and give each segment its label, chip, captions and narration. Colours are the wiki tokens (accent #00b8b0, dark #0d1117, text #e6edf3).

2. Narration is not optional

A demo video has an adom-tts voice. gang-takes synthesises each segment's narration, trims the silence, and speeds it up to +20% until it fits the measured cut; if it still does not fit it says so instead of padding. Run --measure first, write the lines to the printed lengths, then render. Spell out letters and numbers ("adom C L I", "three D"): see tts-pronunciation. Check the track exists and is not silent: ffmpeg -i final.mp4 -af volumedetect -vn -f null - (mean above -35 dB).

3. Look before you ship: the contact sheet

Frames two seconds after every segment boundary plus the first and last, tiled in one image, read for: label over the thing being demonstrated, caption clipped, letterbox, stray cursor, a beat whose caption does not match what is on screen, a hold on an unchanged frame. See demo-review.

4. Embedding in a README (the part that breaks silently)

  • Use the ::adom-video widget, with captions and chapters. It is the wiki's YouTube-style player (adom/widgets): every YouTube shortcut, hold for 2x, frame step, a timeline you can hit, chapters as bar segments. A narrated video gets its captions for free: gang-takes writes final.vtt from the adom-tts narration text and final.chapters.json from the segment labels; run it with --wiki-path /OWNER/SLUG/render/FOLDER and paste the report's embed line:
    ::adom-video{video="/OWNER/SLUG/render/feature/demo.mp4" poster="/OWNER/SLUG/render/feature/demo-poster.jpg" captions="/OWNER/SLUG/render/feature/demo.vtt" chapters="/OWNER/SLUG/render/feature/demo.chapters.json"}
    
    Paths are absolute wiki paths, /OWNER/SLUG/render/..., never relative. The video goes in video=, never src= (the wiki inlines a src file into the frame). On a PRIVATE page use the report's embed_private line, ::adom-video{src=".../demo.video.json"}: the reader's browser fetches captions and chapter files without a login, so on a private page they ride inside that manifest, which the wiki inlines. The VIDEO itself on a private page plays in pup but NOT in a browser that blocks third-party cookies (Safari, Chrome with that setting): the frame is opaque-origin, so the login is not sent and the file 404s; the widget then offers "Play it in a new tab". Until adom/wiki#228 (signed media URLs) ships, test a private page in a real browser, not only pup, and prefer a public page for a video every viewer must see inline. Narration not made with gang-takes? You still have its text and where each clip starts in the cut; write the .vtt yourself (one cue per sentence, start = where the clip starts, end = start + the clip's duration) rather than shipping a narrated video with no captions.
  • The rest of this section is for a raw <video> tag, the fallback when the widget cannot be used.
  • Paths resolve from the page root, even in a sub-folder README. In feature/README.md, write feature/demo.mp4 and feature/menu.png, not demo.mp4. A bare filename renders a 404 that curl of the file itself will not reveal. Same rule for docs/x.md sub-readmes.
  • The sanitizer strips style. <video controls preload="metadata" width="1080" poster="feature/demo-poster.png" src="feature/demo.mp4"></video>: the numeric width survives, a style="max-width:100%" does not, and the markdown stylesheet sizes images but not videos, so an unsized video renders at its intrinsic width and overflows the column (adom/wiki#205).
  • Encode for scrubbing: H.264 yuv420p, -g 30 -keyint_min 30, -movflags +faststart, no wider than 1600 px, under 15 MB. Add a plain "Download the video" link for phones.
  • Push through the git page repo: adom-wiki repo push <owner>/<slug> --files feature/README.md feature/demo.mp4 feature/demo-poster.png ..., never the files blob API (wiki-sub-readme).

5. Verify the rendered page, not your own URL

For ::adom-video: load the widget frame itself, https://wiki.adom.inc/OWNER/SLUG/widget/adom-video?video=... (or ?src= for the manifest), in pup, and ask it: document.querySelector("adom-video").adomDrive.state() reports the duration and how many chapters and captions loaded (0 captions means the path or the login rule above). Then screenshot the README page with the frame in view. Mute it (.v.muted = true): pup plays on the user's speakers. For a raw <video> tag:

  1. Fetch the rendered HTML (curl https://wiki.adom.inc/<owner>/<slug>/files/<path>/README.md) and read the <video> and <img> tags: every src and poster must be under /api/pages/<owner>/<slug>/files/<your folder>/. HEAD each one: 200 and video/mp4 or image/png.
  2. Open the page in a browser on a test box (pup) and screenshot it: the video sits inside the column, the poster shows, the images render. Ask the page: document.querySelector("video") .duration and img.naturalWidth are non-zero.
  3. Only then hand the link over. "The files answered 200" is not a test of the page.