Files
guizang-ppt-skill/references/presenter-mode.md
T

185 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 演讲者模式与演讲备注契约
制作任何需要现场讲述的 deck 时加载本文件。目标不是把页面文案复制到备注区,而是让页面、讲述、转场、时间和现场控制形成一条可以排练和可以恢复的叙事链。
## 1. 页面计划同时规划“看什么”和“说什么”
在写 HTML 前,先做一张表。只填用户大纲、素材或已确认的现场信息能够支持的列:
| 页码 | `data-slide-id` | 章节 | 页面目的 | 观众屏可见信息 | 演讲者补充 | 建议时长 | 转场 | 可选现场信息 |
|---|---|---|---|---|---|---:|---|---|
- **观众屏可见信息**:观众此刻必须读到的结论、证据、结构或图像。
- **演讲者补充**:背景、例子、判断依据、语气和细节,不要逐字复述页面。
- **转场**:解释下一页为什么紧接着出现,不要只写“下一页”。
- **可选现场信息**:可包含停顿、提问、Demo、视频、敏感信息、翻页时机、备用方案或读音。
默认生成“提词卡”,不是逐字稿。只有用户明确要求逐字稿时,才写完整口播。
## 2. 模型如何把大纲信息带进演讲模式
对用户的大纲、项目记录和补充说明做结构化提取,不要自行增加现场事实。
- 已给出章节名或可靠推断的连续章节:写入 `section`。
- 已给出总时长或逐页节奏:可给出 `minutes`,总建议时长不超过现场时长的 90%。
- 大纲明确写了停顿、提问、Demo、视频、语气、翻页点或备用路径:分别写入对应的可选字段。
- 用户明确要求某页自动停留多少秒:才写 `autoAdvanceSeconds`。
- 没有提供的信息不猜测、不写“待补充”到演讲界面,直接省略字段。界面对缺失时长显示横杠,其他可选模块整段隐藏。
- 如果页面在未运行校验的情况下临时新增,且没有对应备注,演讲者界面只显示中性横杠 `—`,不显示“待补充”或虚构内容;校验器仍应报告备注与页面不一致。
`minutes` 是讲述计划,`autoAdvanceSeconds` 是播放行为,二者必须分开。不得因为一页建议讲 1 分钟,就默认 60 秒后自动翻页。
## 3. 稳定的页面 ID
每一页都必须有唯一、语义化且稳定的 ID:
```html
<section class="slide ..." data-slide-id="codepilot-capabilities">
```
- 使用小写英文 slug:`cover`、`codepilot-capabilities`、`demo-workflow`、`closing`。
- 页面重排时保留原 ID;只有页面语义彻底改变时才更换。
- 不要用页码作为 ID。演讲者在浏览器里修改的备注按 ID 保存,稳定 ID 可避免重排后串页。
## 4. `SPEAKER_NOTES` 数据结构
在 deck 中保留一条与每页 ID 对应的记录,顺序必须与 slide 完全一致:
```js
const SPEAKER_NOTES = [
{
id: 'codepilot-capabilities',
title: 'CodePilot 能做什么',
section: 'CodePilot',
minutes: 0.9,
purpose: '先让观众建立完整产品认知,再进入实现过程',
talk: [
'从用户动作讲能力,不先讲底层 Harness',
'用首页、多模型、Skills 和侧边栏四张截图建立产品全貌',
'强调模型、工具和上下文可以在同一工作流里协作'
],
transition: '观众知道产品长什么样后,再回答为什么要这样实现',
cue: '按截图顺序指向四个能力区',
advance: '讲完“同一工作流”后翻页'
}
];
window.__SPEAKER_NOTES__ = SPEAKER_NOTES;
```
必填字段:
- `id`、`title`、`purpose`、`talk`、`transition`。
- `talk` 默认 3–5 条,每条只表达一个意思;封面、章节页和纯过渡页可以更短。
可选字段:
| 字段 | 用途 | 界面缺失时 |
|---|---|---|
| `section` | 章节名和章节进度 | 隐藏章节行 |
| `minutes` | 本页建议讲述分钟 | 显示 `—` |
| `cue` | 停顿、Demo、视频、敏感信息提醒 | 隐藏 |
| `interaction` | 现场提问、举手、投票或 Q&A | 隐藏 |
| `delivery` | 语气、重音、语速或停顿 | 隐藏 |
| `advance` | 人工翻页的句子或动作时机 | 隐藏 |
| `fallback` | Demo / 视频 / 网络失败时的备用说法 | 隐藏 |
| `pronunciation` | 人名、缩写和外语读音 | 隐藏 |
| `autoAdvanceSeconds` | 本页自动停留秒数,优先于全局间隔 | 使用全局间隔或不自动翻页 |
`cue`、`interaction`、`delivery`、`advance`、`fallback`、`pronunciation` 可以是字符串,也可以是字符串数组。
## 5. 演讲者界面行为
- 普通 deck 的右下角控制区显示 `P 演讲模式`,不单独悬浮一个抢眼按钮。
- 点击后当前窗口进入演讲者视图,并打开独立观众屏。
- 主体保持两栏:左侧预览、右侧备注;左侧当前页在上、下一页在下。
- 当前页与下一页 iframe 始终严格保持 `16:9`。空间不足时留边并整体等比缩小,不得裁切、压扁或让页面内部文字重新排版。
- 预览 iframe 只在初次挂载时加载 HTML,翻页时通过 `postMessage` 发送页码,不反复改写 `src` 重载整份演示稿。
- 小屏优先缩小下一页预览,把空间留给当前页。
- 底栏分成三段:左侧是 `已进行 / 本页 / 剩余或超时` 三组时间,中间是两行控制(第一行 `首页 / 上一页 / 下一页 / 尾页`,第二行 `开始计时或暂停 / 重置计时 / 排练`),右侧只显示 `第几页 / 总页数` 和完成百分比。不要在底栏重复当前页标题。计时按钮必须明确写成“开始计时 / 继续计时 / 重置计时”,避免让用户误以为是重置整场演示。
- `自动翻页` 放在右上角状态栏,不占用底部翻页区。
- `宫格` 放在“当前页”标题旁。打开后直接用宫格替换当前页/下一页预览区,不要弹出突兀的全屏层;卡片显示页码、标题、章节和进度,点击页面后立即回到当前页/下一页预览。`ESC` 切换宫格。
- 右侧卡片依次显示 `标题 / 本页目的 / 草稿(备注)`,避免把标题或页面目的混进草稿正文。
- 演讲者可从“均衡 / 页面优先 / 备注优先”三种布局选择。
- 备注编辑按 `data-slide-id` 存入 `localStorage`,显示保存状态;切页后备注滚动回顶部,并允许调整字号。
- `Home` / `End`、方向键、PageUp/PageDown 与可见按钮保持一致;光标在备注编辑器中时不得触发翻页。
- 对话框已打开时,`?` 不得覆盖当前对话框;只有 `Escape` 关闭当前对话框。尾页的“下一页”预览显示“演示结束”,不重复当前页。
- 设置面板使用可辨识的卡片层级;开关使用胶囊 switch,数值间隔使用带减号、数值和加号的 stepper,不直接暴露浏览器原生复选框或粗糙数字输入框。
## 6. 时间控制与排练
- 计时器由用户显式开始,可暂停、继续和重置;不要进入模式就自动计时。
- 同时显示总实际时长、本页实际时长、本页计划、剩余或超时。
- 只有每页都有 `minutes` 时,才显示总计划和预计结束时间;部分页缺失时显示横杠。
- 有 `section` 时显示章节位置;该章节每页都有计划时长时,再显示章节剩余时间。
- 排练模式记录每页实际时长和总时长,本地保留最近 5 次。
- 排练结果只做数据汇总,不生成“AI 教练”式评判。
## 7. 自动翻页
- 默认关闭,由用户显式开启。
- 可设置全局间隔;页面存在 `autoAdvanceSeconds` 时优先使用页面值。
- 进入总览、正在圈选、打开设置、浏览器页面不可见、观众屏黑屏/白屏/冻结或观众屏失去同步时,自动倒计暂停。
- 离开暂停状态后从原剩余时间继续,不重头计时。
- 到尾页后停止,不自动回到首页。
## 8. 激光笔、圈选与观众屏控制
- `L` 切换激光笔,红点短暂淡出,不保存。
- `C` 切换圈选,圈选保留在当前页;翻页时清除。
- `X` 清除当前页标注。
- 所有坐标归一化后传给观众屏,不受演讲者屏和观众屏尺寸差异影响。
- `B` 切换观众屏黑屏,`W` 切换白屏,`F` 冻结/恢复观众屏。
- 冻结时演讲者可以继续翻页,观众屏保留原页;恢复时立即追平演讲者当前页。
## 9. 观众屏同步与恢复
模板同时使用窗口 `postMessage`、`BroadcastChannel` 和 `storage` 事件同步。观众页在加载和每次翻页后回传确认,演讲者端显示:
- **连接中**:观众窗口已打开,尚未收到确认。
- **已同步**:观众页确认的页码与演讲者页相同,心跳有效。
- **未同步**:观众页心跳仍有效,但两端页码或序列号不同。
- **已冻结**:观众屏故意保留原页,不是同步故障。
- **未连接**:观众窗口未打开、已关闭,或心跳已超时。即使某些内置浏览器的 `window.closed` 代理不可靠,心跳超时后也必须落到“未连接”。
- **弹窗被拦截**:浏览器阻止打开观众窗口。
“重新打开观众屏”必须始终可用,并在恢复后立即发送当前页。
演讲者退出演讲模式时必须发送 `bye`。由脚本打开的观众窗口尝试自动关闭;如果浏览器不允许自关,则保留深色“演示已结束”遮罩,不得继续停留在最后一页假装演示仍在进行。
浏览器只能确认观众**页面/窗口**的软件同步状态,不能检测 HDMI、转接器或投影仪线缆是否物理断开。现场仍应目视确认外接屏。
## 10. 演前检查和快捷键
“检查”面板检查观众屏同步、弹窗权限、全屏、字体、图片、视频和当前页 16:9。检查结果不得宣称物理外接屏已连接。
| 键 | 行为 |
|---|---|
| `L` | 激光笔 |
| `C` | 圈选 |
| `X` | 清除标记 |
| `B` / `W` | 观众屏黑屏 / 白屏 |
| `F` | 冻结 / 恢复观众屏 |
| `A` | 开启 / 关闭自动翻页 |
| `R` | 开始 / 结束排练 |
| `?` | 打开快捷键说明 |
## 11. 能力边界
这个演讲模式只依赖当前 HTML 和浏览器本地能力,不需要账号或在线服务。不要默认加入:
- 实时字幕、语音转文字或外部语音模型。
- AI 排练教练或对演讲者的评分。
- 扫码提问、在线投票或云端互动后台。
- 手机遥控或需要服务端中继的跨设备控制。
## 12. 生成后验证
```bash
node <SKILL_ROOT>/scripts/validate-presenter-mode.mjs path/to/index.html
node <SKILL_ROOT>/scripts/validate-presenter-mode.mjs path/to/index.html --target-minutes 30
```
浏览器实测至少包含:进入演讲模式、弹窗允许/拦截、前后翻页且预览 iframe 不重载、内嵌宫格替换预览与选页返回、首页/尾页、尾页预览结束态、尾页重新开始、观众窗口关闭后显示“未连接”、重新打开后恢复同步、退出演讲后观众屏关闭或显示结束遮罩、备注保存、计时、排练记录、自动翻页暂停/恢复、激光笔、圈选、清除、黑屏、白屏、冻结、设置面板与演前检查。
至少在一组常用尺寸和一组小屏尺寸下检查:当前页/下一页上下排列,两个 iframe 宽高比均为 `16:9`,且没有超出各自容器。