1. Введение: Зачем вообще кодить видео?

Если вы хоть раз видели ролики на YouTube-канале 3Blue1Brown, вы знаете этот стиль: плавные трансформации фигур, «живые» формулы и графики, которые строятся сами собой. Многие думают, что это результат адского ручного труда моушн-дизайнера. На самом деле — это чистый Python.

Библиотека называется Manim. И давайте сразу определимся: если вам нужно смонтировать влог из отпуска, закрывайте статью, Manim вам не нужен. Но если вы хотите визуализировать структуры данных, алгоритмы или физмат-модели, классические видеоредакторы (After Effects, Premiere) становятся проблемой.

Попытка построить динамический график функции или анимировать сортировку массива мышкой — это часы возни с кейфреймами (keyframe) и ручным выравниванием. Любая правка в логике заставляет переделывать всё с нуля.

Manim предлагает другой подход — Programmatic Animation:

  1. Абсолютная точность: Всё описывается математически. Если нужен сдвиг на вектор (2, 0, 0), он будет идеальным.

  2. Реюзабельность: Видео — это код. Его можно закоммитить в Git, отрефакторить и использовать куски в других проектах.

  3. Массовость: Нужно изменить цвет тысячи объектов? Вы меняете одну переменную в цикле for, а не кликаете по каждому объекту на таймлайне.

По сути, мы меняем монтажный стол на IDE. Для тех, кому проще написать скрипт, чем двигать ползунки, это глоток свежего воздуха.

2. Подготовка почвы: Manim Community vs ManimGL

Прежде чем писать pip install, нужно прояснить момент, на котором спотыкаются 90% новичков. Существует две основные версии библиотеки, и они несовместимы между собой.

  1. ManimGL (manimlib): Оригинальная версия от Гранта Сандерсона (автора 3Blue1Brown). Работает на OpenGL.

    • Плюсы: Очень быстрый рендеринг (GPU), возможность интерактива в реальном времени.

    • Минусы: Написана «под себя», слабая документация, нестабильна, сложно настраивается на Windows.

  2. Manim Community (manim): Форк, поддерживаемый сообществом разработчиков.

    • Плюсы: Стабильные ежемесячные релизы, отличная документация, кроссплатформенность, плагины.

    • Минусы: Рендерится на CPU (Cairo), поэтому медленнее на сложных сценах.

Вердикт: Для работы используем Manim Community. Это стандарт де-факто для всех, кто не является Грантом Сандерсоном. В статье мы работаем именно с ней.

Зависимости (System Dependencies)

Manim — это не просто Python-пакет, это обертка над системными инструментами. Без них магии не будет:

  1. FFmpeg: Критически важен. Python генерирует кадры (картинки), а FFmpeg склеивает их в MP4. Он должен быть установлен в системе и прописан в переменных среды (PATH).

  2. LaTeX: Нужен для рендеринга красивых математических формул. Если у вас в системе нет TeX-дистрибутива, Manim будет падать при попытке создать объект MathTex.

Установка

Когда системные зависимости на месте, ставим саму библиотеку. Обратите внимание на имя пакета:

# Ставит Community версию (то, что нам нужно)
pip install manim

# НЕ перепутайте с manimlib (это версия 3b1b)
# pip install manimlib — ЭТО НАМ НЕ НУЖНО

Проверяем, что всё взлетело:

manim --version

Если видите номер версии (например, Manim Community v0.19.1), окружение готово.

3. Анатомия сцены: Hello World

В Manim единица контента — это класс, наследуемый от Scene. Внутри него есть метод construct(), который работает как main() в C-подобных языках. Всё, что написано внутри construct, будет выполнено и отрендерено.

Минимально рабочий скрипт выглядит так (сохраните как scene.py):

from manim import *

class HelloWorld(Scene):
    def construct(self):
        # 1. Создаем Mobject (Mathematical Object)
        box = Square()
        box.set_fill(BLUE, opacity=0.5) # Настройка свойств

        # 2. Добавляем объект на сцену
        self.add(box)

Разбор ключевых компонентов:

  1. from manim import *: Обычно import * — это дурной тон (PEP8 не одобряет), но в контексте Manim это стандарт. Библиотека экспортирует сотни классов (цвета, фигуры, константы), и импортировать их поштучно — мучение.

  2. Mobject (Mathematical Object): Базовый класс для всего, что отображается на экране. Геометрия (Circle, Line), текст (Text, Tex), графики — всё это наследники Mobject.

  3. Координатная система: Центр экрана — это (0, 0, 0).

    • Высота кадра по умолчанию: 8 единиц (от -4 до +4 по Y).

    • Ширина: завист от соотношения сторон (при 16:9 это ~14.22 единицы, от -7.11 до +7.11 по X).

    • Поэтому Square() без аргументов создается ровно в центре.

Позиционирование

Вместо того чтобы высчитывать координаты вручную (x=3.5, y=-2), в Manim принят относительный подход.

circle = Circle()
square = Square()

# Сдвиг относительно центра или текущей позиции
circle.shift(LEFT * 2)  # Сдвинуть влево на 2 единицы
square.next_to(circle, RIGHT, buff=0.5) # Поставить справа от круга с отступом 0.5

Запуск рендера

Чтобы превратить этот код в видео (или картинку), идем в терминал:

manim -pql scene.py HelloWorld
  • -p (preview): автоматически открыть файл после рендера.

  • -q (quality): флаг качества. l — low (480p, быстро), h — high (1080p), k — 4k.

  • scene.py: имя файла.

  • HelloWorld: имя класса сцены.

Результатом выполнения кода выше будет статичная картинка с синим квадратом. Чтобы он задвигался, нам нужны анимации, о которых в следующем пункте.

4. Основы магии: Анимация и Трансформация

Если self.add() просто шлепает объект на кадр, то метод self.play() запускает генерацию кадров видео. Именно он отвечает за интерполяцию состояний от начала до конца действия.

Базовая логика

В метод play передается экземпляр анимации. Библиотека блокирует выполнение скрипта на время этой анимации (по умолчанию 1 секунда), рендерит нужное количество кадров и переходит к следующей строчке.

    def construct(self):
        square = Square()
        
        # Рисует контуры квадрата (Create — самая частая анимация появления)
        self.play(Create(square)) 
        
        # Пауза на 1 секунду. ВАЖНО: time.sleep() здесь не работает!
        # self.wait() генерирует статические кадры.
        self.wait(1.0)

Трансформации (The Killer Feature)

То, ради чего используют Manim — это Transform. Библиотека берет векторные точки первого объекта и плавно перемещает их в координаты точек второго объекта.

Это позволяет делать морфинг чего угодно во что угодно: буквы в цифру, квадрата в звезду, графика в прямую линию.

        circle = Circle()
        circle.set_fill(PINK, opacity=0.5)

        # Квадрат плавно превращается в Круг
        self.play(Transform(square, circle))

Важный нюанс архитектуры:
Метод Transform(A, B) модифицирует объект A, заставляя его выглядеть как B. Объект B при этом на сцену не добавляется, он служит лишь целевым шаблоном.
Если вам нужно, чтобы в итоге на сцене остался именно объект B (например, чтобы потом работать с его методами), используйте ReplacementTransform(A, B).

Синтаксис .animate

Для простых изменений свойств (сдвинуть, перекрасить, повернуть) не обязательно создавать целевой объект вручную. У каждого Mobject есть свойство .animate.

        # Вместо создания нового квадрата в другом месте:
        # self.play(square.animate.shift(RIGHT * 3).rotate(PI/4))
        
        # Также можно управлять скоростью через run_time
        self.play(
            square.animate.set_color(RED), 
            run_time=2.0
        )

Итоговый пайплайн анимации:

  1. Creation: Появление (Create, FadeIn, Write, DrawBorderThenFill).

  2. Mutation: Изменение (Transform, .animate).

  3. Destruction: Исчезновение (Uncreate, FadeOut, ShrinkToCenter).

Всё это комбинируется последовательно или параллельно (через запятую внутри одного play), давая полный контроль над таймингом видео.

5. Главная фишка: LaTeX и Формулы

Если вы пробовали вставить красивое уравнение в Adobe Premiere или DaVinci Resolve, вы знаете эту боль: нужно идти в онлайн-редактор LaTeX, генерировать PNG с прозрачным фоном, скачивать, вставлять на таймлайн. Если нашли ошибку в формуле — повторяем цикл заново.

Manim был рожден математиком для математики, поэтому поддержка LaTeX здесь нативная.

Как это работает

Вы пишете строку в синтаксисе TeX, Manim под капотом стучится в системный дистрибутив, генерирует SVG-вектор и превращает его в набор кривых Безье. Для нас это значит одно: формула — это не картинка, это геометрия. Её можно гнуть, перекрашивать по частям и трансформировать.

Используем класс MathTex:

        # Обязательно используйте r-строки (raw strings), 
        # иначе Python сойдет с ума от количества бэкслешей
        equation = MathTex(
            r"e^{i\pi} + 1 = 0",
            font_size=96
        )
        self.play(Write(equation))

разделения (Substrings)

Самая мощная фича — доступ к отдельным символам формулы. Поскольку Manim видит формулу как массив векторных контуров, вы можете обратиться к конкретному символу по индексу, как в списке Python.

Но высчитывать индекс символа «x» в длинном уравнении неудобно. Лучшая практика — разбивать формулу на части при создании:

        # Передаем части формулы отдельными строками
        eq = MathTex("a^2", "+", "b^2", "=", "c^2")
        
        # Теперь eq — это VGroup (группа векторов) из 5 элементов.
        # Мы можем обращаться к ним по отдельности:
        
        # Перекрасим "a^2" в синий
        eq[0].set_color(BLUE)
        # Перекрасим "b^2" в желтый
        eq[2].set_color(YELLOW)
        
        self.play(Write(eq))
        
        # Анимация акцента: масштабируем "c^2"
        self.play(
            eq[4].animate.scale(1.5).set_color(RED)
        )

TransformMatchingTex

Для создания тех самых видео, где одна формула перетекает в другую с сохранением общих символов (например, сокращение дроби, где одинаковые x перелетают и исчезают), используется TransformMatchingTex.

Это работает почти автоматически: Manim анализирует исходный и целевой TeX-код, находит одинаковые куски и плавно перемещает их на новые места, а всё, что не совпало — фейдит. Это выглядит профессионально, а пишется в две строчки.

6. Практический кейс: Визуализация графика и ValueTracker

Двигать квадратики — это весело, но давайте сделаем что-то полезное для Data Science или физики. Построим график функции (синусоиды) и пустим по нему точку, которая будет бежать в реальном времени и показывать свои текущие координаты.

Здесь нам понадобятся три важные концепции:

  1. Axes: Система координат. Manim умеет сам рисовать оси, расставлять засечки и цифры.

  2. c2p (Coordinates to Point): Метод, который переводит математические координаты (x=2, y=5) в пиксельные координаты на экране.

  3. ValueTracker: Это невидимый объект, который хранит число. Мы анимируем изменение этого числа, а все остальные объекты (точка, текст) «слушают» его и обновляются автоматически.

Задача

Нарисовать синусоиду и заставить точку пробежать по ней от x = -3 до x = 3, отображая значение y над собой.

Код примера (сохраните как graph_scene.py):

from manim import *
import numpy as np

class PlottingStats(Scene):
    def construct(self):
        # 1. Настраиваем оси
        # x_range=[min, max, step]
        axes = Axes(
            x_range=[-4, 4, 1],
            y_range=[-1.5, 1.5, 0.5],
            x_length=8, 
            y_length=5,
            axis_config={"color": GREY},
            tips=False # Убрать стрелочки на концах осей
        ).add_coordinates() 

        # 2. Строим график
        # axes.plot принимает лямбда-функцию
        sin_curve = axes.plot(lambda x: np.sin(x), color=BLUE)
        
        sin_label = MathTex("y = \\sin(x)").next_to(sin_curve, UP + RIGHT)

        # 3. Магия ValueTracker
        # Создаем "хранилище" значения X. Стартуем с -3
        t = ValueTracker(-3)

        # 4. Создаем точку, которая зависит от t
        # always_redraw пересоздает объект каждый кадр
        dot = always_redraw(lambda: Dot(
            # c2p берет (x, y) и возвращает координаты на экране
            point=axes.c2p(t.get_value(), np.sin(t.get_value())),
            color=RED
        ))

        # 5. Динамический текст (показания Y)
        # ИСПРАВЛЕНИЕ: Используем параметр number (или позиционный аргумент), 
        # параметра num в DecimalNumber нет.
        number_label = always_redraw(lambda: DecimalNumber(
            number=np.sin(t.get_value()), 
            num_decimal_places=2,
            color=RED
        ).next_to(dot, UP))

        self.play(Create(axes), Create(sin_curve), Write(sin_label))
        self.add(dot, number_label) 

        # 6. Запуск анимации
        # Мы анимируем ТОЛЬКО ValueTracker.
        # Точка и цифра обновятся сами благодаря always_redraw.
        self.play(
            t.animate.set_value(3), 
            run_time=4,
            rate_func=linear 
        )
        
        self.wait()

Разбор механики

Ключевая строка здесь: dot = always_redraw(lambda: ... ).
Функция always_redraw говорит Manim: "Вызывай эту лямбду перед отрисовкой каждого кадра видео".

  1. Каждый кадр Manim смотрит на текущее значение t (которое плавно меняется от -3 до 3).

  2. Вычисляет новый np.sin(t).

  3. Строит новую точку и обновляет цифру в DecimalNumber.

Без этой техники вам пришлось бы вручную рассчитывать тысячи координат. С ValueTracker вы управляете одной переменной, а вся сцена реагирует на её изменение.

7. Тонкости рендеринга и CLI

Код написан, но результат пока существует только в вашей голове. Чтобы превратить его в пиксели, нужно освоить командную строку (CLI). Manim имеет богатую систему флагов, которые определяют разрешение, фреймрейт и формат.

Базовая команда выглядит так:
manim [флаги] [имя_файла.py] [ИмяКлассаСцены]

Управление качеством (-q)

Самая частая ошибка новичка — пытаться рендерить сразу в высоком качестве. Manim работает на CPU (по большей части), и рендер 60 fps в 4K может занять минуты даже для простой сцены.

Используйте флаг -q (quality) с одной из букв:

  • -ql (Low): 480p, 15 fps. Используйте для разработки. Рендерится мгновенно, позволяет быстро оценить анимацию.

  • -qm (Medium): 720p, 30 fps. Хороший компромисс для черновиков.

  • -qh (High): 1080p, 60 fps. Стандарт для YouTube. Ставьте только когда код полностью отлажен.

  • -qk (4K): 2160p, 60 fps. Для перфекционистов.

Полезные флаги

  1. -p (Preview): После рендера сразу открывает видео в плеере по умолчанию. Без этого флага вам придется каждый раз лезть в папку media/videos/....

  2. -t (Transparent): Рендерит видео с альфа-каналом (прозрачным фоном). Критически важно, если вы делаете анимацию для наложения поверх живого видео в Premiere или DaVinci. Формат файла будет .mov (ProRes).

  3. --format gif: Сохраняет результат не в MP4, а в GIF. Удобно для статей на Хабр или GitHub Readme.

Конфигурация (manim.cfg)

Чтобы не писать каждый раз manim -pqh --disable_caching ..., можно создать в папке с проектом файл manim.cfg. Библиотека подхватит настройки автоматически.

Пример конфига:

[CLI]
frame_rate = 60
pixel_height = 1080
pixel_width = 1920
background_color = BLACK
background_opacity = 1
scene_names = DefaultScene

Почему так долго?

Если рендер зависает на этапе Latex error или просто долго думает перед началом:

  1. LaTeX: Каждая формула компилируется через системный TeX. Это медленная операция, но Manim кэширует результаты. Второй запуск будет быстрее.

  2. Кэш: Manim сохраняет промежуточные анимации. Если вы поменяли цвет одного круга в конце сцены, он не будет пересчитывать начало. Но иногда кэш ломается. Если видите странные глитчи — удалите папку media/ и пересоберите проект.

Итоговая рекомендация:
Пишите код с флагом -pql.
Финальный билд делайте с -pqh.
Для интеграции с монтажом используйте -t.

8. Заключение и «Куда копать дальше»

Manim — это не «убийца» After Effects. Пытаться монтировать в нем блог или клип — изощренная форма мазохизма. Но как только задача касается точной геометрии, математических абстракций или алгоритмов, Manim перестает быть просто библиотекой и становится супероружием.

Вам больше не нужно выравнивать пиксели мышкой. Вы описываете логику поведения, а рендеринг — это просто побочный эффект выполнения кода. Это дает вам:

  1. Контроль версий: Ваше видео лежит в Git. Вы можете сделать ветку, поэкспериментировать с цветами и откатиться назад.

  2. Масштабируемость: Написать скрипт для сортировки 10 элементов так же сложно, как для 1000.

  3. Переиспользование: Создав однажды красивую визуализацию нейросети, вы будете использовать этот класс во всех будущих презентациях.

Что мы не затронули (но стоит изучить)

В рамках одной статьи невозможно охватить всё. Вот ключевые темы для самостоятельного изучения:

  • 3D Scenes (ThreeDScene): Вращение камеры, оси Z, поверхности. Выглядит эффектно, но требует хорошего пространственного мышления.

  • Graph Theory: В Manim встроен мощный движок для отрисовки графов и деревьев (Dijkstra, BFS/DFS визуализируются на раз-два).

  • Звук: Методы self.add_sound() для синхронизации аудиодорожки с анимацией.

Анонсы новых статей, полезные материалы, а так же если в процессе у вас возникнут сложности, обсудить их или задать вопрос по этой статье можно в моём Telegram-сообществе. Смело заходите, если что-то пойдет не так, — постараемся разобраться вместе.

Полезные ссылки

  1. Документация Manim Community: Она отлично структурирована и полна примеров.

Комментарии (1)


  1. griha_shershen
    19.01.2026 02:54

    Статья прям очевидно нейронка, но это точно нельзя назвать слопом. Либо автор сам шарит, либо просто постарался, но мне понравилось, давно заглядывался на маним, но никак руки не доходили, сам бы нейронку не спросил, а так для общего ознакомления пойдёт