Auto-Demo — screen-recording + multi-channel distribution (decision doc)
Status: proposal, no code/infra changed. Covers the two remaining auto-demo next-steps that need a decision before building — #5 true screen-recording video and #6 YouTube/TikTok/IG distribution (see the ranked list in AUTO_DEMO_HANDOFF.md). Both are grounded in the current code; each ends with a concrete recommendation + what you'd need to decide.
Refinements #2–#4 (registry auto-PICK, stale regen, earned auto-post) are already built + merged (#1199–#1201). This doc is about the last two.
#5 — True screen-recording video
The real situation (not what the landmine note implies)
The handoff says true recording "needs full Chromium + --headless=new + xvfb on
Railway (nixpacks change)." Reading the actual infra, that's more pessimistic
than reality:
- The full
chromiumbinary is already installed on prod.nixpacks.tomlrunsnpx playwright install chromium chromium-headless-shell— both. The system libs it needs are already apt-installed (theaptPkgslist). - The reason
recordVideofails today is purely the launch mode:persona-browser/pool.tslaunchesheadless: true, which resolves to chrome-headless-shell — the stripped binary that lacks the screencast path Playwright's video recorder uses. The full chromium (already on disk) does have it.
So the limitation is a code/launch-config choice, not a missing binary and not necessarily a nixpacks change.
Options
| Option | What it is | Infra change | Risk | Notes |
|---|---|---|---|---|
| A — full-chromium capture context | Add a second launch path that uses the full chromium binary in --headless=new (or headless:false) only for the demo-capture context; keep headless-shell for the cheap screenshot/PDF/poster paths. Enable Playwright recordVideo on that context. | None (binary + libs already present) | Med — new-headless video recording is generally reliable but unverified on this Railway image; needs a prod smoke test. | Smallest change; reversible; falls back to screenshots on failure. |
| B — xvfb + full chromium | Add xvfb to nixpacks.toml aptPkgs, launch full chromium headless:false under a virtual display. | nixpacks (aptPkgs += xvfb, process wrapper) | Higher — new build-image surface, another thing that can break the deploy | The "classic" recipe. Only needed if A's new-headless video proves flaky. |
| C — do nothing | Keep the Phase-2b real-UI screenshot frames (already built, config-gated on DEMO_CAPTURE_BASE_URL). | None | None | Screenshots already show the real UI per step; the gap vs. true recording is motion (scroll/typing/transition fidelity), not "is it the real app." |
Recommendation
- Do #1 first (validate the 2b screenshot capture on prod). It's built and costs nothing to turn on. If per-step real-UI screenshots read well enough as a product tour, #5 may not be worth building at all — motion is the only thing they lack.
- If motion fidelity is needed, try Option A (code-only, no nixpacks risk),
gated behind a
DEMO_VIDEO_RECORD_ENABLEDflag, with the existing caption-card / screenshot path as the automatic fallback if a recording fails. Validate on a single demo on prod before making it the default. - Fall back to Option B only if A's video is unreliable on the Railway image.
Decision needed: after #1, is screenshot fidelity enough (→ close #5), or do we want true motion (→ I build Option A behind a flag)?
#6 — YouTube / TikTok / Instagram distribution
What exists to build on
- The marketing posting console (
social-posting.ts/dashboard/admin/social-posting, migrations 343/349) is a human-in-loop console: it picks candidate seasons that have a 9:16 vertical trailer + a caption draft and nosocial_post_logrow for a platform yet, and tracks posts. Platforms:youtube_shorts,fb_reels,tiktok,instagram_reels.
- YouTube upload is automated (
youtube-upload.ts): OAuth +videos.insert. But it's Shorts-shaped — returns ashorts_url, folds#Shortsinto the description, assumes a vertical clip. - Bluesky is already done (#4 — earned auto-post + the manual button).
The honest blocker: aspect ratio, not plumbing
Demo videos render 16:9 landscape (1280×720 — VIDEO_W/VIDEO_H in
demo-video-args.ts). The
console's four platforms are all 9:16 vertical (Shorts/Reels/TikTok). So:
- A demo MP4 fits YouTube as a regular (landscape) video natively — but not as a Short, and not TikTok/IG Reels/FB Reels, without a vertical re-render.
- Feeding demos into the console as-is would offer them to platforms whose format they don't match.
Plan (in dependency order)
- YouTube (landscape) — the natural first channel. Add a non-Shorts upload
path (the demo is a normal video, not a Short) or a small
uploadDemoToYouTubethat reuses the OAuth/videos.inserthalf ofyoutube-upload.tswithout the#Shortsframing. This is the one channel demos fit today. ~1 PR. - Vertical demo render — the gate for everything else. To reach
Shorts/TikTok/IG, render a 9:16 variant (a
VIDEO_W/Hswap + caption reflow in the puredemo-video-args.ts; storevideo_url_vertical). Until this exists, the other three platforms are format-blocked regardless of plumbing. ~1 PR (pure-function change + a column). - Console integration. Generalize the candidate pool +
social_post_logto accept a demo subject (today it's keyed onseason_id— needs a nullabledemo_slugor a polymorphic subject). Then approved demos surface in the existing human-in-loop console alongside seasons. ~1 PR after (1)+(2).
Deliberately NOT auto-posting these. Unlike Bluesky (native video upload, low-stakes, already gated), YouTube/TikTok/IG posting should stay human-in-loop through the console — same discipline the season pipeline uses. Auto-post is a Bluesky-only trust tier for now.
Recommendation
Start with step 1 (YouTube landscape) — it's the only channel demos fit without a re-render, and the upload half is already written. Hold steps 2–3 until you actually want vertical Shorts/TikTok/IG demos, since that's a real format-and-schema investment, not just wiring.
Decision needed: (a) do you want YouTube-landscape demo upload now? (b) is a 9:16 vertical demo render worth building for Shorts/TikTok/IG, or is that not how you'd distribute a product tour (vs. a story trailer)?
Summary of decisions to make
- #5: validate 2b screenshots on prod (#1) → then decide screenshot-enough vs. build Option A (flagged full-chromium recording).
- #6a: YouTube-landscape demo upload — build now? (reuses existing OAuth uploader.)
- #6b: vertical (9:16) demo render for Shorts/TikTok/IG — worth it for a product tour, or skip?
None of these are blocking; the system is complete + spend-safe as shipped. This doc exists so the next build starts from a decision, not a guess.