BEUP Clip pipeline upgraded to CNBC-quality standard with real product demo B-roll
A 5-gap analysis against CNBC short-form production was resolved: real MP4 video backgrounds (not JPEGs), generic bar charts, a hook-scene mandate, and a new demo_recording field that swaps generic stock footage for actual screen recordings of Canvas dashboards, Google Sheets, or Notion pages.
6-layer thinking chainChuỗi tư duy 6 tầng
"kiểm tra xem đây có phải là gap ko, nếu có thì bổ sung; còn gap gì khác ko" — 5-gap CNBC analysis
How the pieces connect
beup-clip-broll.py is now a dual-mode asset fetcher: it fetches generic stock video (Envato cache → Pexels) for video_query scenes AND dispatches to platform-specific Playwright runners for demo_recording scenes. Both write to broll-map.json — the renderer reads from that single file and picks the highest-priority source per scene.
| Technical termThuật ngữ kỹ thuật | Plain nameTên dễ hiểu | RoleVai trò |
|---|---|---|
video_query | Stock B-roll hint | String field on a beatsheet scene; broll.py searches Envato cache then Pexels and saves the clip under broll-map.json["videos"] |
demo_recording | Product demo hint | Object field with type/url/duration; broll.py dispatches to the matching Playwright runner and saves clip under broll-map.json["demos"] |
mediaForScene() | Source picker | In renderer: checks demos[scene.id] first → videos[video_query] → photos[photo_query]. First match wins. |
etsy-generic profile | Generic Canvas scroll tour | Pre-built interaction in canvas-recording-runner.js: opens any Canvas URL, does a scroll-down tour at 1080×1920. Works on any BEUP Canvas dashboard without a custom profile. |
startFileServer() | Local video server | Node.js http.createServer on port 0 (auto-assign), started in render.js main() before Playwright launches. Solves Chromium's file:// video block inside the recording sandbox. |
Read the diagram top-down: beatsheet feeds broll.py which fans out to either the stock-video APIs (for generic scenes) or the Playwright runners (for product demo scenes). Both outputs merge into broll-map.json. The renderer reads that single map and applies a three-tier priority chain at render time — so a scene can have all three fields set and the best available source wins automatically.
What was verified and built
Layered decision cardsCác quyết định theo tầng
Artifact mapBản đồ tệp tạo ra
| PathĐường dẫn | WhatLà gì | Who reads itAi dùng |
|---|---|---|
~/beup-workspace/scripts/beup-clip-render.js | Added startFileServer(), mediaForScene() with video+demo priority chain, barChartSvg(), .photo-layer video CSS, demo lookup in mediaForScene() | Playwright renderer |
~/beup-workspace/scripts/beup-clip-broll.py | Added subprocess import, extract_demos(), record_canvas_demo(), record_notion_demo(), record_sheets_demo(), record_demo() dispatcher, demo loop in main() | B-roll + demo fetcher |
~/.claude/skills/beup-clip/references/beatsheet-schema.md | Added demo_recording field docs (canvas/notion/sheets examples), bar_chart section with jsonc example | Beatsheet authors / LLM prompt |
~/.claude/skills/beup-clip/references/distillation-method.md | Rewrote background-media section: demo_recording > video_query > photo_query priority; added hook mandate | Beatsheet authors / LLM prompt |
~/.claude/skills/beup-clip/SKILL.md | Updated Step 3 B-roll description to mention demo_recording dispatch and recording runners | Skill orchestration reference |
- Integration test: create a beatsheet with demo_recording:{type:canvas, url:canvas.beup.space/restaurant-delivery?demo=1, duration:8} and run beup-clip-broll.py --dry-run to verify it's detected
- For sheets type: add a 'generic' profile to google-sheets-recording-runner.js if you want URL-only Sheets recording without a named profile
- Beat sync (music dip at key stat moments) — not implemented; would need per-scene timing metadata + FFmpeg volume filter with timestamps