课程视频 是做什么的?
你将学生的课程材料转化为学习视频。这个技能有一条独一无二的规则:
视频中的每一个数字、例子和论断都必须来自学生自己的课程材料。绝不允许编造。 学生用这些视频来准备由 他们的 教授出题的考试。一个“更友好”的、使用虚构数字的例子,使用不同记号的公式,或来自课程之外的事实,都是错误,即使它在经济学/物理学等方面是正确的。
0. 环境要求(检查一次)
python3 -m pip install -r requirements.txt && python3 -m playwright install chromium
ffmpeg -version | head -1 # brew install ffmpeg / apt install ffmpeg
可选:用于3D场景和吉祥物主持人的Blender 4.2+(如果不在PATH中,需设置BLENDER=/path/to/blender),
用于读取PDF幻灯片的pdftotext(poppler)或pip install pypdf,用于转录录音的openai-whisper,
以及用于Grok语音的XAI_API_KEY(否则使用免费的微软神经语音)。
1. 收集源材料
创建一个文件夹 <course>/sources/,并将 仅限课程材料 放入其中:
讲义转录稿(.txt/.srt/.vtt)、幻灯片(.pdf或导出的文本)、学生的笔记、习题集、模拟考试题。
- 有录音但没有转录稿 →
whisper lecture.mp4 --model base --output_format txt --output_dir sources/ - .docx →
textutil -convert txt file.docx(macOS)或pandoc file.docx -t plain -o file.txt - 询问学生视频应涵盖哪些讲座/主题。除非被要求,否则不要用其他周的材料填充。
在撰写任何内容之前,请完整阅读所有源材料。注意教授使用的精确记号、术语、讲解的例题和数字。
2. 编写脚本(内容JSON)
按照 engine/SCHEMA.md(视觉类型、提示词、测验格式、布局限制)编写 <course>/<name>.json。
examples/lemonade/ 是一个完整的小型示例。
规则:
- 例题:使用讲座中自带的例题及讲座中的数字。如果讲座中使用的是“价格$4,3单位”,视频中就必须是“价格$4,3单位”,而不是“价格$10,5单位”。
- 测验:从课程中的练习题、课堂投票题或讲解的例题中选取。如果你编写了一个新问题,则必须仅使用源材料中的数字,并在测验标签中注明(“练习”,而非“考试题”)。
- 派生数字(你计算出的总数、差值)是允许的,但必须在顶层
"derived"映射中声明每个派生数字的算术过程,且只能使用源材料中的数字:"derived": {"16": "4 * 4", "-6": "120 - 126"}。 - 非数据的小数量(如“要记住的三件事”、“第2步”)可以放入
"allow": ["3"]。0 和 1 始终允许。 - 记号和术语:使用教授的(如果讲座中写的是“MR = MC”,不要换成“∂R/∂q”)。
- 如果视频需要的事实不在源材料中,请停下来询问学生是否有相关材料,否则就略过。绝不要用通用知识填补空缺。
- 旁白(
say)应写成口语化,文字而非符号(例如“4乘以4等于16美元”)。
3. 对照源材料检查每一个数字(必需步骤,在构建视频之前)
python3 tools/check_sources.py <course>/<name>.json <course>/sources --report <course>/<name>.sources.md
它会提取旁白、屏幕文本、测验选项以及任何3D场景标签中的每一个数字,并在源材料中找到每一个数字(数字形式或拼写形式,例如“one hundred twenty”)。派生数字会被重新计算,并检查其操作数。它必须以退出码0结束,然后你才能开始构建。 对于每个问题,它将报告:
- 数字是拼写错误或编造的 → 修复脚本以使用源材料中的数字;
- 是真正的计算 → 将其添加到
"derived"中; - 在源材料中存在但检查器未能识别(例如在图片中) → 请学生确认,然后将其添加到
"derived"或"allow"中,并在你的回复中添加注释。
然后自行阅读报告的“证据”部分,抽查每个数字在源材料中是否与视频中具有相同的含义(检查器只匹配数值,不匹配含义:例如,$40 表示价格,而40 units表示数量)。
4. 构建与渲染
cd engine
python3 build.py ../<course>/<name>.json # 语音、时间轴、字幕、音乐(如需使用Grok:TTS=xai XAI_API_KEY=...)
python3 lint.py build/<video-id>/spec.json # 检查迟到的视觉效果
python3 qa.py <video-id> # 生成每一个节拍的关键帧 + 联系表:请仔细查看
OUT=../out python3 render.py <video-id> --workers 6 # 全高清1080p渲染 -> ../out/<video-id>.mp4 + .srt
在渲染之前查看QA联系表:检查是否有重叠文字、空屏、屏幕上的数字错误。
5. 可选:3D场景、吉祥物、音效
一个包含 "v": {"type": "clip", "scene": "<name>"} 的节拍会播放来自 engine/blender/scene_defs/<name>.py 的Blender场景
(参见 engine/blender/scenelib.py 中的文档字符串;market.py 和 safe.py 是完整示例,为经济学课程编写,因此它们的标签包含该课程的数字。请修改标签以匹配你的源材料)。
场景标签也会被 check_sources.py 检查。
cd engine
python3 blend.py prep <video-id> # 吉祥物时间轴 + 每个场景的输入
python3 blender/stills.py <scene> --dry # 快速捕捉错误,然后不带 --dry 生成关键帧
python3 blend.py clips <video-id> # 渲染3D场景(较慢:每个场景几分钟)
python3 blend.py mascot <video-id> && python3 blend.py pack <video-id>
python3 sfx.py mix <video-id> # 在旁白下方添加音效
OUT=../out python3 blend.py comp <video-id> # -> ../out/<video-id>-3d.mp4
OUT=../out python3 blend.py site <id1>,<id2> --title "我的课程" --out ../out/site # 生成包含章节的网页
渲染过程较慢且占用大量磁盘空间(运行时每个视频会占据数GB的帧)。请先检查可用空间,笔记本电脑上每次只渲染一个场景,并保持机器唤醒。
6. 交付
告知学生:视频在哪里、时长多少、覆盖了哪些讲座,以及源材料检查结果(检查了哪些数字、哪些是派生或允许的)。如果源材料中存在任何歧义,说明你做出的假设。提醒他们此视频是基于他们的材料制作的学习辅助工具,不能替代讲座,并且课程材料可能不属于他们公开发布:在公开发布视频前请先确认版权。