Manim v0.13.0 版本全解读:副字幕 API、反导数绘图与 API 清理
【免费下载链接】manimA community-maintained Python framework for creating mathematical animations.项目地址: https://gitcode.com/GitHub_Trending/man/manim
本文基于仓库内 v0.13.0 版本变更日志,结合 Manim 源码与测试体系,完整梳理该版本的核心新特性、破坏性变更、缺陷修复与工程化改进,帮助开发者在升级到 v0.13.0 时理解新增
Scene.add_subcaption字幕接口、CoordinateSystem.plot_antiderivative_graph反导数绘图工具,以及一批旧 API 的移除清单,从而平滑迁移既有动画脚本。
版本概览:2021 年 12 月的关键里程碑
Manim v0.13.0 发布于 2021 年 12 月 4 日,是本项目社区维护路线上的重要版本。根据官方变更日志:
- 共27 位贡献者参与了本次发布(姓名带
+标记者为首次提交补丁的新贡献者); - 共39 个 Pull Request被合并;
- 项目官方将其定位于一次兼具新功能落地与遗留 API 清理的版本:一方面引入了副字幕(subcaption)支持与反导数绘图等实用能力,另一方面集中移除了直至 v0.12.0 为止所有已标记弃用的接口。
从版本演进的视角看,v0.13.0 也承担了「承上启下」的角色:它一方面兑现了此前版本中积累的弃用承诺,另一方面为后续版本的文档国际化(i18n)与 OpenGL 渲染器相关能力铺路。对于仍在使用旧版 Manim 的创作者,本版本的破坏性变更清单是最需要优先关注的内容。
核心亮点:翻译流程与文档国际化收尾
v0.13.0 的 Highlights 部分仅列出了一项(PR #2313):最终确定翻译流程并完善相关文档。这对应着仓库中docs/i18n/目录下成体系的国际化文件结构:
docs/i18n/gettext/下存放按版本(如0.13.0-changelog.pot)与按主题(如guides/、reference/、installation/)划分的 gettext 翻译模板(.pot);docs/i18n/fr/LC_MESSAGES/、hi/、pt/、sv/等目录存放各语言已翻译的.po文件。
从仓库结构可以推断,这一改动让社区翻译协作得以按模块化模板并行推进,同时也表明 Manim 文档体系从早期「单一英文文档」走向了「多语言协作维护」的阶段。若你关注本地化参与方式,可在 docs/source/contributing/internationalization.rst 中查看贡献指引。
新特性一:副字幕支持(Scene.add_subcaption)
v0.13.0 最值得创作者关注的新功能,是**为动画场景添加副字幕(subcaption)**的基本支持,对应 PR #2314。该特性让 Manim 场景在渲染视频时能同步产出一条标准的.srt字幕文件,无需再手动对齐时间轴。
两种使用方式
根据 Scene.add_subcaption 的 docstring,副字幕可以通过两种方式加入:
from manim import Scene, Square, Circle, Create, Transform class SubcaptionExample(Scene): def construct(self): square = Square() circle = Circle() # 方式一:通过 add_subcaption 方法,在“当前场景时间戳”处插入字幕 self.add_subcaption("Hello square!", duration=1) self.play(Create(square)) # 方式二:在 Scene.play 调用内直接指定 self.play( Transform(square, circle), subcaption="The square transforms." )方法签名:add_subcaption(content: str, duration: float = 1, offset: float = 0),其中:
content:字幕文本内容;duration:字幕显示的持续时长(秒),默认1;offset:叠加到起始时间戳上的偏移量(秒)。
Scene.play的新增关键字参数(定义见 scene.py#L1188-L1240):
| 参数 | 类型 | 默认值 | 含义 |
|---|---|---|---|
subcaption | str \| None | None | 动画期间要显示的字幕内容 |
subcaption_duration | float \| None | None | 字幕持续时长;为None时取动画的run_time |
subcaption_offset | float | 0 | 字幕开始时间的偏移(秒) |
底层实现链路
从源码看,副字幕的写入经过了完整的「场景 → 管理器 → 文件写入器」调用链:
Scene.add_subcaption将参数转发给Scene._get_manager().add_subcaption(content, duration, offset)(见 scene.py#L1766);- manager.py 的
add_subcaption构造一个srt.Subtitle对象:start = self.time + offset,end = start + duration,并追加到file_writer.subcaptions列表; - 渲染收尾时,scene_file_writer.py 的
write_subcaption_file调用srt.compose(self.subcaptions)将字幕序列化为标准.srt文本,写入由output_plan.subcaption_file指定的文件(默认位于视频产物旁),并输出日志Subcaption file has been written as ...。
值得注意的是,play()方式在 manager.py 中调用add_subcaption时使用的offset = -run_time + subcaption_offset——这是因为字幕的起始时间取自「动画开始时刻」,需要在内部用run_time做换算,从而保证字幕恰好覆盖整个动画过程。
对创作者的实际价值:无需第三方工具即可为数学动画生成与画面同步的字幕文件,便于后期在视频平台上发布带字幕的版本,也便于无障碍传播。
新特性二:反导数图形绘制(plot_antiderivative_graph)
PR #2267 为坐标系统类新增了CoordinateSystem.plot_antiderivative_graph方法,填补了此前「导数图形可绘制、反导数图形缺失」的功能空白。
方法签名与参数
实现位于 coordinate_systems.py#L1552-L1610:
def plot_antiderivative_graph( self, graph: ParametricFunction, y_intercept: float = 0, samples: int = 50, use_vectorized: bool = False, **kwargs: Any, ) -> ParametricFunction| 参数 | 默认值 | 含义 |
|---|---|---|
graph | — | 要求反导数的原函数图形(ParametricFunction) |
y_intercept | 0 | 反导数曲线与 y 轴的交点 y 值(即积分常数 C) |
samples | 50 | 对图形下方区域取点计算面积的采样点数 |
use_vectorized | False | 是否使用向量化版本:为True时将生成的 t 值数组整体传入函数,要求函数支持向量化,输出应为形如[y_0, y_1, ...]的 numpy 数组 |
kwargs | — | 透传给ParametricFunction的任意合法关键字(如color) |
数值实现原理
源码中的核心计算逻辑如下:
def antideriv(x): x_vals = np.linspace(0, x, samples, axis=1 if use_vectorized else 0) f_vec = np.vectorize(graph.underlying_function) y_vals = f_vec(x_vals) return np.trapezoid(y_vals, x_vals) + y_intercept也就是说,该方法通过数值积分实现反导数:从x=0到目标点x均匀采样samples个点,对原函数做向量化求值,再用np.trapezoid做梯形法则积分,最后叠加y_intercept作为积分常数。官方文档同时给出了重要提示:由于图形由 x=0 起算的面积值绘制,若原图形在 x=0 处存在不可计算的区域,结果可能不理想。
使用示例
结合仓库自带的 docstring 示例(AntiderivativeExample),一个可直接运行的场景如下:
from manim import Scene, Axes, RED, BLUE class AntiderivativeExample(Scene): def construct(self): ax = Axes() graph1 = ax.plot( lambda x: (x**2 - 2) / 3, color=RED, ) graph2 = ax.plot_antiderivative_graph(graph1, color=BLUE) self.add(ax, graph1, graph2)该方法与同文件中的plot_derivative_graph(coordinate_systems.py#L1505,基于slope_of_tangent计算切线斜率)互为补足,使 Manim 的微积分可视化能力更加完整——导数与反导数可以在同一坐标系中直接对照展示。
破坏性变更:截至 v0.12.0 的弃用项被正式移除
PR #2331 一次性移除了截至 v0.12.0 的所有已弃用接口。升级到 v0.13.0 前,请务必检查你的脚本是否用到了以下 API:
| 已移除项 | 所属类/模块 | 替代方案 |
|---|---|---|
distance参数 | ThreeDCamera | 改用focal_distance |
min_distance_to_new_point参数 | TracedPath | — |
positive_space_ratio、dash_spacing参数 | DashedVMobject | — |
<method>_in_place系列方法 | mobject模块 | 使用非 in-place 版本 + 显式赋值 |
ReconfigurableScene | — | — |
SampleSpaceScene | — | — |
其中ThreeDCamera的focal_distance在当前源码中已作为核心属性落地:见 three_d_camera.py#L42(构造参数默认值20.0)及配套的get_focal_distance/set_focal_distance方法(L187-L246),它由ValueTracker驱动,支持动画化调节相机的焦距。
此外,PR #2312 将代码库中所有set_submobjects的调用替换为更明确的子对象设置方式,这也属于面向新老 API 的统一重构,脚本中如依赖该方法将不再可用。
增强:文档工具、树布局与表格 API
v0.13.0 的 Enhancements 部分包含如下值得关注的能力增强:
- PR #2347:将
manim_directive.py迁移至manim.utils.docbuild包。这正是当前仓库中 manim/utils/docbuild/manim_directive.py 的由来,它负责文档构建时执行并嵌入.. manim::指令对应的动画示例; - PR #2340:为
animation.growing模块补齐文档,并改进SpinInFromNothing动画; - PR #2343:用 SageMath 的树布局算法替换原有算法,改善大树结构的排版质量(影响 manim/mobject/graph.py 中的树形图布局);
- PR #2351:为
Table.add_highlighted_cell补充缺失的**kwargs透传参数,使其能像Table.get_cell(table.py#L788)一样自定义高亮单元格的样式——当前实现见 table.py#L884; - PR #2344:调整 SVG Logo 尺寸,使其内容贴合画布。
缺陷修复:从相机、渲染到表格的全面修整
v0.13.0 修复了一批影响实际创作体验的问题:
- PR #2359:修复调用
manim cfg write时抛出ValueError的问题,保障配置写入命令可用; - PR #2276:修复
ThreeDAxes中z 轴对齐的 bug; - PR #2325:多处改进对
quality参数的处理逻辑,使画质参数在不同命令路径下表现一致; - PR #2335:修复相机缩放(zooming)与
PointCloud结合时的异常; - PR #2328:修复向 Cairo 传递错误的 RGBA 值的问题,避免颜色渲染偏差;
- PR #2292:修复
Flash指示动画的定位问题; - PR #2262:修复
Table.get_cell在缩放(scaling)之后返回错误单元格坐标的问题; - PR #2280:修复
DecimalNumber在显示位数变化时颜色出错的问题。
对于表格用户,PR #2262 尤其关键:它保证了「先缩放表格、再按坐标取单元格」这一常见操作流程的坐标正确性。
文档、测试体系与代码质量改进
文档相关改动
本版本的文档工作相当活跃,包括:
- PR #2354:将
mobject.py与vectorized_mobject.py的文档和类型标注同步移植到其 OpenGL 对应实现(opengl_mobject.py、opengl_vectorized_mobject.py); - PR #2350:在文档中提及 Manim Sideview 的 VS Code 扩展;
- PR #2342:移除
Axes示例中对CoordinateSystem.get_graph的过时用法; - PR #2216:重写并扩充 quickstart 教程章节;
- PR #2279:为不连续函数补充文档(与
ParametricFunction的discontinuities参数相关); - PR #2319:修正
Mobject.interpolate示例中dotL与dotR的书写顺序; - PR #2310:明确说明 Manim 当时尚不支持 Python 3.10;
- PR #2294:精简文档首页并重排教程顺序;
- PR #2287:替换指向旧交互式笔记本的失效链接。
测试体系变化
- PR #2346:将帧测试装饰器
frames_comparison正式化为库的独立模块——即当前 manim/utils/testing/frames_comparison.py; - PR #2318:新增
AnimationGroup的remover关键字参数测试; - PR #2301:新增
ThreeDScene.add_fixed_in_frame_mobjects的测试; - PR #2274:优化部分测试以缩短运行时长;
- PR #2272:新增
Broadcast动画的测试。
代码质量与重构
- PR #2327:修正
Graph的labels关键字参数类型标注; - PR #2329:移除 README 中意外的换行;
- PR #2305:修正
ParametricFunction的discontinuities参数类型标注; - PR #2300:为 PyPI 添加联系邮箱。
升级到 v0.13.0 的实践建议
综合上述变更,从旧版本升级到 v0.13.0 时建议按以下顺序自查:
- 搜索已移除 API:在项目中全局搜索
distance=(ThreeDCamera 场景)、min_distance_to_new_point、positive_space_ratio、dash_spacing、*_in_place、set_submobjects、ReconfigurableScene、SampleSpaceScene,逐一替换为变更日志中给出的替代方案(如focal_distance); - 尝鲜新字幕能力:若你的动画需要对外发布带字幕的版本,可直接在
Scene.construct中使用self.add_subcaption(...)或self.play(..., subcaption=...),渲染后在同一输出目录检查生成的.srt文件; - 升级微积分可视化:用
plot_antiderivative_graph与plot_derivative_graph配对展示原函数、导数与反导数的关系,注意samples与y_intercept参数对曲线形态的影响; - 关注测试回归:本版本针对表格缩放、字幕写入、
quality参数等新增了大量测试,升级后建议运行pytest tests/验证环境一致性。
总体而言,v0.13.0 是一次「功能与清理并重」的版本:副字幕 API 为发布流程补齐了关键一环,反导数绘图扩展了数学可视化的表现力,而集中移除的弃用接口则意味着社区对 API 稳定性的承诺开始兑现。对于想要深入研读源码的读者,建议从 Scene.add_subcaption 与 plot_antiderivative_graph 两处入口出发,沿「场景 → 管理器 → 文件写入器」与「坐标系统 → 数值积分」两条调用链精读,即可全面掌握 v0.13.0 引入的核心机制。
【免费下载链接】manimA community-maintained Python framework for creating mathematical animations.项目地址: https://gitcode.com/GitHub_Trending/man/manim
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考