booth-kiosk-deck · 全自动循环口播演示流水线
替你把「确认单 → 单源生成 → 两级验证 → 出片」跑成 15 分钟流水线。
可跑通的参考实现(整套抄改起点):assets/day1025/booth/booth_1/。
零、先记住物理事实(每条都踩过)
- 浏览器默认拦「无手势出声」:只有
--autoplay-policy=no-user-gesture-required的 kiosk 启动才保证开机有声;被拦时 deck 自动降级墙钟静音循环(字幕/动作照常),任意一次点击即从当前页恢复出声 new Audio()不进 DOM:querySelector('audio')永远查不到——验证必须拦 Audio 构造器(见 fastgate)- PowerShell 5.1 内联写复杂 patch 必炸(
$展开、\n不换行、引号套层):一律写 .py 文件执行,别用python -c传中文 - npx 版本漂移会改变 check 行为(0.8.195 起 0 错误也 exit 1):钉版本,如
hyperframes@0.8.193 - HyperFrames:工程目录只允许一个带
data-composition-id的 HTML(源模板放工程外);未加作用域的类名(如.big)会命中别的组件;left:%补间被 StaticGuard 拒收(用x,固定像素);图层切换用display不用opacity(否则 layout 闸判文字重叠);deck 永不渲染成 MP4——视频是独立合成,由 build.py 从同一数据生成 - deck 时钟跟
audio.currentTime,无声降级墙钟;抽帧验证用?t=秒直跳,不要实时等
一、确认单(动手前一次问全,每个都给★推荐)
必问 5 问(少问一个 = 返工 20 分钟级别):
| # | 问法 | 推荐 |
|---|---|---|
| 1 | 播放方式:全自动循环 kiosk,还是允许访客交互? | ★ 全自动循环,零交互入口,输入全吞 |
| 2 | 声音:默认有声 + 100% 音量,还是静音循环? | ★ 默认有声 100%,不放音频控件;拦声时提示「点一下恢复」 |
| 3 | 鼠标:可见不可控,还是隐藏? | ★ 光标可见、页面不可控 |
| 4 | 客户名:脱敏成 XX客车,还是实名?哪些位置(画面/口播/字幕/文件名/README)? | ★ 全部脱敏,含 TTS 词表与导出文字稿 |
| 5 | 演示哪几个能力(按 demo 最新侧边栏顺序)? | ★ 前两个能力 + 封面 + 收尾,共 4 页 |
grill 清单(头脑风暴补充,逐条给用户过):
| # | 问题 | 推荐 |
|---|---|---|
| 6 | 口播稿谁定? | ★ agent 先出 TXT(每句一行)确认,冻结后再跑 TTS——口播词是一切时长的源头 |
| 7 | 总时长预算? | ★ 60–120 秒;超了删内容,不加速语速 |
| 8 | 页数结构? | ★ 封面 + 每能力 1 页 + 收尾(4–5 页);一个能力不拆两屏 |
| 9 | 数字口径怎么标? | ★ 演示数字全部标「演示用模拟数据」;事实/编号可引用真实调研来源 |
| 10 | 交付物形态? | ★ deck HTML + HyperFrames MP4 双交付(kiosk 用前者,大屏/备份用后者)+ 口播 TXT |
| 11 | 展位机怎么启动? | ★ start.cmd:Edge kiosk + autoplay 豁免 + 独立 user-data-dir |
| 12 | 断网约束? | ★ 全离线:本地音频、本地 gsap、无 CDN 字体/图标 |
| 13 | 分辨率与缩放? | ★ 1920×1080 舞台等比缩放任意窗口 |
| 14 | 循环行为细节? | ★ 页间气口 1.4s;循环回第 1 页时交互状态全部重置 |
| 15 | 验收标准? | ★ 快闸全绿(见下)+ 关键 cue 抽帧人工过目 + MP4 ffprobe 时长==合成声明 |
二、单源生成(消灭双份手工同步)
build.py是唯一数据源:每页一个块 = 口播词 + cues(动作提示点=正文关键词)+ 面板数据- 同一份数据渲染两个产物:
slides.html(kiosk deck)与video/index.html(HyperFrames 合成) - 永远不手改产物;改内容只改 build.py 数据块,重跑生成
- 口播动作点用词级时间戳:
edge_tts.Communicate(..., boundary="WordBoundary"),cue 取关键词开口时刻;时长用 ffprobe 实测,不估算
三、两级验证(快闸每次改动都跑,慢闸只跑一次)
快闸(<30 秒,无截图)——用本 skill 的 scripts/fastgate.py:
- console/pageerror = 0
- 口播
[volume=1, muted=false, playing=true](拦 Audio 构造器取真值) - 禁词表不在画面文字里(客户名等)
- 可见面板矩形不溢出舞台
- (视频)
ffprobe时长 == 根data-duration,差 >0.05s 即 FAIL
慢闸(交付前一次):?t= 直跳抽 6–8 张关键 cue 帧 → 人工过目 → render.ps1 出 MP4 → 抽 2 帧复核。
纪律:改一行先过快闸;慢闸攒到交付前一次跑。严禁拿慢闸当回归测试。
四、15 分钟预算
| 分钟 | 动作 |
|---|---|
| 0–2 | 确认单 15 问过一遍(用户只答「行/改」) |
| 2–5 | 只改 build.py 数据块 → 生成 deck + video 工程 |
| 5–7 | 快闸全绿 |
| 7–9 | 抽帧过目(有问题回到 2,但只修不重验全量) |
| 9–12 | check + 后台渲染 MP4 |
| 12–15 | 导出口播 TXT / README、ffprobe 复核、收尾 |
五、不调的情况
- 要的是可点击原型(访客操作驱动)→ 不是本 skill,kiosk 模式会吞掉一切交互
- 真人手动翻页、带演讲者备注的幻灯 → frontend-slides / slideshow skill
- 与口播无关的纯素材剪辑 → video-use
- 一次性 <15 秒概念片,不需要循环 → 纯 HTML/Canvas 即可,别起工程
六、红线
- 禁词表(客户全名等)进快闸,任何产物不得出现;文字稿与 TTS 词表一并检查
- 合成内禁随机/定时器/网络请求——画面必须是时间轴的纯函数
- 演示数字必须可见地标「演示用模拟数据」;真实事实必须带编号来源
- 观众侧零可操作入口(除非确认单明确要求);离开 kiosk 启动脚本跑,必须保留「点击恢复出声」降级路径