OpenMontage music-to-video 技能 Step 3 深度解析:从骨架到完整 STORYBOARD 的规划(planning)实战
【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage
本篇基于 OpenMontage 仓库中music-to-video技能的 planning.md 文档展开,讲解该技能工作流第 3 步(Step 3)的核心规划过程:如何为一条节拍同步音乐视频选定统一的品牌基调(font + palette)、如何把 Step 2 产出的帧骨架逐帧填充为「组(groups)+ 处理方案 + 真实锚点秒数 + 文案」,并通过validate-plan.mjs完成机器校验。读完本文,你将掌握一份可被 Step 4 帧构建子代理直接消费的STORYBOARD.md完整计划应满足的全部约束与操作细节。
Step 3 在整个 music-to-video 流程中的位置
在 SKILL.md 定义的 7 步工作流中,music-to-video 把「一首音乐」变成「节拍同步的 HyperFrames 视频」:
Step 0 setup → hyperframes.json + assets/bgm.mp3 Step 1 analyze → audiomap.json Step 2 skeleton → STORYBOARD.md(帧骨架,groups 为 TBD) Step 3 plan → 完整 STORYBOARD.md + frame.md ← 本文主角(需用户批准) Step 4 build → compositions/frames/NN-*.html(每帧一个子代理) Step 5 assemble → index.html Step 6 render → renders/video.mp4Step 3 的定位由 planning.md 开宗明义:编排者(orchestrator,即执行技能的 Agent 本身)把 Step 2 的骨架原地编辑为一份完整、已批准的STORYBOARD.md—— 选定品牌主线(brand spine),然后为每一帧决定其组结构、给每个组分配一种处理方案(treatment)、绑定真实的节拍锚点秒数、并写出文案。文档给出的心法(mantra)是:
音乐是脊柱(the spine);模板是起点而非笼子(a head start, not a cage);排版是底线(the floor),素材(assets)只是同一节拍网格上的一种可选配料。
同时文档划定了清晰的责任边界:规划者负责 WHAT(定模板/原语、内容、品牌、锚点秒数与意图),不负责 HOW—— 微时序(micro-timing)、具体实现、帧内切分由 Step 4 的 frame-worker 决定。文档特别强调:永远不要把毫秒级 tween 写进分镜稿(storyboard)。这条边界在 storyboard-format.md 中再次被申明:STORYBOARD.md是构建规格(build spec),不是代码。
输入物(Inputs)
进入 Step 3 前,规划者手上应有以下五类输入:
| 输入 | 说明 |
|---|---|
Step-2 骨架(已在STORYBOARD.md中) | 每帧已带span_sec+pacing+mood+feel,### Groups为TBD (Step 3) |
audiomap.json | 时序事实来源(timing truth)。Step 1 由 analyze-beatgrid.py 一次性分析产出,规划者需读取每帧跨度内的真实锚点秒数 |
| template-catalog.md | 模板选择菜单(L1 层,8 个免素材的组模板) |
| motion-primitive-catalog.md | 自由组合菜单(L0 层,40+ 运动原语配方) |
| montage.md | 素材处理方案(仅当用户提供了图片/视频时才需要读) |
| 用户 brief / 提供的文案 | 主题、情绪、必须原样保留的字词 |
其中audiomap.json的可信度边界值得注意:从 frame-skeleton.md 的「trust boundary」表格看,energy_phases[]、events[]、rolls[]、silences[]、hard_stops[]、key_moments[]、phrases[]、audio.duration_sec等字段对任何音乐都可靠;而tempo.bpm与grid.beats_sec/downbeats_sec的精度只在音乐真正有节奏感时可靠——对平缓音乐,节拍网格只是追踪器强加的节拍器。这个判断(记为每帧的pacing)在 Step 2 已定,Step 3 只需遵守。
Step A — 选定品牌主线:一个未修改的预设
整条视频共享一套字体系列 + 一套色板。Step A 的要求是:
- 从 hyperframes-creative/frame-presets/ 目录里选一个现成预设,选择依据是 design-spec.md 中的预设对照表(Pick when 列)+ 曲目情绪 + brief;
- 预设中只有 fonts 和 colors 重要——模板(template)拥有构图(composition)与运动(motion),预设只负责「看起来的样子(look)」;
- 原样复制,不做任何修改:
cp ../hyperframes-creative/frame-presets/<preset>/FRAME.md "$PROJECT_DIR/frame.md"(该相对路径以 music-to-video 技能目录为基准;$PROJECT_DIR即videos/<project>/。)
然后从预设中回填STORYBOARD.mdfrontmatter 的style:font取自预设的typography:段,palette取 ≤4–6 个色板来自预设的colors:段。hex 与字体族名必须逐字引用(verbatim),绝不能杜撰或取整。每一个组的 palette 参数都只能从这唯一的一套色板里取——正是这种统一性,让不同模板拼接的多个组读起来像同一个作品。
仓库中的预设共有 14 个,每个都带FRAME.md(YAML frontmatter 是规范层:colors/typography/spacing/components为机器可读的精确值)+caption-skin.html+frame-showcase.html(预览用,不得带入项目)。举两个对照示例(摘自 design-spec.md 的表格):
- claude:暖米色纸底 + 稀缺的陶土珊瑚色(
#CC785C)作点缀,EB Garamond 衬线展示字 + Inter 正文 + JetBrains Mono 索引/代码字,适用「深思熟虑 / 文学感 / 面向开发者」的场景; - broadside:抗议海报系统,双平面(墨黑 / 火橙),超大小写 Barlow 900 当图形基元用,适用「bold / 排版驱动 / 宣言式」。
按 design-spec.md 的规则,frame.md恒为小写文件名(预设里发货的大写FRAME.md是模板,落地后采用小写frame.md)。
Step B — 逐帧决定其组结构(groups)
核心原则:一帧通常就是一个组(一个模板或一次自由组合横跨整帧)。仅当单一处理方式无法覆盖整帧时才细分为 2 个及以上组——典型如「繁忙的开场 + 收尾的 lockup」。
分组的三条硬约束:
- 切分点必须落在帧跨度内的真实 audiomap 锚点上——
key_moment(SURGE/DROP)、phrase边缘、或 onset 簇间隙(onset-cluster gap),绝不能在rolls[](滚奏/填充段)运行内部下刀; - 每个组 ≥ 约 1 小节(~1 bar);
- 密度不强迫增加组数——密集帧通常就是一个内部自行消化密度的组(如
poster-tile-mosaic这类元模板)。组数跟随的是不同处理方案的数量(distinct treatments),而不是节拍数量。
最后一条与 SKILL.md 的整体设计呼应:帧数(也就是一帧一个子代理的构建成本)跟随的是「不同处理的帧数」,快歌不会把子代理数量炸开。
Step C — 逐组选定处理方案(三者取其一,且只能其一)
方案 A:匹配一个模板
读 template-catalog.md,把该组的feel+mood+pacing与目录中每个模板的「Reach for it when」匹配,取最接近者(closest fit),然后绑定(bind):
- 填
params(键来自目录条目)——文案进文本槽位、色板来自品牌主线、duration= 组的跨度长度; - 填
role_bindings——用从audiomap.json该组跨度内读出的真实锚点秒数(不是示例时间); - 若模板的自然停止点与组跨度末端不一致,向最近的锚点对齐(snap)。
catalog 中 8 个模板及其参数(可直接照抄的键名清单):
| 模板 | 适用(Reach for it when 摘要) | Best span | Params 键 |
|---|---|---|---|
card-flyby | 加速的离散 onset 流,逐个闪出标题/项目/海报,停在持握卡上 | 4–6.5s(4–7 次 landing) | theme,bgColor,cards,landings,yaw |
held-message-living-field(phrase_flow) | 平缓/稀疏段、onset 荒漠,持握一个词/标记呼吸 | 6–16s(长组例外) | markText,titleText,tagText,palette,flowSpeed,duration |
held-text-strobe-burst | 密集猛击的 roll/fill + 单个词,纹理闪烁数小节 | 1.2–3.5s(上限 ~4s) | markText,fontStyle,markScale,idleColor,idleInk,frames,strobePlan,decor,duration |
intro-kinetic-cascade | 开场陈述:短句逐词落为巨号字,以关键词 + 图标(铃/光标/星/emoji/SVG)收尾 | 3.5–7s(2–4 个 phrase 拍) | theme,icon,phrases,climax |
logo-split-lockup-pulse | 短 logo/品牌 sting:快速密集 onset + 持续 roll 床 | 2–4s(>4.5s 就过长) | bgColor,markColor,textColor,leftMark,rightMark,word1–word4 |
poster-tile-mosaic | 大量可独立定位的 onset + 有明确子相位的密集段(accumulate → recolor-on-roll → fill-then-drop),宜整体当一个丰富 tile 程序 | 4–7s(有子相位时 ≤8s) | bgColor,tiles,bands,gap,showText,labels,program |
roll-flipbook-word-cycle | 快速持续填充 roll(每分钟数百击、约 1/16 音符),无单一可读信息 | 1.2–3.8s(一次 roll 到一次收束) | bgColor,textColor,accentColor,flipWords,resolveText,periodChar |
typewriter-phrase-keyword-shuffle | 稳定网格 + 连续 onset 流:先打字拼出一句,再让一个关键词换字体 | 2.5–5s | bgColor,textColor,accentColor,lead1–lead3,keyword,periodChar |
catalog 还给了组时长纪律(duration discipline):Best span 指模板系统在做有效运动的「活跃处理跨度」,结尾短而可读的持握可以,长而空洞的尾巴说明该换组;超过 ~6s 的帧通常需要 2+ 组;roll 类模板是「一次 roll 一个工具」,一帧两次 roll 或 roll 之间有 drop 就要拆成两组;不得靠整体放慢 tween 来延长——保留模板的运动手感,用 hold / 调色 / 新组补足时间。
品牌同样来自frame.md而非模板:模板自带演示调色(theme/palette/颜色参数),规划时用项目预设的颜色与字体去填这些参数,模板出「运动 + 布局」,预设出「样子」。
方案 B:自由组合(free-compose)
没有合适模板时,写一个free_design:从 motion-primitive-catalog.md 取一个视觉论点(visual thesis)——一个主导系统(dominant system)+ 若干命名的 L0 原语 + 一个密度拓扑(density topology)——外加anchors(动作骑乘的真实 beat/onset 秒数)。文档强调:自由组合是一等公民(first-class)选择,须与匹配模板的组写得一样仔细——它绝不是失败态。
原语目录提供约 40 个 L0 配方(如hypercut-whip、braam-punch、binary-decrypt、dolly-zoom、content-swap、bg-flow-field、freeze-hold、negative-space-hold等),每个标注锚点类型(beat/drop/roll/silence…)与 best span,并附全套时序纪律:硬击 0ms(tl.set无时长);需要「落在」节拍上的动作提前 40–190ms 启动以便在锚点上完成;缓动入场 300–500ms;宏观构建 800–2000ms;每小节上限(每击至多一个累积元素、镜头运动每短语至多一次、密集翻转/闪烁系统 ≤2–3s);张力构建必须在 downbeat/hard_stop 上收束,不许拖在半拍里。组合原则:一组一个主导系统,至多叠一层纹理原语;结构动作落在强拍、纹理动作落在弱拍;drop≠downbeat(前者是制度切换,可用system-replace;后者只是制度内的切分)。
方案 C:素材处理(asset treatment,仅限用户提供了素材且素材合适时)
把该组写成asset组(规则详见 montage.md),必须遵守pacing:
beat_cut帧:用beat_cut(每个锚点切一个 clip)或bg_under_text;phrase_flow帧:用ken_burns(慢推)或慢交叉淡化——绝不做 per-onset 硬切;- 素材是加成的:若没有任何素材适合某组,回退到模板/自由组合(排版是底线——零素材也能出完整视频)。
montage.md 补充的实现侧约束:clip 必须静音(muted,v1 中 BGM 是唯一音频);<video class="clip">必须是帧根的直接子元素(嵌套会被渲染器冻结);交叉淡化只动画opacity/autoAlpha,不动visibility/display;背景 clip 压暗 ~30–50% 保证前景文字可读;素材仅限本地 staged 资产,禁止远程 URL。
文案(Copy)—— 规划者拥有文字
- 保留用户的原话;否则基于 brief 的情绪、有品味地创作;
- 消息(message)vs 纹理(texture)的判据是可读时长:可读词须持握 ≥1 拍(标题 3–8 拍、句子 4–10 拍),且位置稳定、处于视觉焦点;持握 <1 拍的词是纹理(strobe / grid / ticks)。永远不要把消息硬塞进亚拍(sub-beat)——降格为纹理;
- 文案放进模板的文本参数、自由组的锚点上、或 asset 组的
overlay_copy;声明锚点与 accumulate / stagger 意图,微时序留给 worker; - 收尾 logo / CTA 落在最后一次重击(final hit)/ hard stop 上,并持握过尾部静默。
转场(Transitions)—— 规划者不发射转场
当前版本一切都是 0ms 硬切:
- frame → frame的切分由装配器(assembler)负责(帧文件首尾相接,无间隙),相邻的
span_sec本身已隐含切点; - 帧内 group → group由 worker 在其帧时间轴上负责;规划者只设定每个组的
span_sec。
这与 assemble-index.mjs 的确定性装配逻辑一致:帧无缝平铺整条音轨,所以不存在转场注入器。
写回并校验(Write + validate)
按 storyboard-format.md 补全STORYBOARD.md,然后运行计划校验器并修掉所有✗:
node scripts/validate-plan.mjs --storyboard "$PROJECT_DIR/STORYBOARD.md" \ --audiomap "$PROJECT_DIR/audiomap.json" --templates <SKILL_DIR>/references/templates从 validate-plan.mjs 源码可以直接确认校验的两级结构——这正是 planning.md 中「fix every ✗(hard errors)」与「warnings are best-effort」的机器定义:
硬性错误(任一命中即 exit 1):
- frontmatter
duration_s缺失/不可解析,或与audiomap.audio.duration_sec偏差 > 0.05s; - 未找到任何
## Frame N — <id>帧; - 帧缺
- src:,或- duration:缺失/非正数; - 各帧
duration之和与音轨总长偏差 > 0.1s(帧必须无缝平铺音轨); - 某个帧没有任何已填充的组——即
### Groups仍是TBD (Step 3)/空的 Step-2 骨架。源码注释说明这是刻意设计:让「被跳过的 Step 3 永远到不了构建步骤」。
告警(exit 0,best-effort):
- 组头声明为 template 但行内没写模板 id;
- 模板 id 在
templates/<id>/index.html下不存在(即不在 references/templates/ 目录里); phrase_flow帧上出现beat_cut素材处理(应改用ken_burns/crossfade)。
校验通过后,向用户逐帧展示摘要(frame-by-frame summary),迭代直至用户批准——Step 3 是两个人工门禁之一(另一个是 Step 6 渲染批准)。
Self-check 清单(可直接抄用为验收标准)
planning.md 结尾的自检清单,逐项对应上述规则:
frame.md是某个预设的逐字拷贝;frontmatterstyle.font/style.palette取自它(精确值,未杜撰未取整);- 每帧都变成了 ≥1 个组;各组按序平铺帧跨度;无组 < ~1 小节;无组边界落在
rolls[]运行内部; - 每个组恰好是 template / free_design / asset 三者之一(never two, never none);
- 模板
params的键与该模板的 catalog 条目一致;role_bindings/anchors使用的是 audiomap 的真实秒数; - 素材处理遵守
pacing(phrase_flow帧无beat_cut); - 每个组的 palette 都取自唯一一套品牌色板;
duration_s == audiomap.audio.duration_sec;validate-plan.mjs通过。
小结
music-to-video 技能的 Step 3 是一份「WHAT 层」的规划契约:品牌只选一次且逐字继承(Step A),分组跟着处理方案数量走而不是节拍数量走(Step B),每组三选一且必须绑定 audiomap 真实秒数(Step C),文案按「可读写 ≥1 拍」区分消息与纹理,转场全部 0ms 交给装配器与 worker,最终以validate-plan.mjs的硬性校验 + 用户批准作为进入 Step 4 帧构建的前置门禁。配合 storyboard-format.md 的帧/组字段表、template-catalog.md 的选择菜单与 frame-skeleton.md 的可信度边界,这套规划纪律保证了 Step 4 的每个 frame-worker 拿到的都是无歧义、可机器验证的构建规格。
【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考