egaki — генерация изображений и видео из терминала плюс MDX-фреймворк для видео на Remotion
📂 Исходный код на GitHubTypeScript-CLI для генерации изображений и видео из терминала. Поддержка Google Imagen, Gemini, GPT Image, Fal, xAI Grok, Veo, Kling, Bytedance Seedance. Встроенный MDX-to-video фреймворк на Remotion: заголовки MDX превращаются в секции, есть примитивы анимаций, easing-пресеты, layout transitions, captions, TTS и экспорт MP4 в браузере.
egaki (github.com/remorses/egaki, 144 звезды, 338 коммитов) — TypeScript-проект с двумя лицами. С одной стороны это CLI для генерации изображений и видео через Vercel AI SDK, с другой — MDX-to-video фреймворк на Remotion, который превращает обычный MDX-файл в MP4-ролик, собранный в браузере через WebCodecs. Один бинарник pnpm add -g egaki — и в терминале появляется швейцарский нож для медиа, а в проекте — фреймворк для «текстового монтажа».
Установка и быстрый старт
pnpm add -g egaki
egaki login
egaki image "a watercolor fox reading a map" -o fox.png
egaki video "a paper boat drifting on a calm lake at sunrise" -o boat.mp4
Альтернативный путь — зайти через ChatGPT-подписку и использовать Codex-бэкенд для OpenAI-моделей:
egaki login --provider chatgpt
egaki image "a dreamy studio ghibli style bakery at sunrise" -m gpt-image-1.5 -o bakery.png
CLI: что умеет
Изображения
# text-to-image
egaki image "cinematic mountain village at sunrise" -o village.png
# image edit
egaki image "add a red scarf and make it winter" --input portrait.jpg -o portrait-winter.png
# inpainting по маске
egaki image "replace the sky with dramatic storm clouds" --input landscape.png --mask mask.png -o storm.png
# пакетная генерация
egaki image "minimal logo concepts for a cat cafe" -n 4 -o logo.png
# контроль композиции
egaki image "cyberpunk alley at night" --aspect-ratio 16:9
egaki image "studio product shot of a ceramic mug" -m imagen-4.0-generate-001 --seed 42 -o mug.png
Поддерживаются --input (несколько раз), --mask, --seed, --aspect-ratio, --image-size, -n N для пакетов, --json для пайплайнов. Можно лить результат в stdout и дальше в ImageMagick или ffmpeg: egaki image "flat icon of a fox" --stdout | magick - -resize 512x512 fox-icon.png.
Видео
# text-to-video
egaki video "timelapse of a stormy sea, cinematic" -m veo-3.1-generate-001 --duration 8 -o storm.mp4
# image-to-video
egaki video "slowly animate the clouds" --input photo.jpg -m klingai/kling-v2.6-i2v -o animated.mp4
# дешёвая и быстрая модель
egaki video "a cat walking on a rooftop at night" -m klingai/kling-v2.5-turbo-t2v --duration 5 -o cat.mp4
# пакет
egaki video "waves crashing on cliffs at golden hour" -n 2 -o waves.mp4
Ключи: --duration, --resolution (480p–4K), --aspect-ratio, --input для i2v, --stdout для пайпов, -n для серий.
Аудио
CLI заходит далеко за пределы картинок и видео:
egaki demucs song.mp3 --stems vocals -o stems/ # разделение вокала и инструментов
egaki voice clone stems/vocals.mp3 --name "Singer" --json # клонирование голоса
egaki speech "Your text here." --voice <voice-id> -m sonic-3.5 -o output.mp3
egaki transcribe recording.mp3 -m whisper-1 # распознавание речи с word timestamps
egaki bpm soundtrack.mp3 --json # BPM локально, без API
egaki loudness narration.mp3 # LUFS по EBU R128
egaki bpm и egaki loudness — локальные, работают без сети и стоят копейки в ресурсах. node-web-audio-api ставится опционально.
Провайдеры и модели
egaki проксирует запросы к куче провайдеров через единый интерфейс. Вот сводная таблица из README:
| Тип | Модель | Зачем |
|---|---|---|
| image | imagen-4.0-ultra-generate-001 |
топ-качество, поддержка --seed и ratio |
| image | gemini-3.1-flash-image-preview |
быстро и дёшево, широкие ratio |
| image | nano-banana-pro-preview |
топ-фиделити от Google |
| image | gpt-image-1.5 |
OpenAI, сильные edit и inpainting |
| image | fal-ai/flux/schnell |
быстрые ideation-пакеты |
| video | veo-3.1-generate-001 |
топ, 4K, со звуком |
| video | klingai/kling-v2.5-turbo-t2v |
дёшево и быстро |
| video | bytedance/seedance-v1.5-pro |
три разрешения, звук |
| video | grok-imagine-video |
edit/extend/R2V от xAI |
Авторизация гибкая: BYOK для каждого провайдера (egaki login --provider google --key AIza...), ChatGPT-OAuth для Codex-бэкенда, xAI Grok Build OAuth (egaki login --provider xai-oauth), и собственная подписка egaki — один ключ egaki_... открывает все модели. Видео-списание идёт посекундно по формуле «модель × разрешение × длительность», остаток смотрится через egaki usage.
Discovery моделей
egaki models
egaki models --type video
egaki models --type image
egaki models --provider google
egaki models --json
egaki models --json удобно дёргать из пайплайнов: сразу видна цена за вызов/секунду, можно выбирать модель динамически.
MDX-to-video фреймворк
Вторая половина egaki — фреймворк для генеративного видео на стыке Remotion и MDX. Идея простая: пишешь MDX, заголовки первого уровня становятся секциями монтажа, выразительные примитивы — анимациями, экспорт идёт прямо в браузере без серверного рендера.
mkdir my-video && cd my-video
pnpm init
pnpm add egaki remotion @remotion/media react react-dom
video.mdx:
---
fps: 30
bpm: 120
---
# Intro duration=3s
<TranslateX from={-140} to={0} duration={0.5 * FPS}>
<div style={{ fontSize: 72, fontWeight: 900, color: 'white' }}>
Hello World
</div>
</TranslateX>
# Outro duration=2s
<Opacity from={1} to={0} duration={0.5 * FPS} startInFrames={-0.5 * FPS}>
<div style={{ fontSize: 48, color: 'white' }}>Goodbye</div>
</Opacity>
vite.config.ts:
import { defineConfig } from 'vite'
import { egakiPlugin } from 'egaki/vite'
export default defineConfig({
plugins: [egakiPlugin({ entry: './video.mdx' }],
})
pnpm dev — открывается плеер с таймлайном и кнопкой Export MP4. Экспорт идёт через @remotion/web-renderer и WebCodecs, то есть прямо в браузере, без ffmpeg-сервера.
Длительности и beat-sync
У длительности секции есть четыре формы записи: 3.5s, 8beats, 90frames, 90. FPS и BEAT — глобальные scope-переменные, которые можно использовать в выражениях MDX (duration={0.5 * FPS}, duration={8 * BEAT}). В frontmatter задаются fps и bpm, после чего весь монтаж можно подвязать к ритму:
egaki bpm music.mp3 --json
# { S0 : 129.2, S1 : 0.464 }
Дальше в video.mdx подставляешь bpm: 129.2, обрезаешь звук до первого даунбита через trimBefore={11} — и сцены режутся точно в бит. Чтобы ускорить пейсинг без потери бит-синка, увеличиваешь bpm и ставишь playbackRate={140 / 129.2} у <Audio>.
Анимационные примитивы
Из коробки доступны Opacity, Scale, TranslateX, TranslateY, Blur. startInFrames >= 0 — это enter-анимация (от старта секции), отрицательный — exit (от конца). Для сложных компоновок есть inline-обёртка, которая кладёт примитив в обычный flex/grid-flow. Несколько inline-примитивов вкладываются друг в друга для последовательных эффектов.
Пара важных правил из README:
- Используй
FPS, а не голые кадры.duration={15}сломается, когда поменяется fps экспорта.duration={0.5 * FPS}— нет. - Процентные ширины внутри
inlineне работают,inline-обёртка без собственного размера, бериpxилиem. cutInMotion(0–1) режет анимацию по границе сцены — текст «приезжает» уже на полпути, давая эффект конвейера.
Easing
В egaki/video есть набор готовых easing-пресетов: smooth, natural, decelerate, accelerate (безовершутные cubic-bezier) и spring/bounce семейство (elasticSnap, bounce, bounceAnticipate, overshoot, overshootElastic, impulseOvershoot и т.д.). У большинства пресетов есть continuous-вариант с интенсивностью 0–100: overshoot(63), naturalThrow(40). Под капотом — собственный curve engine: cubicBezier(p1x, p1y, p2x, p2y), polybezier([...]), pathPreset({0: [...], 100: [...]}).
cubicBezier() из egaki/video лучше, чем Easing.bezier() из remotion: к нему приклеивается метадата, и tweakpane в дев-режиме показывает и редактирует кривую прямо в плеере. springFromDuration(duration, bounce) и dspring(frame, fps, duration, bounce) заменяют ручную возню с damping/stiffness/mass.
LayoutTransition и FLIP
<LayoutTransition id="title"> анимирует элемент из его позиции в предыдущей секции в новую позицию в текущей — это FLIP по id. Параметры duration, bounce, easing, mode: 'both' | 'position' | 'size'. Внутри одной сцены можно использовать showFrom и showUpTo — несколько экземпляров с одним id, в каждый момент виден только один, и они флип-анимируют друг в друга.
Генерация медиа из MDX
<GeneratedImage prompt="..." seed={99} model="imagen-4.0-generate-001" />, <GeneratedVideo>, <GeneratedSpeech> — типизированные компоненты, которые во время рендера вызывают нужную модель. Использовать их нужно в .server.tsx файлах и импортировать из egaki/generate-media (а не egaki/video, где экспорты — client-стабы, возвращающие null). Сам импорт из .server.* автоматически оборачивается в <Server>-слот RSC, руками ничего не надо.
Captions и TTS
Стандартный воркфлоу: TTS → транскрибация с word timestamps → <Caption words={[...]} />. Модели с таймстампами: whisper-1, ink-whisper, scribe_v1, nova-3, whisper-large-v3-turbo, distil-whisper-large-v3-en. Задержка каждого слова — startSecond * FPS.
Стиль субтитров по умолчанию — плёночный: Georgia 42px, цвет #f5d442, нижняя треть кадра, maxWidth: 70%, без теней и анимаций, только opacity: 0/1. Главное — не рендерить слова по условию, иначе layout будет прыгать. Перегенерировал TTS — обязательно переснимай таймстампы, они сдвигаются вместе с длиной аудио.
Дополнительные штуки
<Server>— RSC-слот, в нём разрешены async-компоненты, файловые операции, прямые импорты.<Fill>— улучшенный аналогAbsoluteFillдля видео, по умолчанию растягивает по горизонтали и центрирует по вертикали.<DimOverlay>— затемняющий слой, удобно класть поверх preamble-видео.useTweakpane('MyComponent', {...})— параметры в tweakpane-панели, после тюнинга кнопкой копируешь изменения как структурированный markdown.cachedGenerate— HOF-обёртка для любых асинхронных функций с кешем вpublic/generated/, дедупликацией и трекингом прогресса.- Framer Motion (
motion.div, springs, variants, keyframes) — поддерживается из коробки, ищется автоматически, при отсутствии — нулевой overhead.
Где это полезно
egaki хорошо ложится в три сценария. Первый — быстрый и единообразный доступ к разным генеративным API из терминала или скриптов: одна команда egaki image|video|speech|transcribe, никаких SDK на каждый провайдер. Второй — генеративный пайплайн для маркетинговых креативов: пакетно генеришь варианты, прогоняешь через ImageMagick/ffmpeg, складываешь в нужный формат. Третий — текстово-управляемый монтаж рилсов и шортсов: MDX как сценарий, egaki bpm для бит-синка, captions из TTS, экспорт в MP4 в браузере.
Главный потолок подхода — Chromium-only экспорт (фоновая вкладка будет троттлить requestAnimationFrame) и отсутствие поддержки vw/vh (композиция имеет фиксированный размер в пикселях). Зато для агентских воркфлоу с генерацией контента по промпту получается компактно: один бинарь, JSON-вывод, пакетный режим.
Источник: https://github.com/remorses/egaki