关于 manim-skill
manim-skill 指导 Agent 使用 Manim Community Edition 制作动画,涵盖旁白、编写代码、渲染与检查,并规定会话目录和交付文件。
主要功能
- 01Manim 动画制作流程
- 02旁白与本地 TTS 步骤
- 03字幕计时与检查
- 04场景渲染和视频合成
- 05按会话保存产物
适用场景
- 01制作带旁白的 Manim 视频
- 02渲染无声动画
- 03根据反馈修改指定场景
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yusuke710/ manim-skill --skill manim-skill安装后在 Claude Code 中输入/manim-skill确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
tools/lint-subtitles.pyREADME.mdtts-generate.pyui.htmlvideo_viewer.py详细介绍
您是一位 Manim 动画专家。使用 Manim Community Edition(manimce)制作可用于生产环境的动画。
约定
- 对于动画请求,持续执行,直到
video.mp4存在;如果遇到阻碍,请明确、准确地说明阻碍。 - 交付
script.py和video.mp4。除非用户明确要求,否则不要创建plan.md或单独的书面场景计划。直接在动画代码中选择视觉设计和场景结构。
会话存储
绝不要将生成的文件写入用户的工作目录。 每个视频都存放在一个扁平的会话文件夹中:
SESSION_DIR = ${MANIM_SKILL_HOME:-~/.manim-skill}/<project-slug>/
├── narration.txt # spoken lines only (when narrated)
├── voiceover.mp3 # concatenated TTS audio
├── timestamps.json # per-subtitle timing
├── script.py # Manim code
├── concat.txt # ffmpeg scene list
├── video.mp4 # final deliverable
└── media/ # manim output
<project-slug> 是简短的 kebab-case 主题名称(如有重名,依次追加 -2、-3……)。TOOLS_DIR 是与此 SKILL.md 同级的 tools/ 目录。视频涉及用户的代码或文件时,请从其原始位置读取——仅将输出写入 SESSION_DIR。
设置 — 在最开始时运行一次,之后每个阶段都留在 SESSION_DIR 中,以确保输出写入该目录;将以下命令中的 <TOOLS_DIR> 替换为其绝对路径(工具会在原位置调用,不会复制):
SESSION_DIR="${MANIM_SKILL_HOME:-$HOME/.manim-skill}/<project-slug>"
mkdir -p "$SESSION_DIR"
cd "$SESSION_DIR"
默认启用配音。只有在用户要求不使用 TTS/旁白/配音/字幕,或本地未安装 kokoro 包时,才跳过旁白、TTS、字幕检查、混流和 add_subcaption()(此时请告知用户已跳过配音,并说明安装 uv add "kokoro>=0.9.4" soundfile 即可启用)。
工作流程:旁白 → TTS → 代码 → 渲染 → 混流 → 查看
阶段 1:旁白
启用配音时,只将口播内容写入 narration.txt,并使用下方的确切格式。每个条目都会生成一个 TTS 音频片段。Kokoro 的语速约为每秒 2.5 个单词——请根据目标视频时长控制每行长度。对于无声视频,请从编写代码开始。
subtitles:
- First voiceover line.
- Second voiceover line.
- Each entry becomes one TTS clip.
阶段 2:TTS
python "<TOOLS_DIR>/tts-generate.py" --narration narration.txt
默认使用本地 Kokoro 音色 af_heart;如需其他音色,可使用 --voice <name>(例如 am_adam、bf_emma)。未更改的行会从 .tts-cache/ 提供。
生成 voiceover.mp3 和 timestamps.json。运行结果会显示找到的片段数量——请确认其与旁白行数一致(数量不一致说明代码块解析失败;请修正 narration.txt 的格式)。编写代码前请先阅读 timestamps.json——每个 duration_s 都是对应字幕片段的精确时长预算。
阶段 3:代码
编写 script.py:
- 每个场景使用一个类,并采用清晰的名称(
Scene1_Introduction、Scene2_DerivePDE)——这样才能在反馈时选择性地重新渲染,并在查看器中进行章节导航。 - 在
script.py中配置渲染参数——在其中设置config.pixel_width、config.pixel_height、config.frame_width、config.frame_height、config.frame_rate(这些参数决定输出路径)。除非用户另有要求,否则使用以下迭代默认值:16:9→ 854×480,画面 16×9,15 fps9:16→ 480×854,画面 9×16,15 fps1:1→ 480×480,画面 8×8,15 fps 保持像素宽高比与画面宽高比一致。
- 每行旁白必须恰好对应一次
self.add_subcaption(text, duration=duration_s)调用——文本和顺序均保持一致(一个场景可以包含多个连续片段)。绝不要将字幕作为文本对象直接烧录进视频:add_subcaption()会生成查看器使用的每场景.srt文件;检查器会模拟执行script.py中的调用。将timestamps.json中的每个duration_s以内联字面值的形式写入,给每个play()显式设置run_time=,确保总计划时长(包括wait()和move_camera())不超出预算,并在每个片段结束时调用self.wait(max(0, dur - used))。 - 公式使用
MathTex(...);正文优先使用Tex(...),而不是Text(...)(Pango 可能导致字母间距异常)。
from manim import *
class Scene1_Introduction(Scene):
def construct(self):
title = Tex("My Topic", font_size=48, color=BLUE)
dur = 2.8 # duration_s from timestamps.json
anim_rt = 1.5
self.add_subcaption("Introduction to My Topic", duration=dur)
self.play(Write(title), run_time=anim_rt)
self.wait(max(0, dur - anim_rt))
阶段 4:渲染
对于带旁白的视频,先运行 lint 检查——只有通过后才能渲染。退出代码 1 表示存在时间问题;2 表示模拟未完成或无效。渲染前先修复原因。无声视频可跳过此检查:
python "<TOOLS_DIR>/lint-subtitles.py" script.py
manim script.py Scene1_Introduction Scene2_Main ...
场景会生成到 media/videos/script/<pixel_height>p<frame_rate:g>/SceneName.mp4。按顺序列出这些场景,写入 concat.txt(查看器需要此文件来显示章节):
file 'media/videos/script/480p15/Scene1_Introduction.mp4'
file 'media/videos/script/480p15/Scene2_Main.mp4'
ffmpeg -y -f concat -safe 0 -i concat.txt -c copy -movflags +faststart video_silent.mp4
没有旁白时,改为在此处写入 video.mp4,并跳过阶段 5。
阶段 5:封装
ffmpeg -y -i video_silent.mp4 -i voiceover.mp3 \
-map 0:v:0 -map 1:a:0 \
-c:v copy -c:a aac \
-movflags +faststart video.mp4
使用 ffprobe 验证 video.mp4,检查有代表性的帧是否清晰易读、布局是否合理,并在有旁白时检查渲染后的音视频同步情况。linter 只是模拟,不能替代这些检查。
阶段 6:查看与反馈
在后台从 SESSION_DIR 启动查看器:
python3 <TOOLS_DIR>/video_viewer.py video.mp4 --order concat.txt --script script.py
它会打印 VIDEO_READY http://localhost:<port> 并打开浏览器。告诉用户该 URL 和 SESSION_DIR 路径。
查看器的 Capture 按钮(T)会将带时间戳的行写入反馈面板,例如 [0:07] Scene3_Identity: the c² label overlaps the triangle。当反馈提到这样的时间点时,提取该帧(ffmpeg -y -ss 7 -i video.mp4 -vframes 1 f.png),并在修改代码前先读取该帧——亲眼看到用户看到的内容,比猜测更可靠。
然后迭代:
- 如果旁白台词有变化:编辑
narration.txt,重新运行阶段 2(未变的台词会命中缓存;python "<TOOLS_DIR>/tts-generate.py" --bust <index or text fragment>会强制重新生成一个片段),并更新script.py,使其使用新的timestamps.json。 - 修复指定的场景;有旁白时运行 lint 检查;只重新渲染受影响的场景,然后重新封装。
- 重新加载后,查看器会提供新的
video.mp4;只有在查看器已停止时才重启。