HyperFrames changelog-video 技能:把每周 Changelog Markdown 变成 45–60 秒品牌化口播视频
本文基于 HyperFrames 仓库中 .agents/skills/changelog-video/SKILL.md 完整展开。这个技能定义了一条从「changelog .md(主题 + 条目)」到「lint-clean、seam-gate 全绿的 HyperFrames 项目」的固定流水线:Annie 配音、动画品牌背景、mock-UI 可视化演示、底部字幕轨。读完本文,你可以完整掌握这条流水线的 6 个步骤、每一步的硬门槛(hard gate)与反模式清单,并能理解字幕对齐脚本 align-captions.mjs 的底层实现原理。
技能定位:输入、输出与前置依赖
技能的输入是一份 changelog .md(主题 + 条目,类似 HyperFrames 每周 digest);输出是一个位于 projects/active/weekly-changelog-<range>/ 的 HyperFrames 项目,且要求 lint 通过、seam-gate 全绿;渲染只在用户明确要求时才执行。
SKILL.md 开头声明了一条不可协商的前置加载规则:必须先加载 motion-doctrine(含 cut-the-curve、有游标时加载 oversized-cursor、以及 seam-craft)和 captions-overlay。分工是明确的——本技能负责 changelog 专属流水线,doctrine 负责动效定律(motion law)。
核心准则只有一句话:visualize, don't list(用可视化代替列表)。每个主题都必须用「真实 UI 的动画 mock 或忠实类比」把这次变更“演”出来,绝不允许纯文字要点。所有主题在写脚本之前必须先经过可视化路由表 visualization-registry.md 的裁决:ui-recreate / ui-analog / terminal / checklist 四选一,文字 checklist 是最后手段,仅保留给真正无法可视化的条目(如可靠性修复清单)。
Step 0 · 从本技能资产启动项目——最常见的“跑偏”根源
SKILL.md 用整段警告强调:Step 0 必须在写任何 composition HTML 之前完成,跳过它必然产出「像上个项目、而不是这个品牌」的视频。原话很直接:“The skill's assets, fonts, and scaffold are the skill; the SKILL.md prompt is a router.”(技能的资产、字体和脚手架本身就是这个技能,SKILL.md 只是路由器。)
启动命令(原文完整继承):
mkdir -p project/assets/fonts
cp <SKILL_DIR>/assets/fonts/*.woff2 project/assets/fonts/
cp <SKILL_DIR>/assets/bgm.mp3 project/bgm.mp3
ffmpeg -y -stream_loop 15 -i <SKILL_DIR>/assets/bg-pattern.mp4 -t <TOTAL> \
-vf "scale=1080:1080,fps=30,eq=saturation=0.72,drawbox=c=black@0.5:t=fill" \
-an -c:v libx264 -crf 20 -pix_fmt yuv420p project/assets/bg-pattern-<TOTAL>s.mp4
cp <SKILL_DIR>/examples/master-skeleton.html project/index.html
对照技能目录,这些占位符全部有实体:assets/fonts/ 下确实打包了 5 个 woff2(TT Norms Pro 的 Normal/Medium/Bold 三级 + Mono + ABC Solar Display Bold),即 assets/fonts/ 下的 TT_Norms_Pro_Bold.woff2、ABC Solar Display-Bold.woff2 等;house BGM 是 assets/bgm.mp3;循环背景源是 assets/bg-pattern.mp4。
注意 ffmpeg 编码链里的品牌化处理:eq=saturation=0.72 把背景饱和度压到 0.72,drawbox=c=black@0.5:t=fill 再铺一层 50% 黑罩——两者叠加就是「animated brand background」的具体形态:有动效、但足够安静,不抢前景视觉。
启动之后必须通读(不是略读)references/build-spec.md。该文件定义品牌令牌:TT Norms Pro + ABC Solar Display + TT Norms Mono 三套字体、奶油底 #f5f6f4、限量绿 #5ef17c、绿色描边的玻璃卡片、kicker/sec-chip 胶囊形状、位于 top: 990 的 32px 字幕轨——所有场景都从脚手架继承这些令牌。
Step 0 还给出了一段自我检查:如果你发现自己想 cp 某个旧视频的 index.html、想自己手写 @font-face、或想设计 WebGL shader 背景而不用上面编码好的 bg-pattern MP4——停手,删掉当前 index.html 回到 master-skeleton 的拷贝步骤重来。理由:在正确的脚手架上重建场景内容,比把品牌往错误的脚手架上 retrofit 更便宜。脚手架 examples/master-skeleton.html 就是这套品牌的外壳(chrome、字体、色板、布局骨架),后续步骤 1–4 只是“规划往脚手架里放什么”,步骤 5 才填充占位符(<RANGE>、<TOTAL>、<CUT_N>、<DUR_N> 与场景主体),绝不重写脚手架的外壳。
Step 1 · 解析 + 编辑性剪裁:预算 45–60 秒
从 changelog .md 中提取:周区间、头条数据(发布数、commits 数)、主题、条目。时间预算是硬性的:
- 总长 45–60s;
- 片头标题 ≤2s,片尾 outro ≤3.5s,4 个主题各约 9–12s;
- 每个主题保留 1 个 hero 可视化 + 最多 3 条口播条目,其余内容只以 outro 的 “full digest” 指针形式存在;
- 「剪裁就是工作本身」:一份 30 条目的 changelog,最终口播 beat 数仍然 ≤14;
- 主题按故事顺序排列:marquee 功能 → 产品界面 → 性能 → 可靠性(digest 通常本来就是这个读序)。
Step 2 · 可视化路由:路由表决定演什么
路由表 references/visualization-registry.md 按强度从高到低定义四个类别:
- ui-recreate——变更发生在一个可以忠实 mock 的界面上;
- ui-analog——没有精确界面,但存在一个诚实的 UI 隐喻(面板、仪表、管线),其行为本身就是这次变更;
- terminal——变更是一条 CLI 命令/参数:打出来,展示结果;
- checklist——不可视化内容(修复清单、依赖升级),最后手段。
有一条红线:绝不发明暗示了不存在的屏幕的 UI——类比必须描绘行为(速度、批处理、缓存),而不是伪造一个产品页面。
路由表中沉淀了 7 个已验证的 ui-recreate 表面(含 Studio 编辑器/时间线、Inspector 面板、画布 + 元素、变体渲染、故事板视图、终端、渲染面板),每个表面都有「mock 解剖」与「已验证编排」两列,例如渲染面板的“绿色进度条 + tabular-nums 帧计数器以 power2.in 跑(慢→快读起来像‘更快了’)”、终端的「字符逐字打出(stagger .02),结果行在 0.3–0.5s 后落定」。另有 8 个已验证类比:LUT/调色用滑杆行 + 同帧重滤镜、缓存用两行相同请求(第二行短路到 ✓ + cache 芯片)、并发上限用芯片队列过闸门、错误上浮用角落 toast 卡片等。
每个主题在路由之后要写一行:theme → surface → mock 执行的 2–4 个有序动作,每个动作绑定一句脚本。如果路由表没有合适表面、也不存在忠实类比,那就是 checklist 场景——不为无法诚实表达的东西编造假 UI。checklist 场景的规格:玻璃卡片、≤6 行 mono 行、绿色 ✓ 在每条的 VO 词上落下(back.out(1.5)、0.3s)+ 行亮度脉冲;超过 6 条的条目直接剪掉,它们活在 digest 链接里。
路由表还带自我生长约定:每当新的 UI 区域上线,第一次 mock 它时就把(解剖 + 编排)加一行进这张表,让下一期 changelog 直接复用而不是重新推导。
Step 3 · 两层脚本:口播层与显示层分离
脚本按 references/script-voice.md 以 token 行书写,同时是 VO 和字幕的唯一事实来源:VO 读 spoken 层,字幕渲染 display 层。这是一条硬质量门——字幕打出 "jay-sawn" 或 VO 念出 "juh-son"(把 JSON 逐字母念)都算构建失败。
语气要求:会话式而非 release-notes("The big one this week —" 优于 "Theme 1:")、允许缩写、可用第二人称、信息型而非推销型、每个 beat 一口气(句子 ≤ 约 14 词)、有信息量的数字保留("fifteen releases")但 commit hash、PR 号和版本细节绝不被念出、以“周 + marquee”开场、以 digest 指针收尾。还有一条特色规则:教会那条简单命令——如果某功能有一行式调用(斜杠命令、CLI 一行命令),脚本要原样念出来,mock 要展示它被敲进去——命令是结果的可见“因”。斜杠命令念作 "slash ",字幕作 /name。
script-tokens.json 的 token 行格式(仓库自带 examples/script-tokens.json 示例):
{
"lines": [
{
"id": "l1",
"tokens": ["This", "week", "at", "HyperFrames,", { "display": "JSON", "spoken": "jay-sawn" }]
}
]
}
- 裸字符串 = display 与 spoken 相同;
- 对象 = 两层分叉:
display保留标准拼写和字幕该显示的标点,spoken是 TTS 读的形式; - 一行 = 一个字幕短语(display 文本 ≤ 约 40 字符),分行是写作期决定的;
vo-spoken.txt由所有 token 的 spoken 形式以空格连接生成。
发音控制完全靠拼写、连字符和空格(HeyGen TTS 只吃纯文本、无 SSML),script-voice.md 给出 7 条规则:缩写字母逐个念(CLI → "C L I")、按词读的缩写重拼(JSON → "jay-sawn"、GSAP → "jee-sap")、混合可发音复合词用连字符小写(ffmpeg → "ff-mpeg",绝不用空格大写,否则 TTS 会逐字母硬停)、版本号展开(v0.7.36 → "version zero point seven point thirty-six")、URL 用 "dot"(hyperframes.heygen.com → "hyperframes dot hey-jen dot com")、扩展名(.mp4 → "dot em pee four")、强调只靠逗号与 em-dash(绝不用大写,省略号在 TTS 中不可靠)。
共享词库是 references/lexicon.json(display → spoken),当前包含约 60 个条目,例如 "JSON": "jay-sawn"、"ffmpeg": "ff-mpeg"、"HeyGen": "hey-jen"、"Linux": "linnucks"、"vite": "veet"、"MusicGen": "music-jen"。规则:每个技术词都查词库;缺失就停下问用户怎么念,然后加词条——绝不猜、绝不念没听过的。新词条要在生成的 VO 里听完那一行才被接受。
Step 4 · VO:Annie(HeyGen,锁定音色)
SKILL.md 给出的命令(原文完整继承):
# spoken-layer text only; words JSON = ground-truth timestamps of the SPOKEN text
# Repo-native path: the changelog-video skill runs from the hyperframes repo root,
# so it uses the tracked hyperframes-media TTS helper directly (no `npx hyperframes
# skills` install step). If you've copied the skill into another repo, swap in
# your own path to the media-use / hyperframes-media heygen-tts.mjs.
node skills/hyperframes-media/scripts/heygen-tts.mjs ./vo-spoken.txt \
-o voiceover.mp3 --words vo-words.json \
--voice 330290724a1b470fb63153f34d4c0183 # Annie — lifelike (do not substitute)
前置要求:heygen CLI ≥0.3.0 且已完成认证(heygen auth login --oauth)。从当前仓库结构看,技能引用的 heygen-tts.mjs 对应的 TTS 助手实现追踪在 skills/media-use/audio/scripts/heygen-tts.mjs(media-use 技能内含配套 tts 参考文档);技能注释也明确:如果把这个技能复制到别的仓库,换成你自己指向 media-use / hyperframes-media 的 heygen-tts.mjs 的路径即可。
词级时间戳是硬门槛。 进入 Step 5 之前必须验证 vo-words.json 非空且带 words: [...] 数组、每词有 start/end。如果它为空(0 字节)或缺数组——这是 TTS 服务商「返回音频但不返回时间戳 payload」的已知失败模式——不得继续。回退方案是用本地 whisper 对已生成音频做强制对齐:
uvx --from openai-whisper whisper voiceover.mp3 \
--model base.en --language en --word_timestamps True \
--output_format json --output_dir .
# then run align-captions.mjs with --words voiceover.json (same shape)
whisper 会误听 TTS 的发音("gee-sap" → "gsap"、"heyjen" → "hey Jen")——但字幕仍使用 script-tokens.json 里的 DISPLAY 拼写,whisper 只贡献时间戳。SKILL.md 把这个回退称作“有字幕构建”与“静默无字幕构建”之间的差别。
对齐由技能自带的 scripts/align-captions.mjs 完成:
node <SKILL_DIR>/scripts/align-captions.mjs \
--tokens script-tokens.json --words vo-words.json --out captions.json
captions.json 是字幕轨的输入(display 拼写 + spoken 时间)。对齐器打印 MISMATCH 警告,构建前必须解决全部(通常是一个词库拼写被 TTS 渲染成了多个词)。音频就是时钟:所有 beat 时间都来自 vo-words.json,重新生成 VO 会重开每一个 seam。
从源码结构看,align-captions.mjs 的实现与文档描述完全一致:
- 多词消耗:
consume()从游标处贪心拼接流中词,直到其规范化拼接串与 token 的 spoken 形式匹配——一个 display token 可以覆盖多个 spoken 词("C L I" 是 3 个词),display 词的时间取其第一个 spoken 词的start; - 模糊匹配:
close()用前缀匹配 + Levenshtein 距离(阈值max(1, floor(min(len)/3)))吸收 TTS 时间戳的怪癖,如 "hey-jen" 可能作为一个词或多个词到达; - 失步再同步:游标未命中时,会在游标之后最多 4 个词范围内重试(
for (let off = 0; off <= 4 ...)),再失败才打印MISMATCH; - 行尾时间:一行的
end= 下一行首词 start;最后一行 = 最后 spoken 词 end +tail(默认 0.6s,可通过--tail调整); - 退出码即门槛:存在 mismatch 时进程
exit(1)并打印N MISMATCH(ES) — resolve before building,意味着它可以直接作为 CI/流水线门使用。
Step 5 · 构建:品牌令牌 + 字幕轨不可省略
严格按 references/build-spec.md 执行:品牌令牌 + 字体(打包在 <SKILL_DIR>/assets/)、动画背景编码、场景脚手架、chrome、字幕轨、每场景一个限量绿瞬间(#5ef17c)。然后是 doctrine 的顺序:ledger.json(所有普通 seam 按 cut-the-curve 切在 LEFT)→ seam-stamp → 内部 beat 落在 VO 词上 → seam-gate verify。
字幕不可选,SKILL.md 用了一整段加粗说明:master-skeleton 自带一个字幕轨 IIFE,读 LINES 数组——把这个数组留空是出厂 bug 而不是风格选择。必须在进入 Step 6 之前把 captions.json 的内容填进去(替换 IIFE 中的 const LINES = /* … */ []):
// paste in place of "const LINES = /* … */ []" in the caption-rail IIFE:
const LINES = /* contents of captions.json */ [
{ id: 0, end: 2.74, w: [["This", 0.0], ["week,", 0.30], …] },
…
];
如果 align-captions.mjs 被跳过或 LINES 为 [],Step 6 的帧检查会失败——不要通过从脚手架删掉 #cap-line 来掩盖它。
字幕轨的渲染规格(见 script-voice.md 的 Caption rail 一节):安静的 OVERLAY 而非预留条带;单行、底部居中(1080 方画幅上 top: 990px、高 52px)、TT Norms Pro 500 32px、墨色 .94、柔和深色 text-shadow、词在时间戳上淡入(0.12s)、短语整组切换;底部中心约 100px 内不放关键小字,其他内容可以从字幕轨下方穿过。
Step 6 · 门槛:全部变绿才能交付
SKILL.md 列出 5 道门槛(原文完整继承):
- lint 检查:
bun run --cwd packages/cli hyperframes check --caption-zone "x0=0;y0=.90;x1=1;y1=1;severity=error;seek=.02,.06,.10,.14,.18,.22,.26,.30,.34,.38,.42,.46,.50,.54,.58,.62,.66,.70,.74,.78,.82,.86,.90,.94,.98"(或仓库本地skills/hyperframes-cli/技能里已安装的hyperframesCLI)——0 error(对比度:变暗文本 ≥ .66 alpha;场景内容保持在字幕轨上方)。不要伸手去用npx hyperframes@latest;追踪中的仓库本地 CLI 才是这个技能所产 composition 契约的事实来源。--caption-zone声明的就是top: 990那一条字幕保护区(y0=.90 到 y1=1 的底部横带),以 25 个 seek 点采样检查。 seam-gate.mjs verify——0 fail。- 重启预览服务器(它缓存 bundle),在原始 comp 页上通过
__player.seek抽查 3–4 个 beat。 - 未经用户要求不要渲染。用户要求渲染之后,从 MP4 验证帧(
ffmpeg -ss <t> … -frames:v 1):字幕在、背景视频不黑、没有极小/冻结帧。 - 字幕在场门槛——硬失败。 在 VO 口播窗口内均匀采样 3–4 帧(例如 48s VO 取
t=3、t=15、t=30、t=42),确认top: 990的字幕轨每帧都渲染出可见文字。任何口播区间内的帧缺字幕,构建即“无字幕出厂”——按红灯门槛处理,回到 Step 5 复查LINES填充。SKILL.md 特别点出这正是 Jul 13–20 v4 构建实际翻车的事故。
项目布局
SKILL.md 定义的标准产物目录(原文完整继承):
projects/active/weekly-changelog-<range>/
├── index.html # single-doc master (scenes as slides, stamped seams)
├── ledger.json # vector ledger (seam-stamp input)
├── script-tokens.json # two-layer script (source of truth for VO + captions)
├── vo-spoken.txt # generated: spoken layer, one line
├── voiceover.mp3 + vo-words.json + captions.json
├── bgm.mp3 # copy from <SKILL_DIR>/assets/bgm.mp3 (the house track) unless the user supplies one
└── assets/fonts/ + assets/bg-pattern-<dur>s.mp4
文件间的依赖链很清晰:script-tokens.json 是 VO 与字幕共同的事实来源 → 生成 vo-spoken.txt → TTS 产出 voiceover.mp3 + vo-words.json → align-captions.mjs 合成 captions.json → 粘贴进 index.html 的 LINES 数组;ledger.json 与 stamped seams 则驱动 seam-stamp / seam-gate 校验。
反模式清单
SKILL.md 末尾的对照表(原文完整继承):
| 不要做 | 应该做 |
|---|---|
| 用要点幻灯片表现 UI 变更 | 让 mock 界面把这次变更“演”出来 |
| 为不可表达条目伪造 UI | 诚实的 checklist 场景 |
| TTS 文本里直接念 "JSON"/"CLI" | 词库 spoken 形式;display 保持标准拼写 |
| 字幕里出现音译拼写 | 字幕永远渲染 display 层 |
| 猜未知词的发音 | 先问,再增长词库 |
| 念 changelog 的每一条 | 每主题 ≤3 条;digest 链接承载其余 |
| 绿色强调铺满全片 | 每场景一个绿瞬间(#5ef17c) |
| 从某个旧视频的 index.html 起步 | Step 0——永远把本技能的 examples/master-skeleton.html 拷入 project/index.html |
手写 @font-face / WebGL shader / 自制 BGM |
Step 0——原样拷贝本技能的 assets/;技能资产即品牌 |
| S3 替换后不做 CloudFront 失效就交付 | 替换后对精确路径执行 aws cloudfront create-invalidation(distribution E2BSLVSZ7FG3U0)——否则 CDN 会缓存旧文件 |
脚手架 LINES 数组留空就出厂 |
Step 4 必须产出填充的 captions.json;Step 5 必须粘贴进 IIFE;Step 6 门槛 5 必须确认渲染帧上有字幕。空 LINES = 无字幕出厂 = 重做 |
没有 vo-words.json 就跳过字幕出厂 |
回退到 whisper 强制对齐;字幕不可选 |
这套流水线的工程要点小结
通读 SKILL.md 与其引用文件,可以看到 changelog-video 技能把三条“不可协商”的纪律做成了可验证的门槛,而不只是口头要求:
- 品牌纪律——Step 0 的脚手架拷贝 + ffmpeg 背景编码把「品牌」固化成资产而非提示词,任何一步想绕开都有明确的 STOP 检查和反模式条目兜底;
- 发音纪律——
display/spoken双层 token + lexicon.json 词库 + “缺失必问不猜”规则,让 TTS 的纯文本限制被系统性绕过; - 字幕纪律——词级时间戳硬门槛(含 whisper 强制对齐回退)+ align-captions.mjs 以退出码表达 mismatch + Step 6 门槛 5 的抽帧验证,形成「时间戳缺失 → 对齐失败 → 渲染帧缺字幕」三段式拦截,确保不存在“静默无字幕出厂”的通道。
对想复用这套思路的团队,技能目录本身就是一个可携带的最小样例:脚手架 master-skeleton.html、token 示例 script-tokens.json、路由表 visualization-registry.md 与发音契约 script-voice.md 都可以独立阅读并移植。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00