srt-whiteboard-animation 白板动画时序模型详解:如何把每一笔墨迹落在字幕节拍上
【免费下载链接】srt-whiteboard-animation将 SRT 字幕做成暖米黄纸张底的流式笔迹白板手绘动画 skill:mask 分区遮罩编排 + stream 连续笔迹(ink→color)。项目地址: https://gitcode.com/gh_mirrors/sr/srt-whiteboard-animation
srt-whiteboard-animation 是一个把SRT 字幕转成暖米黄纸张底白板手绘动画的 Skill。它让动画的节奏完全由字幕驱动——先解析字幕时间跨度确定每幕总时长,再按字幕事件的先后顺序串行绘制各区域,最后以 2:1 权重切分"起笔 ink → 添彩 color"两段笔迹。本文用仓库里现成的猴子山案例,带你拆解这套三层时序模型,让每一笔墨迹都落在字幕节拍上。
先看效果:笔迹如何跟随字幕流动 🎬
下面这段动效对应字幕"小猴坐山顶拿香蕉 → 大猴冲来抢走 → 孩子们鼓掌大笑"。注意三个主体是依次出现的:上一个区域的笔画画完并添彩后,下一个区域才开始落墨,整个画面像有人正在纸上边听口播边画。
原始线稿如下,动画中的每一根线条都来自这张图:
三层时序模型:一条完整的节拍链
时序模型(详见 SKILL.md 的"时序模型"章节)本质上是一条三层节拍链,从宏观到微观层层收敛:
| 层级 | 决定什么 | 由谁驱动 |
|---|---|---|
第一层sceneDurationMs | 每幕总时长 | 该幕字幕的时间跨度 |
第二层startMs/durationMs | 每个区域何时起笔、画多久 | 字幕事件的叙事先后 |
| 第三层 ink : color = 2 : 1 | 区域内先铺线稿再添彩的节奏 | 渲染器固定权重 |
三层对齐后,"笔尖落下的瞬间"就自然落在"字幕念到对应事件"的瞬间。
第一层:sceneDurationMs —— 幕时长对齐字幕跨度
用 scripts/parse_srt.py 解析字幕文件,它会做两件事:把每条 SRT 解析成毫秒级startMs / endMs,并按25–35 秒/幕的建议把连续字幕聚成分镜,每幕给出sceneDurationMs:
python scripts/parse_srt.py <字幕.srt> --target-sec 30 --min-sec 25 --max-sec 35这个sceneDurationMs会被写进标注 JSON,成为该幕动画的总时长上限——幕有多长,由口播有多长决定,而不是画面画完才停。
第二层:区域串行作画 —— startMs 不重叠
stream 画法下画面中只有"一支笔",所以同一幕内的区域必须在时间上依次进行:
- 每个区域用
startMs+durationMs定义作画窗口,且窗口之间不允许重叠; - 下一区域从上一区域
startMs + durationMs之后开始,中间留100–300ms 呼吸间隙,模拟真实书写中抬笔换位的节奏; - 未开始的区域在画布上完全隐藏——渲染器用"允许掩码"(区域矩形扣除后续区域与
protectedRegions)保证这一点,因此后画的对象绝不会提前露出线条。
区域排序也不按画面位置,而是按字幕叙事语义:场景铺垫 → 关键人物/物体 → 动作冲突 → 反应/结果,由sequence字段从 1 开始连续编号。
第三层:ink : color = 2 : 1 —— 区域内的两段笔迹
每个区域的durationMs会被渲染器按 stream 画法 切成两段帧:
- 起笔 ink 段(占 2/3):笔尖沿骨架/网格连续滑行,铺下深灰线稿,留足时间让人看清笔迹流动;
- 添彩 color 段(占 1/3):同一区域换原色"点亮",恢复成彩色画面。
权重在 scripts/stream_render.py 的Config中固定为ink_weight = 2 / color_weight = 1,默认 60fps 输出,保证笔尖移动接近连续书写。
凝视收尾:结尾至少停留 0.5 秒
全部区域画完后,渲染器会自动补帧到sceneDurationMs,并强制结尾停留至少0.5 秒完整原图(render_to 凝视逻辑):
gaze_until = max(total_ms, cur_ms + 500)这一段"凝视"让观众看清完整画面,也为下一幕的合并留出干净的接缝。
一张时间表看懂:猴子山香蕉案例
仓库的 examples/scene-01-monkey-mountain-banana.annotation.json 是理解时序的最佳教材。三个区域各绑一条字幕事件,sceneDurationMs为 8600ms:
| 顺序 | 区域 | narrativeRole | 对应字幕事件 | 窗口 (ms) | ink 段 (2/3) | color 段 (1/3) |
|---|---|---|---|---|---|---|
| 1 | left 左侧场景 | 场景铺垫 | 小猴坐在山顶拿着香蕉 | 300 – 2900 | 300 – 2033 | 2033 – 2900 |
| 2 | center 中间主体 | 动作冲突 | 大猴冲来抢走香蕉 | 3000 – 5600 | 3000 – 4733 | 4733 – 5600 |
| 3 | right 右侧反应 | 反应结果 | 小朋友们鼓掌大笑 | 5700 – 8100 | 5700 – 7300 | 7300 – 8100 |
| – | 凝视停留 | 收笔看全图 | — | 8100 – 8600 | 停留 500ms 完整原图 |
注意两个细节:
- 区域 1 结束于 2900ms,区域 2 从 3000ms 起——100ms 呼吸间隙;区域 2 → 区域 3 同理;
- 最后画完是 8100ms,
max(8600, 8100 + 500) = 8600,凝视段恰好补足到字幕跨度。
每个区域在标注里的时序只有两个核心数字,非常轻:
"reveal": { "startMs": 300, "durationMs": 2600 }direction和handPath仅供预览台做矩形代理演示,成片笔迹由渲染器自动生成,无需精调。
预览台调节拍:三个关键操作 ✏️
时序不是拍脑袋定的,全部在本地预览台 assets/preview.html 里可视化调整(Chrome / Edge 打开,点"打开文件夹"载入场景目录即可,无需服务器):
- 改开始/结束(ms):右侧面板直接编辑区域的开始与结束时间,
durationMs = 结束 − 开始(只读),把窗口对齐到该区域对应字幕的时长; - 拖模块列表调整顺序:拖动即自动重排
sequence,选中模块还会自动高亮关联字幕——顺序错了,节拍必然错; - 按播放核对揭示:播放时未开始的区域不显示,可直观检查"是否提前露线"、呼吸间隙是否自然。
没有合适起点时,可用150 像素/秒 × 绘制距离做durationMs的初始估算,再按字幕微调。保存后写回原.annotation.json,sceneDurationMs会自动对齐到最后一个区域结束 + 0.5s。
保存标注后可先用 scripts/render_annotation_preview.py 生成区域编号/方向检查图核对分区,确认无误再走命令行渲染。
常见时序问题与质量检查清单
渲染前后按这份清单过一遍,基本能覆盖所有时序翻车点(完整标准见 SKILL.md):
- 首帧干净:开场是纯暖米黄纸张底,没有任何提前露出的线条;
- 顺序一致:
sequence、startMs与字幕事件先后一致,而非按画面左右排; - 中段抽查:任意重叠模块的中段帧里,未开始区域与保护区不出现;
- 笔尖贴合:手部素材(assets/drawing-hand.png)始终贴近正在推进的笔迹;
- 收尾停留:每幕结尾至少 0.5s 完整画面;
- 多幕合并:用 scripts/merge_scenes.py 按字幕分镜顺序合并,合并后时长与分镜一致。
小结
srt-whiteboard-animation 的时序模型可以浓缩成一句话:幕时长问字幕、出场顺序问叙事、内部节奏问 2:1。三层节拍层层对齐后,渲染器只需忠实地按startMs排队落墨,动画自然与口播同频。掌握这套模型,你就能把任何一份 SRT 字幕变成节奏严丝合缝的白板手绘视频。
【免费下载链接】srt-whiteboard-animation将 SRT 字幕做成暖米黄纸张底的流式笔迹白板手绘动画 skill:mask 分区遮罩编排 + stream 连续笔迹(ink→color)。项目地址: https://gitcode.com/gh_mirrors/sr/srt-whiteboard-animation
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考