Manim 是一个用 Python 写数学动画的开源项目,GitHub 仓库名是 3b1b/manim。它由 3Blue1Brown 的作者 Grant Sanderson 开发,目的是把数学解释视频里的图形、公式和运动编排变成可复现的代码。很多人第一次接触 manim,是在 3Blue1Brown 的线性代数系列、微积分系列或神经网络视频里,被那些平滑缩放、连续变换的画面吸引,于是想去了解这个动画引擎本身。这也是“manim 官网”这类搜索词持续出现的原因:人们需要先找到正确的项目入口,再决定是看默认视频、读 README,还是动手安装。
这篇文章会围绕 3b1b/manim 这个原始仓库展开,并把它和当前更活跃的 Manim Community Edition 对比清楚。实际动手之后,你应该能够完成这样几条主线:弄清楚 ManimGL 与 Community 的差异并正确安装;理解 Scene、Mobject、Animation 三个核心概念;写出一个包含几何图形和数学公式的动画;用命令行控制分辨率、帧率和输出格式;遇到 LaTeX、ffmpeg、中文字体等常见问题时,按可复现的顺序排查。
1. Manim 是什么,以及为什么适合做数学动画
1.1 数学解释视频需要的不是 PPT,而是“可控的运动”
传统科普视频解释一个公式时,常用静止的公式加旁白,或者用 PPT 动画做简单的淡入淡出。但数学里很多概念本质上是动态的,比如极限逼近、向量在坐标系里的旋转、函数的切线逐渐贴合曲线。把这些过程做成动画,观众才更容易理解“变化”本身。
Manim 解决的正是这个难题。它不是一个通用的视频剪辑软件,而是一个面向“数学对象”的动画框架。开发者在代码里描述图形、公式、坐标和动作,Manim 负责把每一帧渲染出来,再合成视频。和逐帧手绘动画相比,用代码写动画有三个明显优势:
- 精确:图形坐标、颜色、旋转角度都由代码决定,可以精确到像素。
- 可修改:改一个参数就能重新渲染,不需要在时间轴上找关键帧反复调整。
- 可复用:一个图形对象、一组动画方法都可以封装成函数,在多个视频里反复使用。
理解这个定位很重要。Manim 不是用来做普通演示动画的,它的强项是数学符号、几何图形和坐标变换。如果你要做的是产品宣传片或信息图轮播,它并不合适;如果你要解释高数、线性代数、概率论或者物理过程,它几乎是量身定做的。
1.2 两个版本:ManimGL 和 Manim Community 怎么选
搜索“manim 官网”时会发现,这个项目实际上分成了两个方向。一个是原始仓库 3b1b/manim,代码由 Grant Sanderson 本人维护,经常被称为 ManimGL;另一个是社区分支 Manim Community Edition,由一群贡献者维护,包名就叫manim,文档站点是 manim.community。
两个版本的核心思想相同,但 API 细节、安装方式、更新节奏都不一样。最典型的差异是创建图形的动画方法:ManimGL 里常见ShowCreation,Community 里则叫Create。如果拿 ManimGL 的代码直接放到 Community 里跑,大概率会报错。
| 对比项 | ManimGL(3b1b/manim) | Manim Community |
|---|---|---|
| 维护方 | Grant Sanderson / 3B1B 个人工作流 | 社区维护者团队 |
| 安装方式 | pip install manimgl | pip install manim |
| 命令入口 | manimgl | manim |
| API 稳定性 | 跟随视频制作需求变化 | 相对稳定,有发布版本 |
| 文档 | GitHub README 为主 | manim.community 文档站 |
| 典型步骤示例 | ShowCreation(square) | Create(square) |
| 适用人群 | 想复刻 3B1B 风格、研究原始实现 | 大多数新项目和学习者 |
这里要强调一个容易踩的坑:两个包在 Python 里导入时都使用from manim import *,模块名相同。如果在同一个虚拟环境里同时安装manim和manimgl,导入时会出现不确定行为,甚至直接覆盖。建议每个项目单独建虚拟环境,不要混装。
1.3 学习 manim 前需要具备什么基础
使用 Manim 不需要成为 Python 高手,但至少要有以下基础:
- Python 基础语法:类、方法调用、关键字参数,这是写
def construct(self)的前提。 - 命令行操作:在终端里进入虚拟环境、运行渲染命令。
- 一点 LaTeX 经验:渲染数学公式依赖 LaTeX,至少要会写
e^{i\pi}这类公式片段。 - 了解视频和帧率的基本概念:比如 30 fps 意味着每秒渲染 30 张画面。
如果完全没有 Python 经验,建议先花半天时间做一遍 Python 入门练习,再回来写 Manim 场景。否则遇到语法错误和导入错误时,容易分不清是 Python 的问题还是 Manim 的问题。
2. 环境准备:Python、FFmpeg、LaTeX、渲染器缺一不可
2.1 系统依赖清单
Manim 的渲染链路比普通 Python 库长。简单理解:Python 负责描述场景,Cairo/Pango 或 OpenGL 负责绘制,LaTeX 负责生成公式图形,FFmpeg 负责把帧序列编码为视频。任何一环缺失或版本不对,都会导致运行时报错。
| 依赖 | 作用 | 两种版本是否都需要 |
|---|---|---|
| Python 3 | 运行脚本 | 都需要 |
| FFmpeg | 视频编码 | 都需要 |
| TeX 发行版(TeX Live / MiKTeX / MacTeX) | 编译数学公式 | 需要,除非完全不写公式 |
| dvisvgm | 把 LaTeX 输出转换为 SVG | ManimGL 需要 |
| Cairo / Pango | 文本和图形绘制 | Community 文本渲染需要,ManimGL 编译也需要 |
在 Ubuntu/Debian 系系统上,常见安装命令如下:
sudo apt update sudo apt install python3-pip ffmpeg dvisvgm \ libcairo2-dev libpango1.0-devLaTeX 可以装texlive和常用宏包集合:
sudo apt install texlive texlive-latex-extra texlive-fonts-extra在 macOS 上,如果使用 Homebrew:
brew install ffmpeg dvisvgm cairo pango brew install --cask mactexWindows 用户通常选择 MiKTeX 作为 LaTeX 发行版,再单独安装 FFmpeg 并把可执行文件目录加入 PATH。ManimGL 在 Windows 上安装时经常会遇到 Cairo 编译问题,这也是很多开发者最终选择 Community 的原因之一。
2.2 安装 ManimGL(3b1b/manim 原始仓库)
先创建虚拟环境并激活:
python -m venv .venv source .venv/bin/activate # Windows 下是 .venv\Scripts\activate然后安装:
pip install manimgl如果 pip 安装过程中出现 cairo 相关编译错误,通常是系统缺少 Cairo 开发头文件。先回到 2.1 安装系统依赖,再重新执行 pip install。安装完成后检查命令:
manimgl --versionManimGL 的使用方式和 Community 有区别。直接运行场景会打开预览窗口,需要加-w才会把视频写入文件:
manimgl scene.py SceneName -w -m质量参数中,-l是低质量,-m是中等,-h是高质量,--hd对应 1080p,--uhd对应 4K。实际参数以你安装版本的 README 为准,因为个人维护的项目改动比较随性。
2.3 安装 Manim Community
Community 版本的安装更简单,因为它通过 PyPI 发布标准 wheel,依赖处理更完善:
python -m venv .venv source .venv/bin/activate pip install manim验证安装:
manim --version如果系统缺少 Pango 或 ffmpeg,Community 在渲染文本或合成视频时会给出明确的错误提示。先按 2.1 补上系统依赖即可。
2.4 三分钟环境自检
进入虚拟环境后,依次执行以下命令,确认环境完整:
python --version ffmpeg -version | head -n 1 latex --version | head -n 1 dvisvgm --version manim --version # 或 manimgl --version每一条都能输出版本号,说明基础环境基本可用。如果latex --version报错,后面所有数学公式场景都会失败;如果ffmpeg -version报错,视频文件无法生成。不要等到渲染时才怀疑这些依赖。
注意:环境检查不能只看“命令存在”,还要看版本是否匹配。ManimGL 和较新版本的 Community 对 Python 版本要求不同,安装前先确认当前 Python 版本在官方文档支持范围内。
3. 核心概念:Scene、Mobject、Animation 构成一个动画场景
3.1 Scene:一个场景就是一段镜头
在 Manim 里,每个动画都被组织在Scene子类中。定义一个场景就是写一个继承Scene的类,并实现construct方法:
from manim import * class MyScene(Scene): def construct(self): # 在这里描述要显示的对象和动画 passconstruct方法相当于电影的导演脚本。Manim 按顺序执行其中的add、play、wait等操作,把它们转成视频帧。一个 Scene 不一定是完整视频,它可以是视频里的一小段,比如“从直角坐标系切换到极坐标系”。把一个大视频拆成多个 Scene,每个 Scene 单独渲染,方便反复修改。
Scene 提供的基本操作有四个:
self.add(mobject):直接显示对象,没有入场动画。self.remove(mobject):直接移除对象。self.play(animation):播放一个动画,这是大多数场景的核心。self.wait(seconds):画面静止若干秒,默认是 1 秒。
理解add和play的区别很关键。add是“瞬移”,对象直接出现在画面上;play是按帧插值,让对象从当前状态平滑过渡到目标状态。
3.2 Mobject:所有可视对象的基类
Mobject 是 Mathematical Object 的缩写,是所有可视对象的基类。圆形、方形、坐标轴、公式、文字,本质上都是 Mobject。
circle = Circle() # 圆形 square = Square() # 正方形 line = Line(np.array([-3, 0, 0]), np.array([3, 0, 0])) # 线段Mobject 自带位置、大小、旋转角度、颜色、透明度等属性,并提供了大量