Chalkreel — 学习目标输入,无障碍讲解视频输出 是做什么的?
你正在制作一个学习类讲解视频。与追求点击率的 AI 讲解器不同,学习视频从一个可测量的目标出发,有意地管理认知负荷(遵循梅耶的多媒体原则),并将无障碍交付物——字幕、文字记录、音频描述说明——作为一等输出,而非事后补充。旁白中的每一个事实陈述都必须追溯到来源。
观众听到的一切也必须能看见或读到。学习者被告知的一切必须可追溯。没有任何内容可以在没有人工把关的情况下交付。
硬性规则
- 禁止使用生成式视频模型、库存素材或图像生成器来生成场景内容。 所有帧都通过代码绘制(使用 Remotion 组件、SVG、CSS)。这确保了每一帧都是可审查、可差分和可复现的。
- 四个人工审批关口。 未经明确批准(记录在项目日志中),不得越过任何关口:关口 1 目标与节拍图、关口 2 旁白脚本、关口 3 视觉风格、关口 4 最终剪辑。
- 标注所有合成内容。 构造的示例数据、模拟的时间安排和代理审查结果必须在文件本身中标注为“合成”。永远不要将未完成的产物呈现为真实的渲染/TTS 输出。
- 声明先于脚本。 带有来源声明的研究笔记必须在旁白编写之前存在,并且脚本中的任何数字都必须在账本中有对应行。
- 本地优先的 TTS。 默认语音为 kokoro-82m(本地,免费)。支持自带 TTS;未经用户配置密钥,绝不可调用云 TTS。不加载用户未选择的其他本地模型。
输入
objective: 一个可测量的句子(ABCD 格式——目标关口强制要求)
audience: 谁在学习,以及他们假定的先验知识
length: 目标时长(默认 60–120 秒)
language: 旁白语言(默认 en)
拒绝主题。"一个关于光合作用的视频"不是一个有效的输入;运行 scripts/objective-gate.mjs 并与用户迭代,直到目标通过验证。
流水线
目标 + 受众 + 先验知识 + 时长 + 语言
|
+-- 1. 目标关口 objective-gate.mjs;将主题改写为 ABCD 目标;
| 采用面向学习者的 "你将能够..." 表述;
| 根据梅耶分段原则(每节 10-30 秒)生成的节拍图
| << 关口 1:用户批准目标和节拍图
+-- 2. 研究 提取声明,查找来源,编写声明账本
| (claim-001 样式的 ID;带有标题/出版年/来源的出处;
| 宁可措辞模糊,也不要编造统计数据)
+-- 3. 旁白 根据每节预算编写脚本;通过人性化润色检查
| (scripts/lint-narration.mjs 必须返回 0);
| 针对受众进行阅读难度检查
| << 关口 2:用户批准脚本
+-- 4. 风格比选 使用模板渲染同一个节拍的 2-3 个背景/主题变体;
| 用户目视挑选
| << 关口 3:用户选择一种风格
+-- 5. 构建 每节一个 Remotion 段组件(模板/);
| TTS 附带词级时间戳(默认 kokoro-82m,支持自带);
| 构建时间 JSON {segments[].words[{w,start,end}]}
+-- 6. 无障碍 make-srt.mjs(时间对齐 SRT),make-transcript.mjs
| (文字记录 HTML),每节音频描述说明,
| 然后 a11y-lint.mjs 必须通过
+-- 7. 质量控制 根据以下书面标准对渲染帧和脚本评分;
| 编写 qc-report.md 并标注审查方法
| << 关口 4:用户审查最终剪辑
+-- 交付内容: video.mp4 + .srt + transcript.html + instructor-notes.md
+ 声明账本 + 完整的审计轨迹(目标、研究、旁白、
故事板、时间安排、QC 报告)
段落时长预算
- 每段 10–30 秒(梅耶分段原则;未经用户覆盖硬性上限为 30 秒)。
- 每 60 秒旁白约 145 个词;每段一个想法。
- 屏幕文本:仅限标签和短句(2–7 个词),切勿逐字照搬旁白(冗余原则)。
- 每段定义:旁白、一个场景类型、屏幕文本、音频描述说明、声明 ID。
TTS 默认设置
- 默认:kokoro-82m,本地。语音:
af_heart(或用户选择)。语速 1.0。 - 从 TTS/对齐器中捕获每个词的时间戳并存入时间 JSON。如果 TTS 无法输出时间戳,则使用强制对齐器;切勿猜测时间——猜测的对齐会导致字幕漂移,而往返检查只能捕获文本不匹配,但无法捕获时间漂移。
- 自带 TTS:任何能返回词级时间戳的引擎均可;在项目日志中记录引擎和语音。
脚本(均为独立运行,node >=18,无依赖)
| 脚本 | 用途 | 返回 0 表示 |
|---|---|---|
scripts/objective-gate.mjs "<objective>" | 验证 ABCD 目标 | 目标是可测量的 |
scripts/lint-narration.mjs <script.txt> | AI 写作特征检查器(在 TTS 前运行) | 脚本听起来足够人性化可录制 |
scripts/make-srt.mjs <timing.json> --out x.srt | 从时间 JSON 生成时间对齐 SRT | SRT 已写入 |
scripts/make-transcript.mjs --timing <timing.json> --storyboard <sb.json> --out t.html | 生成可访问的文字记录页面 | HTML 已写入 |
scripts/a11y-lint.mjs <storyboard.json> | "没有仅音频信息" + 交付内容检查 | 每个旁白事实都在屏幕上或文字记录/AD 说明中 |
负面测试用例位于 examples/ (bad-narration.txt, bad-storyboard.json)——始终通过在这些文件上运行 lint 并确认它们失败来验证新环境的设置。
文件格式
timing.json — 词级时间戳(来自 TTS 对齐):
{ "video": { "title": "...", "fps": 30 },
"segments": [ { "id": "seg-01", "text": "...", "start": 0.0,
"words": [ { "w": "Close", "start": 0.1, "end": 0.34 } ] } ] }
storyboard.json — 每段一个对象:
{ "video": { "title": "...", "fps": 30, "width": 1920, "height": 1080,
"srtEmitted": true, "transcriptEmitted": true, "claimsLedger": "path" },
"segments": [ { "id": "seg-01", "title": "Hook", "sceneKind": "statement",
"startSec": 0, "durationSec": 18.2, "narration": "...",
"visual": { "backdrop": "chalkboard", "description": "...",
"onScreenText": ["Recall beats rereading"] },
"audioDescriptionNote": "...", "claims": [] } ] }
sceneKind 映射到一个模板组件:statement、definition、timeline、cycle、list、caption。在模板中添加新的场景类型,而不是在项目内创建一次性组件。
QC 标准包(对照以下书面标准对渲染输出进行评分)
QC 代理不会“观看”视频并发表意见。它使用引用性的观察结果对每个标准进行通过/失败评分。帧级检查需要渲染帧;脚本级检查在交付物上运行。将结果写入 qc-report.md,并标注审查方法(例如“代理启发式审查”)。
脚本级(每次运行)
- 目标对齐 —— 每个段落都推进已批准的目标;任何不符合的内容都要删除(一致性原则应用于目标)。
- 声明可追溯性 —— 旁白中的每个数字、日期或具名发现都在声明账本中有对应行并附有来源。任何孤立事实均判为失败。
- 旁白润色 ——
lint-narration.mjs返回 0。 - 阅读难度 —— 句子平均长度不超过约 17 个词;没有未经解释的技术术语;使用具体动词而非抽象概念。
- 无障碍包 ——
a11y-lint.mjs返回 0;SRT 和文字记录存在;每个段落都有音频描述说明。
帧级(对每个段落的渲染帧或截图进行检查)
- 信号 —— 当前时刻的关键术语/数字在旁白的同时被视觉突出显示(粉笔下划线、颜色、箭头)。
- 一致性 —— 屏幕上没有装饰性元素;每个元素都对应一个旁白概念;除非用户要求,否则没有背景音乐。
- 冗余 —— 屏幕文本不与旁白逐字重复;它应为标签和短句。
- 空间邻近 —— 标签紧邻其描述的对象;帧内没有图例与图表之间寻宝式的距离。
- 时间邻近 —— 元素的揭示与其旁白行同步(对照 timing.json 检查),不会提前或延迟显示。
- 易读性 —— 粉笔线条与背景对比度足够(屏幕文本等效物 > = 4.5:1);在 1920x1080 或 1280x720 的分辨率下没有内容被裁剪。
- 动画预算 —— 动画在 1.2 秒内稳定下来;在介绍不同概念时,句子播放期间没有元素移动。
每项评分 PASS/FAIL 并附上证据。1–5 项中任何 FAIL 都会阻止关口 4。6–12 项中任何 FAIL 都需要修复并重新渲染该段落,或获得用户的明确接受。
风格默认设置(关口 3 比选)
- 背景:
chalkboard(深石板绿,细微纹理,柔和渐晕)。比选备选项:paper(暖灰白,墨水线稿),night(近黑色,单一强调色)。 - 调色板:粉笔白为主色,一个强调色(琥珀色 #FFC66D)用于高亮。仅当信号需要时才能高亮。
- 字体:大号(1080p 下 >= 64 px),高对比度;字幕位于底部中央并带有半透明背景,最多 2 行/每行 42 个字符。
- 尊重观众:禁止闪烁(> 3 次/秒),动画快速稳定,进度条显示章节位置。
审计轨迹(全部提交)
01-objective.md (+ 关口输出) 05-timing.json
02-research-notes.md 06-subtitles.srt
03-narration.md 07-claims-ledger.md
04-storyboard.json 08-qc-report.md
审计轨迹与视频本身同样重要:它使得流水线可被其他教学设计人员审计。
诚实限制(在项目日志中说明)
- 代理 QC 是模型进行的启发式审查,而非专家背书。
- 不得声称输出“经过教学验证”——这需要学习者测试,而本技能不执行该测试。
- 时间对齐字幕的质量取决于 TTS 对齐的质量;在关口 4 之前,对 10 个提示与音频进行抽检。
- 语音许可:kokoro-82m 的语音有其自身的使用条款;在商业分发前请检查。
归属
方法层面参考,未复制代码:anything2explainer(PolyForm 非商业许可——仅方法,参见本仓库的 ATTRIBUTION.md),来自 vox-director(MIT)的关口审批流程模式,以及来自 blader/humanizer 和 Wikipedia 的“AI 写作特征”清单概念(本仓库的 lint 是独立实现)。