1实现原理 · 为什么它能做到
产物定义先于一切:交出去的是「跑起来的 deck」而不是 MP4,并且明确禁止把 deck 交给 hyperframes render——因为 deck 由多个顶层 scene 合成、没有 master root,render 只解析第一个合成,会静默截断成很短的片子。
**Do not `hyperframes render` a slideshow into a single MP4.**
实现机制是「普通合成 + 一个声明式 JSON 岛」:合成仍是 HF 的 scenes/clips/GSAP,多出来的一块是 application/hyperframes-slideshow+json,播放器的 SlideshowController 读它,把连续时间线变成可离散导航的 deck。
A HyperFrames slideshow is a normal HyperFrames composition — scenes, clips, GSAP timelines — with one extra ingredient: a **JSON island**
island 必须是真实存在的块、位置随意但要在 body 靠前:present 静态解析合成 HTML,若把 manifest 藏在别的 script 标签后由运行时代码生成,present 读不到。
The `present` command reads the composition HTML statically and expects the real `application/hyperframes-slideshow+json` island to already be present.
片段(fragments)是**绝对合成时间**上的揭示停点,导航由确定性 seek 驱动而不是播放:进入带片段的页会直接 seek 到 fragments[0] 停住,Next 依次 seek 到下一个停点。
Navigation is seek-driven, not play-driven.
分支是真实存在的场景,只是不列进主线:点热点把 {sequenceId, slideIndex:0} 压栈进入分支首页,back 弹栈回父页、backToMain 清空栈;面包屑与计数器按序列作用域渲染。
Clicking a hotspot pushes `{sequenceId, slideIndex: 0}` onto the nav stack and enters the branch's first slide.
写作纪律是硬约束而非建议(完整句标题、一页一意、先讲最狠的点、市场测算必须自下而上、字号下限、动手前先搜 live catalog 找现成积木),并给出理由:违规的页会在评审时被直接替换。
**Headline is a complete-sentence claim, not a label.**
移植既有页面时要求保真到机制层:以 native media 元素为唯一真相、由媒体事件与 media.currentTime 派生视觉状态、字体 token 必须落成具体字体栈、截图类内容按原比例 contain 而不能 cover。
Treat native `<video>` / `<audio>` elements as the source of truth for any custom media chrome, canvas visualizer, waveform, beat grid, or playhead.
讲者模式由共享组件拥有:Present 按钮/P 键、新开 audience 标签页、两个标签页用 BroadcastChannel 同步;备注在讲者视图里编辑并存 localStorage(覆盖 manifest 而不改合成文件)。
**Presenter mode:** use the built-in Present icon button in the slideshow nav capsule, or press P.
媒体清理与静音属于控制器职责且有跨 realm 细节:换页/换序列时由控制器调 stopMedia;同一页内的片段导航不清媒体;判断 iframe 媒体不能用父页的 instanceof(真实浏览器返回 false)。
The slideshow controller owns slide-exit media cleanup.
standalone harness 是过渡方案而非正统:引擎托管路径(preview --slideshow / studio present mode)未落地之前,裸播放器打开的 demo 需要三个绕行(暴露可 seek 的 root 时间线、把 island 复制进 wrapper、wrapper 自持音频)。
These patterns are a **temporary workaround** for standalone demos.
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| cli | 官方 hyperframes CLI:present(起 deck 服务与讲者/观众同步)、lint、check、preview、snapshot(逐页静帧) |
| package | 播放器构建产物(本仓 packages/player/dist 的 hyperframes-player / hyperframes-slideshow 全局包;改播放器行为后需在 packages/player 跑 bun run build) |
| network | CDN 资源(harness 示例):Three.js 模块从 jsdelivr 导入,供独立 demo 的 3D 背景层使用(产物期由浏览器拉取,按范式不判级) |
| package | 浏览器平台 API(非外部服务):BroadcastChannel 讲者/观众同步、localStorage 备注持久化、postMessage 与 iframe 播放器通信、WebAudio/Audio 自持音效 |
| package | 兄弟 skill 关联:deck 内容来自 Figma 时必须先跑 /figma(资产导出/品牌令牌/分镜重建),基础合成契约在 /hyperframes-core,词级字幕规则在 /embedded-captions |
| cli | 官方 registry 搜索/安装(写页面前先 catalog 查现成视觉积木,需要时 add 进 deck) |
4风险提醒 风险提醒:蓝色 · 知晓即可
- 误用 render 会安静地产出错片 — 若使用者绕过文档直接对 deck 跑 hyperframes render,只会得到第一页的短 MP4 且没有任何报错——这类失败没有运行时信号,只能靠人知道这条红线。
- 移植源页面会把不可信代码带进产物 — 契约要求尽量保真地复制源站的自定义播放器、可视化、滚动驱动运动;源站若不可信(第三方站点),其脚本逻辑随之进入你的交付物,演示时可能触发网络请求或副作用。
- 演示环境依赖(分享方式/自动播放策略) — Meet 需分享 audience 标签页、Zoom 需把 audience 窗口拖出并保持不完全被遮挡;跨标签页无法转移用户激活,观众端首次播放须静音兜底——这些约束若被忽略,现场会表现为幻灯片卡住或没声音。
- standalone 路径非正统且会随引擎上线而失效 — harness 的绕行(复制 island、自时钟、postMessage 桥)是为裸播放器缺口写的;一旦引擎托管路径上线,照抄这些模式反而会变成技术债。
- TTS 字段是保留位 — island 里的 ttsScript / ttsAudioUrl / ttsDurationMs 尚未接线(文档明示 Reserved),若按 schema 预填会得到「有字段但不会播」的结果。
5第二遍独立确认
- [ok] 网络面是否真如声明(蓝档判定的关键反例检查) — 全目录仅 1 处 http(s) 命中:standalone-harness.md 第 895 行的 [email protected] jsdelivr 导入(示例代码块内);无 fetch(、无 process.env、无 child_process、无凭证关键词。SKILL.md 侧只有本地命令(present/lint/check/preview/snapshot)与浏览器 API(BroadcastChannel/localStorage/postMessage),均为本地或浏览器内行为。
- [ok] 「禁止 render」的声明是否与机理自洽(不是随口警告) — SKILL.md 给出原因:deck 由多个顶层 scene 合成(每页一个 data-composition-id)且**没有 master-root 合成**,所以 render 只解析第一个合成,产出静默截断的 MP4(举例 6s/40s);并说明线性导出(仅主线、排除分支)目前是 deferred,故支持输出为 present 活 deck 与逐页 snapshot。声明与结构描述一致。
- [ok] island 的「静态可读」要求与 present 行为是否一致 — 文档明确 present 静态解析合成 HTML、期望真实的 application/hyperframes-slideshow+json 已存在,并禁止用另一个 application/json 块 + 运行时代码生成 island。这与「JSON 岛是唯一真源、sceneId 必须匹配 data-composition-id」的 lint 契约自洽。
- [ok] harness 内容是否被当成正统做法(避免误判为「本 skill 主张两套实现」) — harness 开头即写 interim framing(临时绕行)与「When that path ships, most of what follows collapses」,SKILL.md 亦写「Do not treat the patterns there as the blessed model」。两处口径一致,属过渡文档而非第二套正统。
- [ok] 是否存在夸大(把引擎/播放器能力算作本 skill 能力) — 文档反复把导航、presenter mode、媒体清理、静音归给共享播放器组件(<hyperframes-slideshow> / SlideshowController / hyperframes-player.stopMedia),本 skill 只声明 island 数据契约与写作/移植纪律,未见据他人之功。
6结论
034ea590dd179243…d2f0bc7f34