黑板长卷短视频 · 制作流程手册(一镜到底 · 无限画布)
读者:负责制作视频的 AI Agent。
目标:拿到一篇旁白文字后,按本手册产出一条与本账号既有风格完全一致的竖屏知识短视频。
验收基准:1080×1920 / 片长 = 配音时长 + 4.7s 引导层 / check 全绿(lint 0 error + 文字对比度 100% WCAG AA)/ 多模态读帧质检通过(内容不越安全区,相邻板边缘粉笔除外)/ 整体响度 -11.5 ~ -13 LUFS(2026-09-11 音量重平衡后)。代码与资源:全部代码(引擎、渲染模板、工具脚本)、参考实例、图片/音频资源打包在 blackboard-template.zip 中(文末附下载)。手册只写流程与规范,不复述代码。
1. 成品风格
- 形态:1080×1920 竖屏「一镜到底长卷」——所有内容铺在一张巨大的虚拟黑板画布上,镜头沿画布漫游,配画外音打字机逐字呈现。
- 视觉:每段内容 = 一块带实木框的小黑板(三态:待讲暗淡 → 正在讲点亮+粉笔辉光 → 归档缩小 0.58 褪色沉底);板间用虚线相连;粉笔白/蓝
#86C5FA/黄#E8D44D/红#FF8C7E四色体系;线条图标/手绘 SVG 粉笔化(视觉素材由创作 Agent 按视频内容自行选定)。 - 安全区(硬约束):上下 300px、左右 100px(内容区 880×1320);所有内容含动画过程不得越出。卡片上下内边距 34px、图示内容整体缩进 31px。
- 文字:正文 44px 上限,按句子分块自然折行,打字机逐字出现(15 字/秒,逗号停 0.16s、句号停 0.32s),关键词着色并弹跳。
- 音频:edge-tts 音色
zh-CN-YunjianNeural语速 +30%,loudnorm 归一到 -14 LUFS;混音时旁白再 +2 dB(≈ -12 LUFS,限幅保护峰值),BGM 固定用c260.mp3(DJ L《C260》)volume 0.22(≈ -21.3 LUFS)无闪避,淡入 1.5s / 淡出 5.5s。人声与 BGM 响度差约 9 LU(2026-09-11 重平衡:原 0.3 配方 BGM 偏大、旁白偏小)。 - 结尾:镜头拉远看整面黑板 → 覆盖「高老师的分享局」关注引导卡(logo 用
logo.png。
2. 代码包与目录结构
本手册与代码包 blackboard-template.zip 一起参考(代码、参考实例、图片/音频资源全在里面)。解压后得到:
blackboard-template/
├── README.md ← 包内速览(内容清单 + 依赖)
├── template/ ← 引擎层(冻结层,除 bug 修复外不要动)
│ ├── composition/index.html ← 渲染工程模板壳(CSS+DOM+@@ENGINE@@ 占位符)
│ ├── composition/{package.json, hyperframes.json}
│ ├── engine/core.js ← 引擎本体:排布/镜头/黑板三态/连线跟随/打字机/CTA/动效工具
│ ├── assets/ ← 图片音频资源(见下表)
│ └── tools/ ← 5 个 Python 脚本(见下表)
└── example/ ← 参考实例 hidden-state 项目源文件
├── script.txt ← 旁白原文(空行分段)
├── config.js ← 项目参数示例
└── boards.js ← 图示创作示例(14 个 case,覆盖全部常用模式)
每个短视频 = 一个独立项目目录(new_video.py 创建,位置任意,与 blackboard-template/ 平级或另放):
<视频项目>/
├── script.txt ← 旁白文字,空行分段(唯一文字输入)
├── config.js ← 项目参数
├── boards.js ← 图示创作(Agent 独立实现)
└── build/
├── audio/ ← tts.py 输出(s{i}.wav/.srt、narration.m4a、narration_bgm.m4a)
└── composition/ ← 自包含渲染工程
├── index.html ← 模板壳 + 内联引擎
├── assets → template/assets
├── audio → build/audio
├── config.js / boards.js → 项目源文件 (symlink)
├── scenes_data.js
└── renders/ ← 渲染输出
资源清单(都在 template/assets/,解压即得,无需手动放置):
| 文件 | 用途 |
|---|---|
board_wall.jpg | 烘焙好的整面黑板墙(板面+木框一体),camPan 背景 |
wood_frame_9.png | 实木框九宫格贴图(卡片 border-image) |
logo.png | 账号 logo(结尾引导卡) |
bgm/c260.mp3 | 背景音乐(DJ L《C260》,129.3s) |
wood_frame_src.jpg | 木纹原图(CC BY-SA 4.0,仅重制贴图时用) |
工具脚本(都在 template/tools/,用系统 python3 跑,依赖仅 ffmpeg/ffprobe + edge-tts + Pillow/numpy):
| 脚本 | 作用 |
|---|---|
new_video.py <项目路径> | 视频项目脚手架(创建独立项目目录 + 自包含渲染工程;已存在则刷新渲染工程,不覆盖源文件) |
tts.py <视频项目> | script.txt → 配音 build/audio/narration.m4a(-14 LUFS)+ 各段 srt/wav |
build_scenes.py <视频项目> | 配音 srt → build/composition/scenes_data.js(打字机时间轴) |
mix.py <视频项目> [--mux <video>] | C260 固化配方混音;--mux 时合成 build/final.mp4 |
3. 制作流程
Step 0 创建视频项目
首次使用先解压 blackboard-template.zip,下文以解压出的 blackboard-template/ 为根。
cd <blackboard-template>/template/tools
python3 new_video.py ../../my-video # 项目名自取;一个文档 → 一个独立项目目录
产出项目目录骨架。★ 闸门 1:分段——把用户的旁白文字填入 script.txt(严格原文,不优化;空行分段,一段=一块画板),把分段结果给用户确认。
Step 1 配音
python3 tts.py ../../my-video
产出 build/audio/narration.m4a + 各段 s{i}.wav/.srt,并打印「回填 config.js」的 4 个时长参数。★ 闸门 2:试听 narration.m4a 给用户确认。
Step 2 时间轴
python3 build_scenes.py ../../my-video
产出 build/composition/scenes_data.js。核对输出段数/总时长与 Step 1 报告一致。
Step 3 回填 config.js + 图示创作 boards.js
见 §4(config.js 字段)与 §5(结构边界与图示创作)。这是每个视频的核心创作步骤。
Step 4 检查与渲染
cd ../../my-video/build/composition
npm run check # 必须全绿:lint 0 error + 文字对比度全部 WCAG AA
npm run render # 约 1-3 分钟,输出 renders/composition_*.mp4
Step 5 质检(多模态读帧)
抽 14-16 个关键帧(每块画板收尾时刻 + 开头 1s + 结尾 CTA,时刻取 scenes_data.js 各段 end 附近),用多模态大模型逐帧读图检查:
- 内容是否越出安全区(上下 300px、左右 100px);边缘轻微越界若为相邻画板的边缘粉笔(背景允许溢出)可放行
- 图示与文案语义匹配、无文字贴木框、光点 fade 不越归档
- 打字机进度与画面元素对应(正在讲的板应是点亮态)
发现问题改 boards.js / config.js 后回到 Step 4。
★ 闸门 3:成片画面给用户审。
Step 6 混音出片
python3 ../../../template/tools/mix.py ../../my-video \
--mux <composition 目录下 renders 里的 mp4 路径>
产出 build/final.mp4(视频流不重编码)。实测整体响度应在 -11.5 ~ -13 LUFS、真峰 < 0 dBTP。★ 闸门 4:终审交付。
4. config.js 字段说明
window.EP_CONFIG = {
duration: 123.5, // 片长 = narrDuration + 引导层停留(一般 +4.7s)
narrDuration: 118.8, // tts.py 报告的配音成片时长
outStart: 116.8, // 收尾拉远开始 ≈ 最后一段打字结束前 0.2s(留 0.1 给归档动画)
outDur: 1.6, ctaIn: 118.5, // ctaIn ≈ narrDuration - 0.3
zoomOut: 0.137, // 全景比例(整面黑板缩进视口),固定
cols: [0,0,1,1,0,...], // 每段所在列:0=左列 1=右列,长度=段数。建议左右交错(0,0,1,1 循环)
vh: [430,430,...], // 每段图示区高度(340-560,简单段小、复杂段大),长度=段数
zoomPeeks: [[5,30.0,36.5],...], // 关键节点整板展示 [[段号(1起), 拉远开始, 拉回结束], ...] 0-3 处
keywords: [["hidden state","b"],...] // 打字机关键词着色:b=蓝 g=黄 r=红
};
cols/vh 的确定方法:读完文案后按每段信息量预估(数字统计类段 vh 420-520、单纯叙述段 340-430),首渲后按画面微调。完整示例见 example/config.js。
5. boards.js:结构边界与图示创作
画布与画板的结构、样式全部由引擎负责;boards.js 只负责画板下半图示区的内容创作,其余一律不要碰。
5.1 固定结构与样式(引擎强制,勿改)
- 画布:整面黑板墙,镜头沿画布漫游;板间虚线相连。
- 画板:每段文案 = 一块带实木框的小黑板;上半 = 打字机文字区(逐字呈现、关键词着色,文字与时序来自 scenes_data.js);下半 = 图示区(高度 = config.vh)。
- 画板三态:待讲暗淡 → 正在讲点亮+粉笔辉光 → 归档缩小褪色沉底。
- 安全区:所有内容含动画过程不得越出(上下 300px、左右 100px)。
5.2 接口与硬约束
function buildBoards(ctx) {
const { b, i, z, vh, S, E, T, tl, ... } = ctx; // 上下文与可用原语的完整签名见 template/engine/core.js 注释
switch (b.sc.id) { // 从 1 起,对应 script.txt 第几段
case 1: { ... break; }
}
}
- 所有动画时刻用相对语法,绝不写绝对秒:
S/E= 本段配音开始/结束;T(j)= 本段第 j 句(0 起)的开始时刻。例:S + 0.4(段首登场)、T(1) + 1.2(第二句讲到处)、E - 0.15(段尾前收)。 - 图示内容(含动画过程)不得越出
z容器(872 宽 × vh 高)。 - 元素不设入场动画则一直可见——默认都给入场。
- 中英混排的 HTML 字符串写成单行(源码换行会被折叠成空格,中文间多出空格)。
5.3 图示创作(自由发挥)
- 图示区内容完全由 Agent 按本视频文案自行设计:SVG、手绘 path、图形、图表皆可。引擎只提供结构原语(建元素/SVG/路径绘制/入场动画等,签名见 core.js 注释);图标卡、印章、计数等内容动效辅助按本视频需要自建——写法参考
example/boards.js顶部自建辅助的方式。 - 不要套用参考实例的具体图式——
example/boards.js只是接口用法与完成度方面的参考,不是模式库;每个视频的视觉表达应当从文案本身出发。 - 视觉素材自选并直接写进 boards.js(如需用引擎的图标函数,在文件顶部提供
window.ICONS = { 名: "<path…/>" },键名带连字符必须加引号)。
6. 质量清单(交付前逐项打勾)
- check 全绿(lint 0 error,对比度 100% WCAG AA)
- 多模态读帧质检:内容不越安全区(相邻板边缘粉笔除外),图示语义匹配、三态正确
- 每块画板关键帧目检:图示与文案语义匹配、无文字贴木框、动画元素不越画板
- 打字机与配音同步(抽查 2-3 段首句)
- final.mp4 时长 = config.duration;整体响度 -11.5 ~ -13 LUFS,真峰 < 0 dBTP
- 开场无全景跳入(直接第一块板);结尾 CTA 卡 logo/箭头方向正常
模板工程包下载
⬇︎ blackboard-template.zip(5.8MB,26 个文件)——内含渲染工程模板壳、引擎 core.js(画布/画板三态/打字机/镜头/CTA + 结构原语)、4 个工具脚本(new_video / tts / build_scenes / mix)、参考实例 hidden-state 三源文件、全部图片音频资源与素材署名记录。解压即得完整工程,配合本手册 §3 六步流程使用。