Skip to main content
Glama
Tarunls
by Tarunls

manim-storyboard

Увидьте каждую анимацию в сцене Manim в виде одной подписанной контактной таблицы и сверьте её с вашим раскадровщиком.

Контактная таблица с намерениями

Первые 18 шагов 97-шаговой сцены. Голубым показано, что отрендерилось, янтарным — что должно было произойти по вашему замыслу.

Зачем

Manim сообщает, что сцена отрендерена. Он не говорит, что заголовок главы вылез за правый край или что баннер приземлился поверх текста под ним. Это видно только при просмотре, а просмотр означает пролистывание mp4 или угадывание временных меток для извлечения кадров.

Угадывание тратит много сэмплов. Затухание между двумя разделами — это чёрный кадр, и примерно четверть наугад выбранных временных меток попадают в такой.

Есть лучший источник. Manim записывает один клип на каждый вызов self.play() в partial_movie_files/ и перечисляет их по порядку. Возьмите последний кадр каждого — и получите один устоявшийся кадр на каждую анимацию, по порядку, без потерь. В этом и заключается вся идея.

Related MCP server: blockout-mcp

Установка

pip install manim-storyboard

Требуется ffmpeg в PATH, или переменные FFMPEG_EXECUTABLE и FFPROBE_EXECUTABLE, указывающие на бинарные файлы. Это то же соглашение, что используется в manim-mcp-server, поэтому существующая настройка уже подойдёт.

Использование

Одна таблица для целой сцены:

manim-storyboard sheet scene.py MyScene
97 panels -> storyboard_MyScene.png

Каждая панель содержит индекс, время начала в финальном видео, длительность и классы анимаций, которые на самом деле выполнялись:

#012   0:08.5   1.33s
LaggedStart[Write, FadeIn x2]

Группы раскрываются на один уровень, чтобы вы могли видеть, что внутри LaggedStart, не открывая файл. self.wait() получает собственную панель, потому что manim рендерит его как отдельный клип.

Страница для больших сцен:

manim-storyboard sheet scene.py MyScene --range 1-40 --columns 6

Если уже отрендерили через CLI manim и нужна только таблица:

manim-storyboard sheet scene.py --from-media media/videos/scene/480p15/partial_movie_files/MyScene

Попробуйте

В папке examples/ есть небольшая сцена без LaTeX и без ресурсов, а также готовая раскадровка для неё:

manim-storyboard sheet examples/demo_scene.py DemoScene -s examples/storyboard.yaml
manim-storyboard check examples/demo_scene.py DemoScene -s examples/storyboard.yaml

Демонстрационная контактная таблица

Раскадровка

Раскадровка — это YAML-файл, описывающий, что должен делать каждый шаг. Напишите его вручную до того, как сцена существует, или создайте каркас на основе рендера:

manim-storyboard plan scene.py MyScene            # scaffold from what rendered
manim-storyboard plan scene.py MyScene --blank 40 # 40 empty steps to fill in
scene: LarpGuide
steps:
  - at: 1
    section: cold open
    intent: the overheard question fades up on an empty frame
    expect: [FadeIn]
  - at: 7
    intent: the title writes on, RENT-A-GIRLFRIEND FAN
    expect: [Write]
  - at: 9
    intent: pink flash pops on the word FAN
    expect: [Flash]
  - at: 11
    intent: clear everything before chapter one
    expect: [FadeOut]

intent — это текст для вас. expect — это тип анимации, который вы намерены использовать на этом шаге, и именно он проверяется:

manim-storyboard check scene.py MyScene -s storyboard.yaml
step 7: [drift] expected FadeIn but rendered Write
step 9: [drift] expected Circumscribe but rendered Flash
step 400: [missing] plan has step 400 but the render stopped at 97

Передайте раскадровку обратно в sheet — и каждая панель получит напечатанное под ней намерение, а шаги, которые отклонились, будут обведены красным:

manim-storyboard sheet scene.py MyScene -s storyboard.yaml

Полезные правила

Подсчёт опционален. expect: [FadeOut] означает «на этом шаге объекты исчезают» и подходит для любого их количества. Вспомогательный метод, очищающий сцену, скрывает столько объектов, сколько на ней есть, и вам не придётся обновлять план каждый раз при добавлении одного. Когда точное количество важно, пишите expect: [FadeOut x6] — тогда сравнение становится строгим и чувствительным к порядку.

Частичные планы допустимы. Проверяются только шаги, объявляющие expect. План может охватывать начало и ничего не говорить об остальном. Используйте флаг --strict, чтобы также отмечать отрендеренные шаги, которые план вообще не упоминает.

Планы только с текстом никогда не приводят к ошибке. Шаги с intent и без expect — это подписи для таблицы, а не утверждения.

Содержимое групп игнорируется. expect: [LaggedStart] выполняется при наличии LaggedStart[Write, FadeIn x2]. Сопоставляйте обёртку, а не её дочерние элементы.

MCP

Те же три инструмента через MCP, чтобы агент, пишущий Manim, мог видеть свой собственный вывод:

pip install "manim-storyboard[mcp]"
python -m manim_storyboard.mcp_server
{
  "mcpServers": {
    "manim-storyboard": {
      "command": "python",
      "args": ["-m", "manim_storyboard.mcp_server"],
      "env": {
        "FFMPEG_EXECUTABLE": "C:\\ffmpeg\\bin\\ffmpeg.exe",
        "FFPROBE_EXECUTABLE": "C:\\ffmpeg\\bin\\ffprobe.exe"
      }
    }
  }
}

Предоставляет storyboard_sheet, storyboard_plan, storyboard_check и storyboard_from_media. Чтобы подключить их к уже запущенному MCP-серверу manim:

from manim_storyboard.mcp_server import register
register(my_fastmcp_instance)

Python

from pathlib import Path
from manim_storyboard import record, build, load, check

take = record(Path("scene.py"), "MyScene", quality="low_quality")
plan = load(Path("storyboard.yaml"))

for issue in check(plan, take.steps):
    print(issue.index, issue.kind, issue.message)

build(take.steps, Path("sheet.png"), columns=6, plan=plan)

record() обёртывает Scene.play на время одного рендера, чтобы манифест точно соответствовал клипам на диске. После этого он восстанавливает исходный метод, даже если рендер вызывает исключение.

Разработка

pip install -e ".[dev]"
pytest

Для тестов сопоставления планов не нужны ни manim, ни ffmpeg.

Лицензия

MIT

Related MCP Connectors

Related MCP Servers