| name | manim-viz |
| description | Use when writing Manim Community Edition (manim 0.20.x) animation scripts from natural-language or mathematical descriptions; symptoms include `FileNotFoundError: 'latex'` from `Axes.get_axis_labels`, silent updater freezes during `self.wait()` despite `Played N animations` log, repeated `NameError` on `DOWN`/`UR`/`RIGHT` after `from manim import *`, or defaulting to `-qh` renders during debug. |
Manim Community Edition
5 步写出可发布的数学动画:写 Scene → -ql 跑 → 抽帧检查 → -qh 跑 → 按 renders/<date-topic>/ 发布。
何时用
写 NL→manim 代码 时。典型触发:
FileNotFoundError: 'latex'(LaTeX 缺失 + 用了 MathTex/Axes.get_axis_labels)
NameError: 'DOWN'/'UR'/'RIGHT' after from manim import *
- manim 跑过但画面冻结 / 数字变形 / 卡片溢出画面外
- 默认上
-qh,单次迭代 5 分钟
5 步快速上手
1. 项目骨架(如首次)
scripts/init_project.sh my-slug 2026-07-01 ← 一次性建完整目录
2. 改 src/<slug>.py 写 Scene(参考 references/examples.md)
├─ 显式 import(绝不用 `from manim import *`)
├─ 不调 MathTex / Axes.get_axis_labels / DecimalNumber
│ └─ 改用 Text + Unicode + 手动 next_to(references/api-cheatsheet.md)
│
3. 渲 debug + 抽帧检查(scripted)
scripts/render_scene.sh src/<slug>.py <Scene> ql renders/<id>/renders/debug
scripts/extract_frames.sh renders/<id>/renders/debug/*.mp4 frames 0.1 0.3 0.5 0.7 0.9
├─ 看 5 张 PNG,walk references/frame-check.md 的 13 条 checklist
├─ 失败 → 改 Scene,重跑 step 3(脚本会复用 build/)
└─ 通过 → step 4
│
4. 渲 final
scripts/render_scene.sh src/<slug>.py <Scene> qh renders/<id>/renders/final
│
5. thumbnail + 填 meta.json(参考 references/render-project-layout.md)
ffmpeg -ss MID -i renders/<id>/renders/final/*.mp4 -frames:v 1 renders/<id>/thumbnail.png
3 个最致命的陷阱(其余 19 条在 references/anti-patterns.md)
1. updater 形参必须字面叫 dt —— 否则 silent freeze
Mobject.has_time_based_updater() 用 inspect.signature 字面检查形参名。改名 dt_wall 后 self.wait() 不 tick,画面冻结,manim 日志照常 Played N animations。
particle.add_updater(lambda m, dt: m.move_to(...))
particle.add_updater(lambda m, dt_wall: m.move_to(...))
2. LaTeX 类 API —— 先 check_latex.sh 再决定,否则隐式崩
MathTex / Tex / Axes.get_axis_labels / Axes.add_coordinates / DecimalNumber / Integer 都内部 spawn pdflatex。LaTeX 缺失时全崩,stack trace 末端 FileNotFoundError: 'latex' 让人以为是 LaTeX 问题、实际是 manim 隐式调用。
先检测,按退出码选路:
scripts/check_latex.sh
scripts/check_latex.sh --probe
- 可用(exit 0) → MathTex / Tex / 轴标签 / DecimalNumber 放心用(真公式
∫₀¹x²dx=⅓ 比 Unicode 上标专业)。
- 不可用(exit 1) → 全改
Text+Unicode 上标(Text("x²")),见 anti-patterns.md #3-6 #13。
CJK 中文始终用 Text(Pango)——Tex/MathTex 无中文字体,与 LaTeX 是否可用无关。
3. 渲染每个 Scene 后必须抽帧检查
manim bug不崩、只在像素层面暴露:文字偏心、色块没盖住副标题、卡片溢出、polyline 中心非 0。完全套用 references/anti-patterns.md #19-22 与 references/frame-check.md 的 13 条 checklist 解决。
Wall-clock 预算门禁(编码前必须完成)
从"建议"升级为硬门禁。这是 manim-viz baseline 里最大的剩余漏洞——
跳过规划直接写代码,实际时长经常比目标短 1–5 秒(已观察 13.07s vs 12s)。
根因:没在编码前把每个 beat 的时长钉死,让 manim 默认 run_time=1.0 替你决定节奏。
写第一行 construct 之前,先产出一张 beat × 时长表(可见计划):
| beat | 内容 | 动画 | run_time | wait | 小计 |
|---|
| 1 标题入场 | FadeIn 标题 | FadeIn | 0.6 | 0.4 | 1.0 |
| 2 主体揭示 | Create 图形 | Create | 1.2 | 0.3 | 1.5 |
| 3 强调 | Indicate 焦点 | Indicate | 0.8 | 0.2 | 1.0 |
| … | | | | | |
| 合计 | | | | | ≈ 目标秒数 |
公式 total = Σ run_time + Σ wait,合计应 = 设计目标 ±0.3s。beat 内容骨架见 references/examples.md。
门禁:没有这张表不算"开始编码"。 照表填 run_time=,别留默认。
验收(渲染后,对应 frame-check.md #12):
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 renders/.../debug/*.mp4
实测 vs 表合计,偏差 >0.5s 就回表查哪个 beat 漂移(通常是 wait 漏算,或 Transform 默认 1s 没覆盖)。
渲染分辨率:480p 迭代 / 1080p 定稿
调试别上来就 -qh(1080p60,单次 ~5min)。分阶段省 ~4× 时间:
| 阶段 | 质量 | 分辨率 / fps | 命令 |
|---|
| 写代码 + 迭代 | -ql | 480p15(<30s/次) | scripts/render_scene.sh ... ql |
| 视觉验证(frame-check + frame_audit) | -ql 起,看不清升 -qm | 480p15 / 720p30 | 同上 |
| 最终定稿 | -qh | 1080p60 | scripts/render_scene.sh ... qh |
设计基准 ≠ 渲染分辨率。 字号、间距、坐标一律按 1080p 基准 写(坐标系 14.22×8、字号层级见 references/style-guide.md),但视觉行为在 480p/720p 上验证就够——几何碰撞、溢出、拥挤都与分辨率无关(frame_audit.py 用的就是 1080p 坐标基准)。所有改动在低分辨率跑通后再升 -qh 定稿,别在 1080p 上 debug。
References 索引
8 份长尾文档按需求查阅:
helper 脚本(8 个,缺哪个调哪个):
| 脚本 | 何时用 |
|---|
scripts/render_scene.sh <script.py> <Scene> <quality> <out_dir> | 渲一个 Scene(含 cd/mv/清 build)。替换 SKILL.md "5 步" 里 step 2/4 那一串手动命令 |
scripts/extract_frames.sh <mp4> <out_dir> [t1 t2 ...] | 渲完抽 5 帧 → frame-check 13 条 |
scripts/bbox_audit.py | 渲染期包围盒采集:scene.py 继承 AuditedScene 即用(render_scene.sh 自动配 PYTHONPATH) |
scripts/frame_audit.py [bbox.jsonl] [--strict] | 渲染后自动审计溢出/重叠/拥挤,退出码可阻断(配合 frame-check) |
scripts/check_env.sh | 任何 install/迁移后确认环境健康(uv/ffmpeg/pdflatex/manim) |
scripts/check_latex.sh [--probe] | 写公式前检测 LaTeX 可用性(exit 0→可用 MathTex / 1→回退 Text+Unicode) |
scripts/cleanup.sh [dir] [--dry-run/--force] | 删 _build/ partial_movie_files/ *.pyc,迭代多了能盘胀 |
scripts/init_project.sh <slug> [date] | 开新动画一键建 renders/<date>-<slug>/ 骨架(含 meta/README/占位 src) |
怎么选 manim 还是 Remotion
- manim(这个 skill):数学 / 算法可视化,几何变换,程序化的科普视频
- Remotion(
remotion-vid skill):React 组件驱动视频,营销 / 产品展示,rich motion design
两个 skill 互补不同范式——选对工具再开始写。
课程类视频中的 Manim 边界
技术课程中,先判断镜头表达是否需要 Manim,而不是先看本地有没有现成场景。
课程项目存在 episode JSON 和 orchestrator 时,Manim 只生产带指纹的输入资产:
- scene、渲染 profile、源码和依赖必须进入课程 adapter 的输入指纹;
- Manim 产物由 Remotion 合成后再进入课程 Candidate 和统一审查;
- 本 skill 的独立项目
renders/<date-topic>/、thumbnail 和发布步骤只适用于没有课程 adapter 的独立动画;
- 不得把 Manim 的独立
current、promote 或 publish 当作课程 Current/Release,也不得绕过课程 orchestrator 直接替换正式成片。
优先用 Manim:
- 对象关系:blob / tree / commit、parent 指针、内容寻址。
- 图结构:DAG、merge base、three-way merge、rebase 复制提交。
- 抽象过程:快照流、hash 变化传播、状态机、算法步骤。
- 需要构建期几何检查:节点、箭头、标签不能重叠,方向必须稳定。
不要用 Manim:
- 课程品牌片头/片尾、标题、字幕、进度条。
- 终端输入、代码窗口、diff、文件树。
- 大段解释文字或 bullet 总结。
如果一个镜头适合 Manim 但没有现成 scene,应新增 scene,而不是让 Remotion 临时硬画复杂关系。Manim 输出低文字结构动画,Remotion 用 ManimClip 合成字幕、进度和课程包装。
Manim scene 完成后必须做两层检查:
- Manim 内部:
assert_no_overlap、assert_inside_frame 检查对象几何。
- Remotion 合成后:抽最终成片 still,确认字幕、标题、进度条没有压住 Manim 图形。