Manim 视频制作管道
创作标准
这是教育电影。每一帧都在讲授,每一个动画都在揭示结构。
在写任何代码之前,先阐述叙事弧线。它要纠正什么误解?“原来如此”的时刻是什么?什么视觉故事能将观众从困惑带入理解?用户的提示只是一个起点——要用教学野心去诠释它。
几何优先于代数。 先展示形状,再展示公式。视觉记忆比符号记忆编码更快。当观众在看到公式之前先看到几何模式,公式就显得理所应当。
一次性渲染优秀是不可妥协的。 输出必须在视觉上清晰、审美上连贯,无需修改轮次。如果看起来杂乱、节奏不佳或像“AI 生成的幻灯片”,那就是失败。
不透明度分层引导注意力。 永远不要把所有元素都设成最高亮度。主要元素设为 1.0,上下文元素设为 0.4,结构元素(坐标轴、网格)设为 0.15。大脑分层处理视觉显著性。
留白时间。 每个动画之后都需要 self.wait()。观众需要时间吸收刚才出现的内容。切勿仓促地从一帧动画跳到下一帧。关键揭示后停顿 2 秒永远不浪费。
统一的视觉语言。 所有场景共享调色板、一致的字体大小和匹配的动画速度。一个技术上正确但每个场景都用随机颜色的视频是审美上的失败。
先决条件
运行 scripts/setup.sh 验证所有依赖。需要:Python 3.10+、Manim Community Edition v0.20+ (pip install manim)、LaTeX(Linux 上为 texlive-full,macOS 上为 mactex)和 ffmpeg。参考文档已针对 Manim CE v0.20.1 测试。
模式
| 模式 | 输入 | 输出 | 参考文档 |
|---|---|---|---|
| 概念讲解 | 主题/概念 | 具有几何直观的动画解释 | references/scene-planning.md |
| 公式推导 | 数学表达式 | 分步动画证明 | references/equations.md |
| 算法可视化 | 算法描述 | 带数据结构的逐步执行过程 | references/graphs-and-data.md |
| 数据故事 | 数据/指标 | 动画图表、对比、计数器 | references/graphs-and-data.md |
| 架构图 | 系统描述 | 组件逐步构建并连接 | references/mobjects.md |
| 论文讲解 | 研究论文 | 关键发现和方法的动画呈现 | references/scene-planning.md |
| 3D 可视化 | 3D 概念 | 旋转曲面、参数曲线、空间几何 | references/camera-and-3d.md |
技术栈
每个项目一个单一 Python 脚本。无需浏览器、Node.js 或 GPU。
| 层 | 工具 | 用途 |
|---|---|---|
| 核心 | Manim Community Edition | 场景渲染、动画引擎 |
| 数学 | LaTeX (texlive/MiKTeX) | 通过 MathTex 渲染公式 |
| 视频 I/O | ffmpeg | 场景拼接、格式转换、音频混合 |
| 语音合成 | ElevenLabs / Qwen3-TTS (可选) | 旁白配音 |
管道
规划 --> 编码 --> 渲染 --> 拼接 --> 音频 (可选) --> 评审
- 规划 — 编写
plan.md,包含叙事弧线、场景列表、视觉元素、调色板、旁白脚本 - 编码 — 编写
script.py,每个场景一个独立可渲染的类 - 渲染 —
manim -ql script.py Scene1 Scene2 ...用于草稿,-qh用于生产 - 拼接 — 使用 ffmpeg 将场景片段连接成
final.mp4 - 音频 (可选) — 通过 ffmpeg 添加旁白和/或背景音乐。参见
references/rendering.md - 评审 — 渲染预览截图,对照规划核实,调整
项目结构
project-name/
plan.md # 叙事弧线,场景分解
script.py # 所有场景在同一个文件中
concat.txt # ffmpeg 场景列表
final.mp4 # 拼接输出
media/ # Manim 自动生成
videos/script/480p15/
创意指南
调色板
| 调色板 | 背景色 | 主色 | 辅色 | 强调色 | 用途 |
|---|---|---|---|---|---|
| 经典 3B1B | #1C1C1C | #58C4DD (蓝色) | #83C167 (绿色) | #FFFF00 (黄色) | 通用数学/计算机科学 |
| 暖学术 | #2D2B55 | #FF6B6B | #FFD93D | #6BCB77 | 亲和力强 |
| 霓虹科技 | #0A0A0A | #00F5FF | #FF00FF | #39FF14 | 系统、架构 |
| 单色 | #1A1A2E | #EAEAEA | #888888 | #FFFFFF | 极简 |
动画速度
| 上下文 | run_time | 之后 self.wait() |
|---|---|---|
| 标题/介绍出现 | 1.5s | 1.0s |
| 关键公式揭示 | 2.0s | 2.0s |
| 变换/变形 | 1.5s | 1.5s |
| 辅助标签 | 0.8s | 0.5s |
| FadeOut 清理 | 0.5s | 0.3s |
| “原来如此”时刻揭示 | 2.5s | 3.0s |
字体比例
| 角色 | 字号 | 用途 |
|---|---|---|
| 标题 | 48 | 场景标题,开场文字 |
| 标题 | 36 | 场景内章节标题 |
| 正文 | 30 | 解释性文字 |
| 标签 | 24 | 注释,坐标轴标签 |
| 说明 | 20 | 副标题,小字 |
字体
所有文字使用等宽字体。 Manim 的 Pango 渲染器在使用比例字体时会产生破碎的字间距。参见 references/visual-design.md 获取完整建议。
MONO = "Menlo" # 在文件顶部定义一次
Text("傅里叶级数", font_size=48, font=MONO, weight=BOLD) # 标题
Text("n=1: sin(x)", font_size=20, font=MONO) # 标签
MathTex(r"\nabla L") # 数学 (使用 LaTeX)
可读性最低 font_size=18。
每场景变化
切勿对所有场景使用完全相同的配置。对于每个场景:
- 不同主色调(从调色板中选择)
- 不同布局——不要总是将所有内容居中
- 不同动画入场方式——在 Write、FadeIn、GrowFromCenter、Create 之间变换
- 不同视觉重量——有些场景密集,有些稀疏
工作流程
第一步:规划 (plan.md)
在写任何代码之前,编写 plan.md。参见 references/scene-planning.md 获取完整模板。
第二步:编码 (script.py)
每个场景一个类。每个场景都能独立渲染。
from manim import *
BG = "#1C1C1C"
PRIMARY = "#58C4DD"
SECONDARY = "#83C167"
ACCENT = "#FFFF00"
MONO = "Menlo"
class Scene1_Introduction(Scene):
def construct(self):
self.camera.background_color = BG
title = Text("为什么这有效?", font_size=48, color=PRIMARY, weight=BOLD, font=MONO)
self.add_subcaption("为什么这有效?", duration=2)
self.play(Write(title), run_time=1.5)
self.wait(1.0)
self.play(FadeOut(title), run_time=0.5)
关键模式:
- 每个动画加字幕:
self.add_subcaption("文本", duration=N)或在self.play()中使用subcaption="文本" - 共享颜色常量放文件顶部,确保跨场景一致性
self.camera.background_color在每个场景中设置- 干净退出——场景结束时 FadeOut 所有 mobject:
self.play(FadeOut(Group(*self.mobjects)))
第三步:渲染
manim -ql script.py Scene1_Introduction Scene2_CoreConcept # 草稿
manim -qh script.py Scene1_Introduction Scene2_CoreConcept # 生产
第四步:拼接
cat > concat.txt << 'EOF'
file 'media/videos/script/480p15/Scene1_Introduction.mp4'
file 'media/videos/script/480p15/Scene2_CoreConcept.mp4'
EOF
ffmpeg -y -f concat -safe 0 -i concat.txt -c copy final.mp4
第五步:评审
manim -ql --format=png -s script.py Scene2_CoreConcept # 预览截图
关键实现注意事项
LaTeX 的原始字符串
# 错误:MathTex("\frac{1}{2}")
# 正确:
MathTex(r"\frac{1}{2}")
边缘文本的 buff >= 0.5
label.to_edge(DOWN, buff=0.5) # 永远不要 < 0.5
替换文本前先 FadeOut
self.play(ReplacementTransform(note1, note2)) # 而不是在原来上方 Write(note2)
永远不要对未添加的 Mobjects 做动画
self.play(Create(circle)) # 必须先 add
self.play(circle.animate.set_color(RED)) # 然后做动画
性能目标
| 质量 | 分辨率 | FPS | 速度 |
|---|---|---|---|
-ql (草稿) | 854x480 | 15 | 5-15秒/场景 |
-qm (中等) | 1280x720 | 30 | 15-60秒/场景 |
-qh (生产) | 1920x1080 | 60 | 30-120秒/场景 |
始终在 -ql 下迭代。仅对最终输出渲染 -qh。
参考文档
| 文件 | 内容 |
|---|---|
references/animations.md | 核心动画、速率函数、组合、.animate 语法、时序模式 |
references/mobjects.md | 文本、形状、VGroup/Group、定位、样式、自定义 mobject |
references/visual-design.md | 12 条设计原则、不透明度分层、布局模板、调色板 |
references/equations.md | Manim 中的 LaTeX、TransformMatchingTex、推导模式 |
references/graphs-and-data.md | 坐标轴、绘图、BarChart、动画数据、算法可视化 |
references/camera-and-3d.md | MovingCameraScene、ThreeDScene、3D 曲面、摄像机控制 |
references/scene-planning.md | 叙事弧线、布局模板、场景过渡、规划模板 |
references/rendering.md | CLI 参考、质量预设、ffmpeg、配音工作流、GIF 导出 |
references/troubleshooting.md | LaTeX 错误、动画错误、常见错误、调试 |
references/animation-design-thinking.md | 何时动效 vs 静态显示、分解、节奏、旁白同步 |
references/updaters-and-trackers.md | ValueTracker、add_updater、always_redraw、基于时间的 updater、模式 |
references/paper-explainer.md | 将研究论文转化为动画——工作流、模板、领域模式 |
references/decorations.md | SurroundingRectangle、Brace、箭头、DashedLine、Angle、注释生命周期 |
references/production-quality.md | 编码前、渲染前、渲染后检查清单、空间布局、颜色、节奏 |
创造性发散(仅当用户要求实验性/创造性/独特输出时使用)
如果用户要求创造性、实验性或非传统的讲解方法,请在设计动画之前选择一种策略并充分论证。
- SCAMPER — 当用户希望为标准讲解带来新鲜视角时
- 假设反转 — 当用户希望挑战通常的教学方式时
SCAMPER 转换
对标准数学/技术可视化进行转换:
- 替代:替换标准视觉隐喻(数轴→蜿蜒路径,矩阵→城市网格)
- 结合:融合两种讲解方法(代数 + 几何同时进行)
- 反转:反向推导——从结果开始,解构到公理
- 修改:夸大某个参数以显示其重要性(10 倍学习率,1000 倍样本量)
- 消除:去除所有符号——纯粹通过动画和空间关系解释
假设反转
- 列出该主题“标准”的可视化方式(从左到右、2D、离散步骤、正式符号)
- 选择最根本的假设
- 反转它(从右到左推导、2D 概念的 3D 嵌入、连续变形代替步骤、零符号)
- 探索反转揭示了什么标准方法所隐藏的东西