Kadr — GPU-ускоренный многодорожечный видеоредактор (Electron + React + TypeScript) со встроенным ИИ-ассистентом Claude Code, локальным распознаванием речи и программируемой анимацией на Remotion. Превью компонуется на GPU (WebGL2), экспорт строго WYSIWYG: тот же компоновщик кадр в кадр рендерит итоговый файл.
- Быстрый старт
- Интерфейс
- Проекты: создание, сохранение, автосохранение
- Импорт медиа и панель «Медиа»
- Прокси для плавного превью
- Таймлайн и дорожки
- Клипы: базовые операции
- Горячие клавиши
- Трансформации и ключевые кадры
- 3D-режим
- Маски
- Пресеты поз (маски/трансформации)
- Эффекты: внешнее сияние
- Пресеты эффектов
- Переходы наложения (Vegas-стиль)
- Торцевые переходы («кончики», AE/BorisFX-стиль)
- Текстовые клипы
- Аудио
- Музыка и ритм: биты, такты и разделы, реакция на звук, библиотека звуков
- Распознавание речи (транскрипция)
- Панель субтитров и текстовые документы
- Авто-субтитры
- Озвучка текста (ElevenLabs)
- Дефекты озвучки: поиск, перегенерация фразы, обучение
- Remotion-фрагменты: библиотека проекта, параметры, проверка, 3D
- Встроенный Claude Code
- MCP-инструменты Claude
- Экспорт
- Качество движения: Motion Blur и Frame Blending
- Производительность
- Автоматизация: window.kadrEditor
- Файлы и папки приложения
- Устранение неполадок
- Приложение А: полный список переходов
- Приложение Б: формат проекта
npm install # один раз (postinstall сам пересоберёт node-pty под Electron)
npm run dev # запуск в режиме разработки
npm run build # production-сборка в out/
npm run typecheck # проверка типов (рендерер + main-процесс)- Импорт — кнопка «Импорт» в панели «Медиа» (или перетащите файл из панели прямо на таймлайн).
- Монтаж — расставьте клипы на дорожках, подрежьте края, добавьте переходы и эффекты.
- Просмотр — Space, перемотка кликом по линейке, покадрово ←/→.
- Экспорт — кнопка «Экспорт», выбор пресета, готово.
- Многодорожечный монтаж: видео, аудио, текст, Remotion-фрагменты.
- GPU-превью в реальном времени, идентичное финальному рендеру.
- Ключевые кадры на всех параметрах трансформации и масок.
- 3D-повороты слоёв с честной перспективой.
- 14 переходов наложения + 12 кинематографичных торцевых переходов.
- Эффект «Внешнее сияние» — неравномерный дым с частицами.
- Локальное распознавание речи (faster-whisper large-v3) с пословными таймкодами и защитой от галлюцинаций.
- Авто-субтитры с караоке-анимацией одним диалогом.
- Монтаж под музыку: биты как метки с прилипанием (сетка — по реальным атакам), фрагменты, которые двигаются в музыку, библиотека из 260 эффектов и 5 музыкальных подложек со свободными лицензиями.
- Remotion-фрагменты: программируемая анимация как клип на таймлайне, превью без рендера, hot reload.
- Встроенный Claude Code с MCP-доступом ко всему проекту.
- Экспорт: ffmpeg x264 с честным битрейтом, мастер-лимитер, motion blur, frame blending, пресеты под YouTube/Shorts/WebM/MP3.
- Автосохранение раз в 5 минут.
Окно редактора состоит из пяти зон:
┌─────────────────────────────────────────────────────────────┐
│ Топбар: Kadr · имя проекта · Отменить/Повторить · │
│ Новый/Открыть/Сохранить/Сохранить как… · Экспорт · │
│ Хранилище · Журнал · Claude · RU │
├───────────────┬──────────────────────────┬──────────────────┤
│ │ │ │
│ Боковая │ Превью (GL-канвас) │ Инспектор │
│ панель │ + индикатор звука │ («Свойства») │
│ («Медиа») │ + транспорт │ │
│ │ │ │
├───────────────┴──────────────────────────┴──────────────────┤
│ Таймлайн: тулбар · линейка · дорожки с клипами │
└─────────────────────────────────────────────────────────────┘
| Кнопка | Действие |
|---|---|
| ↶ / ↷ | Отмена / повтор (в подсказке — что именно отменится) |
| Новый проект | Чистый проект (несохранённые изменения теряются) |
| Открыть проект | Диалог открытия .kadr |
| Сохранить | Ctrl+S — в текущий файл (или диалог, если не сохранялся) |
| Сохранить как… | Ctrl+Shift+S — всегда диалог; проект «переезжает» по новому пути |
| Экспорт | Диалог рендера |
| Хранилище | Что редактор оставил на диске и что из этого можно убрать (§32) |
| Журнал | Что не получилось в этой сессии; загорается счётчиком только при сбоях |
| Claude | Встроенная сессия Claude Code (повторное нажатие — закрыть) |
| RU/EN | Переключение языка интерфейса |
Рядом с именем проекта горит янтарная точка, пока есть несохранённые изменения; после сохранения на три секунды появляется «✓ Сохранено».
Кнопка «Журнал» молчит, пока всё в порядке, и загорается янтарным счётчиком, когда что-то не получилось. Раньше два десятка мест в редакторе сообщали о неудаче только в консоль разработчика, и снимок, который не сохранился, импорт, который ничего не принёс, и автосейв, который не записался, выглядели одинаково: «я нажал, и ничего не произошло».
Журнал живёт только в памяти (кольцо на 500 записей) и исчезает
вместе с окном: это окно в текущую сессию, а не дневник на диске.
Строку можно раскрыть и увидеть причину целиком, а всё сразу —
скопировать одной кнопкой и отдать в отчёт или встроенному Claude
(kadrEditor.logAsText()).
Сообщения браузера, которые сбоем не являются (например, отложенное
уведомление ResizeObserver), пишутся как информационные и счётчик не
зажигают — лампочка, мигающая на хорошие новости, бесполезна.
В верхней строке журнала — видеокарта, на которой рисует превью, и переключатель «Авто (по замерам) / Дискретная / Встроенная» (нужен перезапуск). На ноутбуке с двумя картами Chromium по умолчанию рисует на встроенной, на которой работает экран. Дискретная выбирается по замеру, а не «потому что мощнее»: на гибридной системе каждый её кадр копируется на встроенную для показа, и на проверенной машине превью с ней было медленнее — поэтому «Авто» оставляет карту по умолчанию. Если выбранная карта не поднялась или GPU-процесс падает, следующий запуск откатывается к умолчанию и пишет об этом в журнал.
- Вертикальный разделитель между боковой панелью и превью — ширина панели.
- Горизонтальный разделитель над таймлайном — высота таймлайна.
- Размеры запоминаются между запусками (localStorage).
- Отображает проект в реальном времени через WebGL2-компоновщик — то, что вы видите, и есть будущий рендер (один и тот же код рисования).
- Поверх канваса живут оверлеи Remotion-фрагментов и гизмо перемещения.
- Справа — индикатор уровня звука.
- Снизу — транспорт: undo/redo, в начало, play/pause, разрезать, удалить, текст, снимок кадра, вынести превью в отдельное окно, луковая кожура (§25), таймкод.
Кнопка справа от снимка кадра выносит превью в самостоятельное окно операционной системы: его можно растянуть, перенести на второй монитор и развернуть, пока таймлайн остаётся в основном окне. Второй клик (или закрытие окна) возвращает превью на место; в основном окне на его месте появляется надпись и кнопка «Вернуть в редактор».
Переносится тот самый холст, а не создаётся новый. Иначе на каждом переключении получался бы новый контекст GPU (Chromium держит их 16 на процесс и, когда лимит пройден, отбирает самый старый — то есть у превью) и перезагружались бы все iframe'ы фрагментов. Следствия, которые вы заметите: картинка не мигает, фрагменты не начинают воспроизведение заново, а пробел и стрелки управляют транспортом из обоих окон.
Размер и положение окна запоминаются. Снимок кадра из вынесенного окна работает как обычно.
Без выделения — настройки проекта: имя, разрешение (W/H), частота кадров.
С выделенным клипом:
- имя клипа;
- для текстовых клипов — текст, размер шрифта, цвет, обводка, жирность;
- позиция X/Y, масштаб, поворот, прозрачность (числами);
- громкость и «Без звука»;
- секция Эффекты с пресетами (кнопка «Пресеты» со звёздочкой).
- у Remotion-фрагментов — секция Реакция на звук: запечь звук под клипом, чтобы фрагмент двигался в музыку (§19).
Интерфейс собран на одной палитре токенов: цвета, отступы, радиусы, тени и длительности анимаций заданы в одном месте, и ни одно правило ниже не изобретает собственный цвет. Практический смысл — редактор выглядит как один инструмент, а не как склейка экранов, и любую правку темы достаточно сделать один раз.
- Иконки вместо эмодзи. Форму, вес и цвет эмодзи задаёт шрифт операционной системы: они никогда не выравнивались с текстом рядом и на Windows выглядели игрушечно. Теперь это встроенные векторные иконки, наследующие цвет и размер текста.
- Контраст измерен, а не подобран на глаз: основной текст 15.3:1, вторичный 8.7:1, приглушённый 4.95:1, акцент 6.0:1 — по WCAG 2.2 AA. Границы управляющих элементов светлее декоративных линий: кнопку здесь опознают именно по контуру.
- Видимый фокус с клавиатуры — раньше его не было ни у одного элемента. Теперь Tab обводит активный элемент акцентной рамкой (и только при работе с клавиатуры, не при клике мышью).
- Диалоги устроены одинаково: заголовок, прокручиваемое тело, неподвижный низ, Escape, ловушка фокуса и возврат фокуса туда, откуда диалог открыли. Пока диалог открыт, горячие клавиши редактора не срабатывают сквозь него — пробел на кнопке диалога раньше нажимал кнопку и запускал воспроизведение.
- Полоса прокрутки таймлайна — рабочий инструмент, а не системная ниточка: 15 px, различимый ползунок с минимальным размером. Ползунок пропорционален зуму, и на пятнадцатиминутном проекте при большом увеличении он вырождался в один пиксель, который невозможно поймать.
- Уважение к
prefers-reduced-motion: если в системе просили меньше анимаций, переходы теряют движение, но не теряют смысл.
Проект — один JSON-файл с расширением .kadr. Внутри — полная модель:
дорожки, клипы, ссылки на медиафайлы (по абсолютным путям), ключевые
кадры, эффекты, тексты, фрагменты. Медиафайлы в проект не копируются.
- Ctrl+S / «Сохранить» — в текущий файл; если проект ещё не имеет файла, откроется диалог.
- Ctrl+Shift+S / «Сохранить как…» — всегда диалог; после сохранения проект продолжает жить по новому пути (последующие Ctrl+S — туда).
- Все диалоги (проекты, импорт, экспорт) запоминают последнюю папку; первый запуск открывается в «Видео»/«Загрузки».
Работает само, настройки не требует:
- раз в 5 минут, и только если проект менялся с прошлого раза;
- файл
<имя>.autosave.kadrв той же папке, что и основной (для ещё не сохранённых проектов — в «Загрузках»), перезаписывается; - запись атомарная (временный файл + переименование) — сбой в момент записи не может оставить битый автосейв;
- пропускается, пока идёт экспорт или открыта сессия встроенного Claude (чтобы не конкурировать за диск и не снимать проект посреди массовых правок); после завершения — запишется при следующем тике;
- пустые проекты не сохраняются.
Восстановление: «Открыть проект» → выбрать .autosave.kadr.
- История на 50 шагов, каждый шаг подписан («перемещение клипа», «разрезание», «выбор перехода»…) — подпись видна в подсказке кнопок ↶/↷.
- Ctrl+Z — отмена, Ctrl+Shift+Z или Ctrl+Y — повтор.
- Откатывается всё: правки клипов, ключевые кадры, эффекты, переходы, тексты, применение пресетов.
- Кнопка «Импорт» в панели «Медиа» (мультивыбор).
- Drag-and-drop в любое место окна: бросок на дорожку кладёт файлы клипами встык от точки броска (несколько файлов — друг за другом, аудио уходит на аудиодорожку); бросок на линейку/пустоту таймлайна — на первую подходящую дорожку; на медиапанель или куда-либо ещё — просто импорт в лоток. Повторный дроп того же файла не создаёт дубликата.
- Картинка из браузера: перетащите изображение прямо со страницы —
оно скачается (кэш по URL в
userData/imported) и встанет клипом. Понимаются иdata:-миниатюры, и перетаскивания из песочных приложений через XDG-портал, и файлы из панели загрузок Chrome. - Ctrl+V — вставка из буфера обмена (когда внутри редактора ничего не скопировано): скопированные файлы или скопированное изображение (например, «Копировать изображение» в Telegram — перетаскиванием tdesktop фото не отдаёт). Изображение сохраняется как PNG и ложится клипом на плейхед.
- Файлы анализируются ffprobe: длительность, размеры, fps, наличие аудио, миниатюры (начало и конец для видео), волновая форма звука.
Прозрачные исходники (WebM с VP8/VP9+alpha, MOV с ProRes 4444, HEVC с альфой) сохраняют прозрачность и в превью, и в экспорте: под ними видно нижние дорожки, маски и эффекты работают как обычно. Прокси и промежуточные файлы для таких исходников строятся с сохранением альфа-канала, а при экспорте они читаются быстрым путём — см. §28.
- Видео: mp4, mkv, mov, webm, avi, m4v, mts (в том числе с альфа-каналом).
- Аудио: mp3, wav, flac, ogg, aac, m4a, opus.
- Изображения: png, jpg/jpeg, webp, bmp, gif.
- Текст: srt, txt — попадают в секцию «Тексты» (см. §21).
- Сетка карточек: миниатюра (для аудио — ♪), имя, полный путь в подсказке.
- Перетаскивание карточки на таймлайн — вставка клипа в указанное место; двойной клик — вставка на плейхед.
- Видео со звуком вставляется парой связанных клипов: видео на видеодорожку + звук на аудиодорожку (двигаются вместе, см. §7).
- Бейджи на карточке:
⚙ 47%— строится прокси;P— прокси готов, превью идёт через него;- кнопка транскрибации (для медиа со звуком) и кнопка озвучки (для текстов).
- Выделение и удаление: клик выделяет карточку, Ctrl+клик добавляет, Shift+клик — диапазон. Крестик на карточке (при наведении) удаляет файл из проекта, кнопка «✕ N» в шапке — всю выборку. Клипы на таймлайне, использующие удаляемые файлы (включая связанные AV-пары), удаляются вместе с ними — с подтверждением, одной записью в истории отмен; сами файлы на диске не трогаются.
Сворачиваемый список под сеткой медиа (стрелка ▾/▸ в заголовке, счётчик документов, собственная прокрутка — длинный список не вытесняет медиа). Подробности — в §21.
- 3D-файлы (STL, 3MF, STEP, OBJ, GLB/glTF), брошенные в корзину или импортированные, уходят не в медиа, а в модели проекта (§25, «3D-модели»).
- HDR-съёмка (HLG с телефона, PQ с камеры) показывается и экспортируется приведённой к SDR BT.709: иначе она выглядит плоской и серой. Раньше это приходилось делать самому командой ffmpeg.
- Поворот из метаданных (портретное видео с телефона) учитывается везде — в превью, в снимках и в экспорте. Экспорт такого клипа раньше выходил боком.
У HDR-исходников прокси строится уже в SDR (тон-маппинг через 3D-LUT, ffmpeg без zscale здесь не нужен); такие прокси используются и для снимков кадра, потому что оригинал в браузере выглядел бы серым.
Тяжёлые исходники тормозили бы превью, поэтому:
- каждое видео с коротком стороной ≥720p автоматически получает фоновую облегчённую копию: H.264 540p + AAC 96k;
- прокси строятся по одному (очередь), прогресс виден на карточке;
- кэш:
userData/proxies/, ключ — путь+размер+mtime файла (изменился исходник — прокси перестроится); - превью декодирует прокси, экспорт всегда читает оригинал — качество рендера не страдает.
| Кнопка | Действие |
|---|---|
| +Видео | Добавить видеодорожку (сверху) |
| +Аудио | Добавить аудиодорожку (снизу) |
| Транскрибировать | Распознать речь в выделенном диапазоне (§20) |
| Авто субтитры | Анимированные субтитры на диапазон/весь проект (§22) |
| Биты | Найти доли, такты, разделы и паузы музыки (§19) |
| Магнит (рядом с «Биты») | Включить/выключить прилипание к битам |
| Проверка | Проверить фрагменты: ритм, читаемость, контраст, стыки, камера (§25) |
| Звуки | Библиотека эффектов и музыки, свои звуки (§19) |
| Волна | Аудио-реактивная неоновая волна по диапазону (§25) |
| Озвучка | Настройки синтеза речи (§23) |
| Дефекты | Разметка и перегенерация дефектов озвучки (§24) |
| Отметить · Переозвучить | Поставить свою отметку «дефект» / «не нравится» (§24) |
| Скрыть отметки | Спрятать полосы дефектов, чтобы видеть клипы (§24) |
| Высота | Слайдер высоты дорожек (32–140 px) |
| Масштаб | Слайдер зума таймлайна (логарифмический) |
- Порядок видеодорожек = порядок слоёв: верхняя дорожка рисуется поверх всех.
- У каждой дорожки:
- имя (V1, V2…, A1…);
- 🔇 mute — видеодорожка исчезает из кадра, аудио замолкает;
- замок — клипы не редактируются, вставка на дорожку запрещена;
- слайдер: для аудио — громкость дорожки (0–200 %), для видео — непрозрачность всего слоя (0–100 %);
- 🌐 движение дорожки (видео) — анимированная 3D-трансформация целиком всей дорожки (общий «полёт камеры» по слою): X/Y/масштаб/ поворот/наклоны/глубина с ключевыми кадрами в абсолютном времени проекта;
- контекстное меню — удалить дорожку, добавить дорожку рядом.
- Клик по линейке — переставить плейхед (с перетаскиванием).
- Колесо мыши — зум вокруг курсора. Во время жеста таймлайн плавно растягивается (подписи клипов на мгновение растянуты), а через 0.15 с после остановки перерисовывается чётко — точка под курсором остаётся на месте. Раньше каждый шаг колеса перерисовывал весь таймлайн, и на проекте в тысячу клипов зум шёл рывками по несколько кадров в секунду.
- Слайдер «Масштаб» зумирует так же, держа на месте плейхед (если он виден), иначе середину экрана.
- Shift+перетаскивание по линейке — выделить диапазон (фрагмент): жёлтая зона. Диапазон используется экспортом, транскрипцией, авто-субтитрами, копированием/удалением фрагмента.
- Esc — снять диапазон.
- Ctrl+клик по пустому месту дорожки — сомкнуть клипы (закрыть дыру слева от места клика).
Метки времени поверх всего таймлайна — не привязаны ни к дорожке, ни к клипу. Удобно отмечать места, к которым нужно вернуться, и объяснять встроенному Claude, где именно править.
- M — поставить маркер на плейхеде; номера выдаются подряд (1, 2, 3…), следующий маркер получает следующий свободный номер;
- перетаскивание флажка — передвинуть маркер (прилипает к краям клипов и к плейхеду, как обычное перетаскивание);
- правый клик по флажку — удалить маркер;
- маркеры живут в проекте (
project.markers) и сохраняются вместе с ним; - встроенный Claude их видит (
kadr_state) и может ставить свои:addMarker(t),moveMarker(id, t),removeMarker(id); - к маркерам прилипает всё, что прилипает к краям клипов: клипы при перетаскивании, их края, диапазон и сами маркеры;
- биты музыки — это тоже маркеры (вида «бит»): тонкие розовые линии без флажка, ставятся кнопкой «Биты» (§19). Первая доля такта толще и несёт номер такта, разделы песни идут подписанной полосой под линейкой, паузы заштрихованы. Биты и ваши маркеры не мешают друг другу: разметка битов никогда не трогает ваши номера.
Постановка, перенос и удаление маркера — отдельные шаги истории, отменяются через Ctrl+Z.
Красная вертикаль через все дорожки. Во время воспроизведения движется по «якорным» часам — равномерно, без накопления дрожания таймера.
| Вид | Цвет | Содержимое |
|---|---|---|
| media (видео) | синий | кадры видеофайла/изображения |
| media (аудио) | зелёный | звук |
| text | особый | текстовый оверлей |
| remotion | фиолетовый ⚛ | живая Remotion-композиция (§25) |
- Перетаскивание — перемещение по дорожке и между дорожками (с примагничиванием к соседним клипам и плейхеду).
- Края клипа — подрезка начала/конца (трим). У начала меняется
inPoint(откуда играть исходник). - Верхние уголки — ручки фейдов: потяните внутрь — плавное появление/затухание (видео — прозрачность, звук — громкость).
- Перетаскивание края с зажатым Ctrl — изменение скорости клипа (растяжение/сжатие по времени с пересчётом темпа). Работает за оба края: правый якорит начало, левый — конец клипа. Диапазон ×0.02–×100; значение прилипает к круглым множителям (×0.5, ×1, ×2…) и к краям соседних клипов/плейхеду, рядом с курсором — живой бейдж «×N» (подсвечивается в момент прилипания). Синие ручки на середине обоих краёв делают то же самое; без Ctrl левая ручка подрезает клип (контент остаётся на месте), правая — растягивает/зацикливает.
- Нижние фиолетовые уголки — «кончики» торцевых переходов (§16).
- Двойной клик — открыть редактор анимации (§9).
- Контекстное меню — разрезать, удалить, переходы, связка и т. д.
Правый клик по видео- или аудиоклипу → «Реверсировать». ffmpeg
рендерит используемый диапазон исходника задом наперёд (видео — кусками
с ограниченной памятью, звук — целиком, без потерь для аудиофайлов) в
кэш userData/reversed, клип и его связанная AV-пара переключаются на
новый ассет (и в лотке, и на клипе он помечен значком реверса, во время
рендера — ⏳). Эффекты, маски, переходы и ключевые кадры клипа не
трогаются. Повторный вызов на реверсированном клипе — «Убрать
реверс» — мгновенно возвращает оригинал без пере-кодирования. Одна
запись в истории отмен; повторный реверс того же диапазона берётся из
кэша. Доступно и встроенному Claude: kadrEditor.reverseClip(clipId).
Если видео/аудио-клип растянут дольше, чем длится исходник, источник зацикливается (играет по кругу). Удобно для фоновой музыки и текстур.
speed ≠ 1 ускоряет/замедляет клип; звук обрабатывается цепочкой
atempo в финальном миксе (без изменения высоты тона). Время исходника
для кадра вычисляется как inPoint + rel·speed. Диапазон ×0.02–×100:
экспорт точен на любой скорости, превью воспроизводит элемент в пределах
аппаратного диапазона Chromium (×0.0625–×16) и на более экстремальных
значениях держит синхронизацию перемотками.
Видео со звуком вставляется парой с общим linkId:
- двигаются и подрезаются вместе;
- U — разорвать/восстановить связь выделенного;
- видеоклип пары автоматически замьючен (звук идёт с аудиодорожки).
- S — разрезать все выделенные клипы (или клип под плейхедом) в позиции плейхеда.
- D / Delete / Backspace — удалить выделенные клипы; если выделения нет, но есть диапазон — вырезать диапазон из всех дорожек со смыканием.
- Ctrl+C / Ctrl+V — копирование клипов (или содержимого диапазона) и вставка на плейхед.
| Клавиша | Действие |
|---|---|
| Space | Воспроизведение / пауза |
| S | Разрезать по плейхеду |
| Ctrl+S | Сохранить проект |
| Ctrl+Shift+S | Сохранить как… |
| D / Delete / Backspace | Удалить выделение (или вырезать диапазон) |
| Ctrl+Z | Отменить |
| Ctrl+Shift+Z / Ctrl+Y | Повторить |
| Ctrl+C | Копировать выделение / диапазон |
| Ctrl+V | Вставить на плейхеде |
| M | Поставить маркер на плейхеде |
| U | Связать/развязать видео+аудио |
| ← / → | Шаг на кадр назад/вперёд |
| Shift+← / Shift+→ | Шаг на 1 секунду |
| Home | В начало |
| Esc | Закрыть редактор анимации / снять диапазон |
Раскладка не имеет значения: используются физические коды клавиш, работает и в русской раскладке.
Каждый видимый клип имеет:
| Параметр | Диапазон | Описание |
|---|---|---|
| X, Y | px проекта | смещение от центра кадра |
| Масштаб | 0.01–20 | относительно вписанного размера |
| Поворот | градусы | вокруг центра слоя (ось Z) |
| Прозрачность | 0–1 | умножается на фейды и непрозрачность дорожки |
| Наклон X/Y | градусы | 3D-наклоны (§10) |
| Глубина Z | px | 3D-смещение от камеры (§10) |
Числами параметры правятся в Инспекторе, анимация — в редакторе анимации.
Открывается двойным кликом по клипу. Режимы: Трансформация и Маска (вкладки).
- Каждый параметр — строка с числовым полем и кнопкой-ромбом ◇/◆:
- ◇ — параметр статичен; клик ставит ключевой кадр в позиции плейхеда;
- ◆ — на плейхеде есть ключ; клик убирает его.
- Ключи отображаются маркерами на мини-таймлайне клипа; перетаскиваются.
- Между ключами значения интерполируются (линейно / сглаженно — выбор easing на ключе).
- Изменение значения при включённой анимации записывает ключ в текущей позиции — рабочий процесс как в AE: двигаете плейхед → крутите ручку → ключ ставится сам.
- Время ключей хранится в секундах от начала клипа — клип можно свободно двигать по таймлайну, анимация едет с ним.
- Вся трансформация (X, Y, масштаб, поворот, прозрачность, наклоны, Z).
- Громкость клипа (gain).
- Маска: все четыре кромки и каждый параметр каждой фигуры (§11).
- Движение дорожки (🌐) — в абсолютном времени проекта.
- Включается в редакторе анимации (переключатель 3D) — у клипа появляются наклон X, наклон Y и глубина Z.
- Перспектива честная: углы слоя проецируются с гомогенной координатой, текстура интерполируется перспективно-корректно (без «излома» по диагонали).
- Фокусное расстояние «камеры» — 1.2 максимальной стороны кадра.
- Работает на любых клипах, включая Remotion-фрагменты (для них превью автоматически переключается в режим захвата пикселей, §25).
- Движение дорожки (🌐) — те же 3D-параметры, применяемые ко всем клипам дорожки после их собственных трансформаций: общий облёт сцены.
Два механизма, работают одновременно:
Четыре анимируемые кромки — слева/сверху/справа/снизу, каждая 0–50 % слоя. Обрезка прямоугольником, вычисляется в шейдере.
До 8 фигур на клип, каждая:
| Свойство | Описание |
|---|---|
| Тип | прямоугольник / эллипс / треугольник |
| Центр (cx, cy) | в координатах слоя (0–1), анимируемый |
| Размер (w, h) | анимируемый |
| Растушёвка внутрь | мягкая кромка внутрь от границы |
| Растушёвка наружу | мягкая кромка наружу |
| Инверсия | фигура вырезает дыру вместо «оставить внутри» |
Логика комбинирования: объединение обычных фигур минус все инвертированные. Расстояния до кромок считаются аспектно-корректно (растушёвка одинаково широка по всем направлениям).
Редактирование — в редакторе анимации, режим «Маска»: фигуры добавляются, перетаскиваются и растягиваются мышью прямо в превью.
Сохранение одного состояния маски или трансформации под именем — и применение в любом проекте, в любое время, к любому клипу.
- Кнопка «Пресеты» в редакторе анимации.
- Меню показывает пресеты текущего режима (трансформация/маска).
- Сохранить: ввести имя → текущие значения параметров (или набор фигур маски) записываются.
- Применить: клик по имени. Значения пишутся через обычный механизм анимации: если параметр анимирован — ставится ключевой кадр в позиции плейхеда (поза «вклеивается» в анимацию), если нет — задаётся значение. 3D-поза автоматически включает 3D-режим. Маска с тем же числом фигур применяется попараметрно (анимируемо), с другим — заменяет набор фигур.
- Удалить: ✕ рядом с именем.
- Хранение:
pose-presets.jsonв данных приложения — пресеты живут между перезапусками и общие для всех проектов.
Эффекты живут в секции Эффекты Инспектора выделенного клипа. У каждого эффекта: галочка включения, кнопка удаления ✕, свои параметры. Эффекты работают на любых клипах — видео, изображениях, тексте, Remotion-фрагментах — и в превью, и в рендере одинаково.
Гауссово размытие всего слоя на GPU — расфокус фона под титрами, «мечтательные» планы, мягкие подложки:
| Параметр | Диапазон | Что делает |
|---|---|---|
| Интенсивность | 0–300 px | радиус размытия (в пикселях проекта — в любом разрешении рендера выглядит одинаково) |
Совместимо с внешним сиянием на том же клипе, работает внутри переходов и motion blur; WYSIWYG в экспорте. Входит в пресеты эффектов.
Не плоский ореол, а неравномерный дым с частицами, хаотично выходящий из-за краёв объекта:
| Параметр | Диапазон | Что делает |
|---|---|---|
| Цвет | пипетка | базовый цвет свечения |
| Размер | 4–400 px | радиус ореола |
| Яркость | 0–3 | сила свечения (выше ~1.5 — начинает «выгорать») |
| Насыщенность | 0–2 | 0 — монохром, 2 — кислотный перенасыщенный |
| Дымность | 0–1 | 0 — чистый ровный ореол, 1 — полный хаос клубов |
| Скорость дыма | 0–3 | темп дрейфа клубов и мерцания частиц |
| Частицы | 0–1 | плотность круглых «угольков», уносящихся от кромки |
Как это устроено (и почему выглядит дорого):
- слой рендерится в отдельный буфер; его альфа-силуэт размывается спиральным фильтром в поле ореола (¼ разрешения — быстро);
- шум FBM с поворотом октав (никаких «линейных волн») и billow-профилем даёт круглые пухлые клубы, разделённые тёмными трещинами;
- низкочастотная огибающая по периметру делает свечение неравномерным: где-то еле тлеет, где-то вырывается далеко за радиус;
- отдельный слой хлопьев отрывается от внешней кромки и уплывает;
- сама граница ореола «гуляет» по шуму — рваные щупальца вместо ровного круга;
- частицы — круглые мерцающие точки из клеточного хеша, каждая со своим размером и фазой;
- свечение подавлено внутри объекта и мягко гаснет на внешней границе; яркость проходит через «киношное плечо» — пересветы сохраняют текстуру.
Анимация дыма привязана к локальному времени клипа: в превью и в экспорте дым идентичен кадр в кадр. Эффект корректно работает внутри переходов и при motion blur.
Аналог пресетов поз, но для всего стека эффектов клипа:
- кнопка «Пресеты» в заголовке секции «Эффекты» Инспектора;
- Сохранить — текущий набор эффектов клипа со всеми настройками под именем;
- Применить — клик по имени заменяет эффекты выделенного клипа набором из пресета (с новыми внутренними id); ложится в историю — отменяется Ctrl+Z;
- Удалить — ✕;
- хранение:
fx-presets.jsonв данных приложения, общее для всех проектов, переживает перезапуск.
Vegas-стиль: перекройте два клипа на одной видеодорожке — зона перекрытия автоматически становится переходом.
- На зоне перекрытия рисуется заметная полоса; клик по значку — меню выбора эффекта (15 пунктов, включая «Без перехода»).
- Оба клипа рендерятся в отдельные буферы и смешиваются GLSL-шейдером (семейство gl-transitions) — любые маски/эффекты/анимации внутри клипов продолжают работать.
- Длительность перехода = длительность перекрытия (двигайте клипы).
- Звук перекрывающихся клипов автоматически кроссфейдится — и в превью, и в экспортном миксе.
- «Без перехода (склейка)» — жёсткий кат в точке начала второго клипа.
Список переходов — Приложение А. Работает между любыми видами клипов, включая Remotion-фрагменты.
AE/BorisFX-стиль: эффектные переходы на кончиках клипов, без перекрытия — для смежных («впритык») клипов и одиночных входов/выходов.
- Фиолетовые уголки в нижних углах каждого клипа: клик по левому — In-переход (вход), по правому — Out-переход (выход). В меню — эффект и длительность.
- Значок ◈ на стыке двух смежных клипов: ставит парный переход (Out первого + In второго того же типа) — кат прячется в пике эффекта, два кончика читаются как одно непрерывное движение.
- Полоски на кончиках клипа показывают установленные переходы.
Эффекты сделаны «дорого»: 14–22-точечные размытия со спектральным расщеплением (хроматическая аберрация вдоль движения), квартическая кривая с максимумом скорости в точке стыка (длинный замах → резкий рывок), параболические траектории у вип-панов, виньетка.
12 эффектов: зум-блюр (наезд/отъезд), RGB-расхождение, вип-паны в четыре стороны, вращение с размытием, засветка-вспышка, глитч, упругое растяжение, линзовое искажение. Полный список — Приложение А.
Кнопка «Текст» добавляет текстовый клип на видеодорожку.
Параметры (Инспектор):
- многострочный текст;
- размер шрифта (8–500), жирность;
- цвет, цвет обводки, толщина обводки (0–40 px);
- выравнивание, фон-плашка;
- вся трансформация/маски/эффекты/переходы — как у любого клипа: текст можно анимировать ключами, светить сиянием, вводить вип-паном.
Для анимированных титров со сложной типографикой используйте Remotion-фрагменты (§25) и авто-субтитры (§22).
- Клип: параметр «Громкость» (0–200 %), анимируемый ключами (gain — это Anim, как X/Y); «Без звука» — галочка.
- Дорожка: слайдер громкости 0–200 %.
- Итог = громкость клипа × громкость дорожки × фейды.
- Ручки в верхних углах клипа — fade in/out (звук и картинка вместе).
- Перекрытие клипов на одной дорожке — автоматический аудиокроссфейд.
Аудио маршрутизируется через WebAudio: громкость >100 % реально усиливает сигнал; индикатор уровня — справа от превью. Элементы синхронизируются с мастер-часами (пересинхронизация при дрейфе >0.15 с).
Финальный звук собирает ffmpeg по сегментам:
громкость → atempo (скорость) → afade (фейды) → adelay (позиция) → apad → amix. Все потоки выровнены по длительности, масштабирование amix
компенсируется точно — громкости в миксе соответствуют превью. Лупы
клипов разворачиваются в несколько сегментов, скорость — цепочкой atempo.
На аудиоклипах рисуется двухслойная волна (пик + RMS) в стиле Audacity, до 1000 точек/сек.
Всё для монтажа под музыку: доли как метки на таймлайне, фрагменты, которые «слышат» звук под собой, и библиотека эффектов и музыки. Основа взята из навыка /brag (latent-spaces/brag) и встроена в редактор.
Кнопка «Биты» в тулбаре таймлайна открывает диалог.
- Что слушать: выделенные клипы, микс выделенного диапазона, микс всего проекта или одна дорожка.
- Какие доли: каждая, каждая 2-я, каждая 4-я (такт) или только акценты. Для текста, который нужно успеть прочитать, берите 2-ю или 4-ю: выше 110 BPM доли идут чаще, чем раз в 0.55 с.
- Результат: тонкие розовые линии на таймлайне, акценты ярче. Прежние биты на этом участке заменяются, ваши собственные маркеры не трогаются. Это маркеры вида «бит» — они сохраняются в проекте и видны встроенному Claude.
- Прилипание: к битам прилипают клипы, их края, диапазон, маркеры и плейхед. Магнит рядом с кнопкой выключает прилипание именно к битам; к вашим маркерам клипы теперь прилипают всегда (раньше маркер вообще не был точкой привязки).
Анализ — порт beat_track из librosa 0.11 (сила онсетов по 128 мел-полосам,
темпограмма с априорным темпом 120 BPM, динамическое программирование
Эллиса). На пяти встроенных треках он совпадает с librosa бит в бит:
темп тот же, каждая доля в пределах 0.05 мс (node scripts/check-beats.mjs resources/music). Анализ идёт на 44.1 кГц: на 22.05 кГц темп квантуется
грубо, и трек в 120.19 BPM читался бы как 117.45 или 123.05.
Сетка по атакам. librosa ставит долю на пик силы онсета, а на треке, зажатом лимитером, где 808 вступает после провала сайдчейна, этот пик приходит, когда нота уже звучит. На реальном фонк-треке каждая доля стояла на 78–120 мс (≈110) позже баса — шесть кадров при 60 fps: текст «прыгал в бит» заметно после удара, склейки и звуки тоже опаздывали. Поэтому после librosa сетка сверяется с реальными атаками — низ до 150 Гц, затем вся полоса. Сдвигается она, только если опоздание систематическое: у большинства долей чёткая атака, разброс узкий, медиана дальше 25 мс. Тогда каждая доля встаёт точно на свою атаку. На трек, где librosa прав, это не влияет вовсе — на встроенных треках не сдвигается ни одна доля. Если сетку подтянули, диалог так и пишет: «сетка подтянута к ударам на N мс».
Чего это не лечит: места, где трекер теряет саму фазу (например, музыка обрывается на несколько долей). Там разница бывает в четверть такта, и безопасно искать так далеко нельзя — такие места стоит проверить глазами по волновой форме.
Сетки долей мало: ролик под песню ощущается правильным, когда крупное событие приходится на первую долю такта, а не на любую. Поверх долей анализ определяет:
- размер (4/4 или 3/4) и какая доля — «раз»: по силе бочки и баса и по смене гармонии, за вычетом малого барабана на слабых долях. Рядом — уверенность; если она низкая, стоит проверить «раз» на слух;
- разделы песни — вступление, нарастание, куплет, припев, брейк, концовка — с энергией 0..1: по сходству тактов между собой и скачкам громкости. Названия — эвристика, границы — надёжнее;
- паузы — места, где музыка останавливается (барабаны выпадают): пауза в музыке — пауза и в кадре;
- смещение бочки относительно сетки (например, −15 мс — удар раньше линии): отклики во фрагментах опережают сетку ровно на него.
На таймлайне первая доля толще и с номером такта, разделы — полосой под линейкой, паузы заштрихованы; всё это — точки прилипания. Диалог «Биты» пишет сводку вида «4/4 · 124 BPM · раз = фаза 0 · бочка −15 мс · 6 разделов». Паритет с librosa по самим долям сохранён.
У выделенного фрагмента в Инспекторе есть секция «Реакция на звук»:
выберите, что слушать (по умолчанию — весь микс под клипом), и нажмите
«Запечь звук». В папку фрагмента пишутся audio.json (громкость, бас,
середина, верх — по значению на каждый кадр композиции — и доли) и
audio.ts с готовым хуком:
import { useAudio } from './audio'
const a = useAudio() // a.level, a.bass, a.mid, a.treble — 0..1
// a.beat — 1 на каждой доле и спадает за ~0.15 с
// a.accent, a.beatIndex, a.sinceBeat, a.bpmЕсли на таймлайне есть карта музыки (кнопка «Биты»), в audio.ts есть и
её структура — такты и разделы берутся из анализа всего трека, а не
восьми секунд вокруг клипа:
import { useAccent, breathAt, bars, sectionAt, inPause } from './audio'
const a = useAccent() // a.hit: 1 на «раз», 0.35 на остальных долях, 0 в паузе
// a.bar, a.beat, a.beatInBar, a.barNumber, a.section, a.energy
const b = breathAt(frame, fps) // волна раз в такт, глубже в энергичных разделахbars — время каждого «раз» в секундах композиции. Крупные события
ставьте на них, мелкие — на доли, в паузах — ничего; свечение пусть
«дышит» раз в такт, а не пульсирует на каждую долю.
Время — время композиции, как его играет превью: секунда τ звучит на
start + (τ − inPoint) / speed. Для устойчивости темпа анализ слушает по
8 с до и после клипа. Если клип сдвинули или музыку под ним поменяли,
секция показывает «Устарело». Экспорт перезапекает такие фрагменты сам;
превью — по кнопке «Обновить». Совет из /brag: пусть музыка оживляет то,
что уже есть в кадре (свечение, масштаб на несколько процентов), а не
превращает кадр в эквалайзер — и никогда не раскачивайте текст так, что его
нельзя прочитать.
Кнопка «Звуки»: вкладки «Эффекты» и «Музыка», поиск по названию, фильтр «Для чего», галочка «Без резких», прослушивание.
- Встроено: 260 эффектов (Kenney, unicaegames — CC0) и пять музыкальных подложек ende.app (CC BY 4.0). Лицензии и условия автора музыки — в resources/CREDITS.md.
- Свои звуки: положите файлы в подпапку
<userData>/sfx/<семейство>/(одна подпапка — одно семейство) и нажмите «Обновить мои звуки». Новые файлы разбираются один раз и кэшируются. - Механика в кадре: в фильтре «Для чего» — щелчки, переключатели,
защёлки, лёгкие удары по металлу, пластику и дереву (75 встроенных).
Под песней с вокалом лучше только такие звуки, тихо (0.4–0.5), каждый —
на то, что в кадре щёлкает на место: «бумы» и «свуши» спорят с песней.
Свой звук можно пометить так же (
kadr_sound_label). - Разметка: у каждого звука есть яркость (тёплый / ровный / яркий),
риск резкости (мягкий / средний / резкий) и форма огибающей. Правила
восстановлены по опубликованной разметке /brag и совпадают с ней на 96–99 %
(
node scripts/check-sfx-labels.mjs). - Удар: главное событие звука. При добавлении на плейхед встаёт именно удар, а не начало файла — у свиста или «бума» с подводкой он бывает через полторы секунды. Звук без единого события (печать, гул) ставится началом.
- Куда ложится: на первую аудиодорожку, свободную на всём отрезке звука, или на новую — наложение на одной дорожке дало бы кроссфейд и приглушило музыку. Музыку можно сразу добавить вместе с метками битов.
Микс — простая сумма, и раньше ничто не мешало ей выйти за 0 дБ. Громкий
трек под одним ударом 808 давал +9.8 dBFS, и кодировщик жёстко срезал именно
самые важные удары. Теперь на выходе микса стоит лимитер на −1 dBFS; для
MP3 это нужно с запасом, потому что сам кодек добавляет выбросы. Всё, что
тише порога, проходит бит в бит и той же длины: задержку «заглядывания
вперёд» лимитера компенсирует сама цепочка
(node scripts/check-limiter.mjs). Анализ битов, транскрипция и волна
слушают микс без лимитера.
Локальная транскрипция на faster-whisper — без интернета и подписок.
- кнопка на карточке медиа (панель «Медиа») — распознать весь файл; таймкоды реплик — от начала исходника.
- «Транскрибировать» в тулбаре таймлайна — распознать выделенный диапазон: микшируется всё слышимое в диапазоне (ровно как в экспорте — с громкостями, скоростями, фейдами) и распознаётся.
| Поле | Варианты |
|---|---|
| Модель | large-v3 (максимум качества, ≈2× длительности записи), medium (в 2–4 раза быстрее), base (черновик) |
| Язык | автоопределение / русский / английский |
| Разбивка | 1 слово (караоке) / 2 / 3 / 4 слова / целые фразы |
| Таймкоды (для диапазона) | абсолютные (по таймлайну) / относительные (от начала фрагмента) |
Во время работы — прогресс и живой текст распознаваемых реплик; можно отменить.
Whisper склонен «слышать» текст в тишине и музыке. Включены все обороны:
- VAD (детектор речи) вырезает неречевые участки до распознавания;
- отключена «память» между сегментами — главный источник зацикленных повторов;
- пороги уверенности (log-prob, no-speech, compression ratio);
- пропуск текста, «услышанного» внутри длинных пауз;
- пост-фильтры: сегменты с равномерно низкой пословной уверенностью и бесконечные повторы одной фразы отбрасываются.
Контракт закреплён тестом: чистый тон обязан дать ноль реплик. На реальной русской речи пословная уверенность ≈1.0.
Whisper отдаёт время каждого слова. Реплики нарезаются с правилами:
- не больше N слов (1–4) на реплику;
- реплика не перепрыгивает конец предложения и паузы >0.6 с;
- слова распределяются ровно: 7 слов при лимите 3 → 3+2+2 (никаких болтающихся одиноких слов);
- составные слова («мини-программами») не рвутся: токены-продолжения склеиваются обратно.
имя.srt + имя.txt рядом с медиафайлом (для диапазона — рядом с
доминирующим исходником, имя вида проект_0m12s-0m45s.srt). Файлы не
перезаписывают чужие: при коллизии добавляется суффикс. Оба документа
регистрируются в секции «Тексты».
Клик по документу в секции «Тексты» открывает панель:
- список реплик: номер, таймкоды начала/конца (правятся как текст в
формате
чч:мм:сс,мс), текст (многострочный); - ▸ номер реплики — плейхед прыгает к реплике на таймлайне (умный маппинг: для файла-исходника — через клип, где он лежит, с учётом обрезки и скорости; для диапазона — через сохранённое смещение);
- удаление реплик, правка текста и времени;
- Сохранить — запись в тот же файл (звёздочка — несохранённые правки);
- ↻ — перечитать с диска.
Простое редактирование всего текста.
Панель раз в 2 секунды проверяет mtime файла: если документ изменил кто-то снаружи — например, встроенный Claude отредактировал SRT своими инструментами — панель сама перечитает файл (пока у вас нет несохранённых правок).
Кнопка «Авто субтитры» в тулбаре таймлайна: речь → стильные анимированные субтитры одним диалогом.
| Поле | Варианты |
|---|---|
| Цель | выделенный диапазон, иначе весь проект |
| Модель / язык | как в транскрипции |
| Слов в титре | 1 (караоке) / 2 / 3 / 4 |
| Шрифт | Sans / Arial Black / Serif / Mono |
| Размер | стартовый размер в px (дальше — мышью) |
| Жирный | да/нет |
| Цвет / Цвет выделения | пипетки |
| Появление | Поп (пружина) / Подъём / Фейд / Нет |
| Выделение слова | Караоке-цвет / Подпрыгивание / Плашка / Нет |
| Скорость анимации | 0.5×–2× |
- Распознаётся речь цели (с пословными таймкодами; SRT попутно сохраняется в «Тексты»).
- Генерируется прозрачный Remotion-фрагмент с запечёнными репликами
и стилем — каждое слово анимируется ровно в момент произнесения:
- караоке-цвет — произнесённые слова перекрашиваются и остаются подсвеченными до конца реплики;
- подпрыгивание — активное слово упруго увеличивается;
- плашка — активное слово на цветной плашке;
- появление реплики — пружинный поп / подъём снизу / фейд.
- Клип субтитров ложится на свободную верхнюю дорожку над целью, в нижней трети кадра, и сразу выделен.
У выделенного фрагмента в превью — пунктирная рамка (гизмо):
- перетаскивание рамки — позиция;
- уголок или колесо мыши — масштаб;
- каждый жест — шаг истории (Ctrl+Z работает).
Гизмо работает для любых Remotion-фрагментов, не только субтитров.
Субтитры — обычный фрагмент: код открыт (index.tsx в workspace),
правится руками или встроенным Claude («сделай плашку скруглённой и
жёлтую обводку»), превью обновляется горячо, рендер — один, при экспорте.
Модуль превращает текст в аудиоклип на таймлайне через API ElevenLabs. Он опционален: без ключа кнопки просто не делают ничего разрушительного, остальной редактор работает как обычно.
- «Озвучка» в тулбаре таймлайна — окно настроек: ключ, голос (кнопка обновления тянет список из вашего аккаунта), модель, ползунки (стабильность, похожесть, стиль, скорость, boost), формат, прокси, интерпретатор python для поиска дефектов и галочка «искать дефекты после озвучки».
- Значок на каждом тексте в панели «Медиа» — маленькое окно «озвучить»: источником может быть этот текст, файл с диска или прямо введённый в поле текст.
Страница редактора скриптуема — через неё работает kadr_eval, а значит
и встроенный Claude. Поэтому ключ там держать нельзя: он лежит в
<userData>/elevenlabs-key.json, права 0600 выставляются при
создании файла, а не потом (между open и chmod файл был бы
всемирно читаемым и уже содержал бы секрет). Рендерер умеет ровно две
вещи: записать новый ключ и спросить, задан ли он. В файл проекта, в
kadr_state и в текст ошибок ключ не попадает никогда.
Запросы идут через сетевой стек Chromium в отдельной партиции
(session.fromPartition), которой прокси задаётся явно — из настройки
или из HTTPS_PROXY. Так сделано не из любви к сложности: общий
net.fetch всегда берёт сессию по умолчанию, а Chromium сам выбирает ей
прокси и вполне может взять HTTP_PROXY, через который API недоступен.
Тогда вместо JSON приходит HTML-страница ошибки прокси и всё падает на
«Unexpected token '<'» — сообщение, которое о настоящей причине не
говорит ничего. Ответ дополнительно проверяется по типу содержимого, и в
тексте ошибки называется прокси и начало того, что пришло.
Синтаксис правил у Chromium свой: для HTTP-прокси нужно
https=host:port;http=host:port, для socks — полный socks5://host:port.
Это делает shared/proxy.ts, и его можно проверить без приложения:
node scripts/check-proxy.mjs.
Текст режется под лимит модели по самой сильной доступной границе:
абзац → предложение → часть предложения → пробел. Куски синтезируются
по очереди и сшиваются через previous_text/next_text, а когда API
вернул идентификаторы — ещё и через previous_request_ids: без этого
интонация на стыках рвётся слышимо.
Разбиение ничего не теряет: куски, склеенные обратно, совпадают с
входом байт в байт. Это не педантизм — дальше детектор дефектов
адресует места в тексте по смещению символа, и один потерянный пробел
сдвинул бы все последующие индексы. Проверяется отдельно:
node scripts/check-ttstext.mjs.
Галочка «ускорить» с коэффициентом (по умолчанию выключена). Ускорение применяется в том же проходе ffmpeg, что и декодирование ответа API, — отдельный проход перекодировал бы звук ещё раз и терял поколение на ровном месте.
Коэффициент запоминается в самом прогоне озвучки, а не берётся из текущих настроек. Это важно для перегенерации: файл на таймлайне уже ускорен, и новая фраза обязана быть ускорена так же, иначе темп слышимо прыгнет посреди предложения — даже если галочку в настройках с тех пор сняли.
- Аудиофайл рядом с проектом — FLAC. Раньше это был wav: 12 минут речи стоили 142 МБ, и каждая перегенерация писала рядом новый файл, так что рабочая папка распухала за день до гигабайтов. FLAC — без потерь, склейка остаётся посэмвольно точной, а тот же материал занимает вчетверо меньше.
- Число каналов — как прислал синтез. ElevenLabs отвечает в моно, а запись велась в стерео: канал просто дублировался. Кроме двойного размера это стоило ровно 3.01 дБ — матрица моно→стерео в ffmpeg умножает на 0.7071, и озвучка в превью звучала тише, чем была синтезирована.
<имя>.script.txt— точный текст, ушедший в синтез, регистрируется в текстах проекта. Его sha1 хранится в прогоне: индексы слов, которыми оперирует детектор, верны только пока файл не изменился.- Клип на аудиодорожке. Если аудиодорожек в проекте нет, она создаётся: озвучка, которая не издала ни звука, — это отказ, а не «ничего не произошло». Всё вместе — одна запись в истории отмен.
KADR_TTS_MOCK=1 заставляет главный процесс синтезировать
речеподобный звук локально через ffmpeg (тон с паузами на границах
предложений). Без этого каждый прогон набора тратил бы ваши платные
запросы и требовал сети.
kadr_voice_speak — озвучить текст и положить клип. Смотрите §27.
Синтез иногда ошибается: проглатывает слово, читает аббревиатуру не так, ставит ударение не туда. Этот модуль находит такие места, даёт вам принять решение по каждому и перегенерирует только подтверждённую фразу, вшивая её обратно бесшовно.
Детектор — отдельный проект автора редактора, встроенный внутрь вместе с лёгкими весами. Он локальный: звук никуда не отправляется.
Python 3.11 и новее (пакету нужен tomllib) с torch и
faster-whisper. Дистрибутивы до сих пор ставят 3.9 как python3, а
колёса обычно живут в venv — поэтому интерпретатор это настройка
(окно настроек озвучки → «Python», либо переменная
KADR_TTSQC_PYTHON). Кнопка самопроверки в том же окне печатает версию,
модули, наличие весов, CUDA и ffmpeg; если чего-то нет, модуль честно
говорит об этом и вырождается в обычную озвучку, а не ломается.
Первый запуск на чистой машине тянет из HuggingFace около 3 ГБ весов — это не зависание.
Диалог «Дефекты» построен пятью шагами, и это же порядок работы:
- Найти — прогнать детектор по озвучке.
- Разметить — пройти по найденному и решить по каждому.
- Перегенерировать — заменить подтверждённые фразы.
- Обучение — отправить решения в корпус и, по желанию, переобучить.
- Версии — убрать старые дубли файлов.
- Дефект — фиолетовая полоса в косую штриховку высотой в свою дорожку (обычное выделение диапазона — во всю высоту таймлайна; разница видна сразу) с флажком-шевроном.
- Ваша отметка «здесь дефект» — тот же фиолетовый, флажок с ✎. Идёт в обучение.
- Отметка «просто не нравится» — бирюзовая, флажок с ↻. Её можно перегенерировать, но в обучение она не идёт и подсказка об этом говорит прямо: «мне не понравилось» — не то, что детектор может измерить.
- Полосы не перехватывают мышь: клип под ними по-прежнему таскается, события ловят только флажок и две ручки на краях фразы.
- Кнопка-глаз прячет все отметки разом (запоминается): после проверки их на таймлайне десятки, и клипы под ними становится плохо видно.
| Действие | Что делает |
|---|---|
| ЛКМ по отметке | «это дефект» |
| ПКМ | «это не дефект» |
| Alt+клик | снять решение |
| двойной клик | проиграть фразу целиком |
| тащить ручку | подвинуть границу дефекта или фразы |
| Ctrl+перетаскивание по клипу озвучки | поставить свою отметку на этот отрезок |
Ручки есть и у самой полосы дефекта, а не только у фразы: именно её границы читает признаковый разбор, так что поставить их точно должно быть можно. Границы дефекта зажаты внутрь фразы — на этом инварианте стоит склейка.
Все времена дефектов — секунды исходного файла, и запись привязана к ассету. Клипы двигают, режут, дублируют, а ripple-правка сдвигает их пачкой: таймлайновое число протухло бы после первой же операции. Из привязки к файлу три вещи следуют даром: разрезание клипа не требует никакой сверки (каждая половина рисует свою часть), дублированная озвучка показывает свои дефекты дважды, а вырезанный кусок — не показывает вовсе.
Фраза — это одно или несколько предложений сценария вокруг дефекта (соседнее берётся, если между дефектом и краем предложения не больше одного слова). А сам разрез ищется по звуку: в зазоре между последним словом слева и первым справа берутся вероятности речи от Silero, внутри них — RMS окнами 5 мс, и точкой становится середина самого длинного по-настоящему тихого участка. Порог относительный, от шумовой полки файла.
Если тишины нет — берётся минимум RMS в зазоре; если зазора нет — середина, и фраза расширяется ещё на одно предложение, чтобы ненадёжный шов ушёл подальше от дефекта. На реальной 531-секундной озвучке: 169 из 176 швов попали в настоящую тишину, медиана −55.3 дБ против шумовой полки −49.1 дБ.
Всё подтверждённое по одной озвучке делается одним проходом. Это не оптимизация, а корректность: по одному пришлось бы каждый раз заново считать точки разреза в уже сдвинутом файле — целое семейство ошибок на миллисекунды, которого при пакетной склейке просто не существует. Заодно получается один новый файл, одна запись отмены и один повторный разбор.
Что происходит с каждой фразой:
- Текст берётся точной подстрокой сценария — с пунктуацией: без финальной точки модель читает фразу как незаконченную.
- Синтез с ±400 символами контекста вокруг (и с идентификаторами предыдущих запросов, если озвучка шла кусками) — это и делает интонацию совпадающей. Сид каждый раз новый: нужен другой дубль.
- Ответ проверяется на обрыв: все символы фразы должны присутствовать, внутренних пауз больше 0.7 с быть не должно.
- Кусок ускоряется коэффициентом самого файла, подрезается или
дополняется тишиной так, чтобы совпасть с тем, что он заменяет, и
выравнивается по уровню (EBU R128 на длинных, среднее по
volumedetectна коротких — интегральная громкость на двух секундах шумит). Разница больше ±6 дБ — предупреждение: это уже другой дубль, а не вопрос громкости. - Склейка — равномощным кроссфейдом (20 мс на чистом шве, 12 мс на ненадёжном). Линейный фейд дал бы провал в 3 дБ ровно посередине речи.
- Новая длина измеряется, а не вычисляется: ресэмплинг и ускорение врут на единицы миллисекунд.
- Всё, что начинается правее, сдвигается на разницу — по всем незалоченным дорожкам, иначе разъедется синхрон с картинкой.
Отдельно про отказы. Клип, граница которого попала внутрь заменяемой фразы, не чинится автоматически: честного ответа, куда должен уехать этот монтажный стык, нет. Такая ситуация называется вслух, и проект не трогается вовсе.
Повторная перегенерация той же фразы работает как ожидается: исправленный дефект принимает границы того, что было вставлено, поэтому вторая и третья попытка заменяют ровно свой кусок, а не съедают соседей.
Разбор описывает файл таким, каким его слушали, а каждая склейка файл переписывает. Поэтому сразу после склейки тайминги переносятся: снаружи заменённого куска сдвигаются, внутри интерполируются, а рядом с прогоном кладётся 16 кГц копия текущего звука — миллиметровый разрез надо искать в тишине того файла, который и будут резать. Исходный разбор при этом не трогается: он и есть обучающий корпус, и по нему же отмена перегенерации возвращает согласованное состояние.
Каждое ваше решение пишется в корпус прогона в формате детектора. Пользовательские отметки лежат в отдельном файле, и это не аккуратность: строка, которой не соответствует ни один кандидат, понижает совпадение, и когда таких больше половины — выбрасывается весь файл, вместе с настоящими решениями. Сессия с большим числом своих отметок доходит до этого легко.
Честно о том, что даёт разметка: подтверждения и отклонения поднимают точность. Ваша отметка учит модель только тогда, когда правила вообще породили кандидата на это место (пусть и похороненного ранжировщиком) — тогда у строки есть настоящие признаки. Отметки, на которые не сработало ни одно правило, считаются и показываются отдельно, но выучить по ним «признаков нет ⇒ дефект» означало бы получить модель, продвигающую пустышки.
Переобучение никогда не происходит само: модель пересобирается с нуля и общая с консольным детектором, поэтому старая копируется рядом с меткой времени, печатаются числа перекрёстной проверки, и всё это требует явного подтверждения. Меньше 30 примеров по хотя бы двум файлам — отказ. Кнопка сначала показывает, что получится, и только потом пишет.
После переобучения число примеров не меняется — меняется модель. Поэтому диалог показывает путь к файлу модели и время его записи: это и есть доказательство, что что-то произошло.
Каждый дубль — новый файл рядом. Кнопка уборки удаляет только те звенья цепочки, на которые проект больше не ссылается; исходная озвучка под правило не подпадает никогда. Решает это главный процесс: страница присылает только список нужных ей путей и не может назвать файл на удаление. Первый клик показывает список с предупреждением, второй удаляет — отмены у файловой системы нет.
kadr_voice_check, kadr_voice_mark, kadr_voice_verdict,
kadr_voice_regenerate (действует только на подтверждённое) и
kadr_voice_learn (по умолчанию только считает). Смотрите §27.
Программируемая анимация (React/TSX) как полноценный клип на таймлайне.
- Фрагмент = композиция Remotion. Код фрагмента лежит рядом с
проектом — в
<папка проекта>/kadr-fragments/<имя>-<id>/, поэтому проект переносится вместе со своей графикой. Общий workspace~/kadr-fragments(один node_modules на все проекты, ~150 МБ, ставится автоматически при первом использовании) держит на них символические ссылки: там живут только зависимости и служебные файлы. У несохранённого проекта фрагмент создаётся прямо в workspace и переезжает в папку проекта при первом сохранении; при открытии проекта на другой машине недостающие ссылки восстанавливаются автоматически. - На таймлайне — фиолетовый клип ⚛: двигается, режется, миксуется переходами, принимает эффекты и маски, как любой клип.
- Бывают прозрачными (титры/анимации поверх нижних слоёв — по умолчанию) и непрозрачными (самодостаточные сцены с фонами и звуком). Звук композиции слышен в превью и попадает в экспортный микс. Прозрачность сохраняется и в превью, и в экспорте — как у любого импортированного видео с альфа-каналом (см. §4).
- Создаются с fps = max(60, fps проекта) в размере проекта.
- iframe-оверлей (по умолчанию): страница с @remotion/player позиционируется поверх GL-канваса по трансформации клипа, синхронизирована с часами редактора (seek/play/pause/громкость). Нулевые накладные расходы; оверлей обрезается границами кадра превью. Dev-сервер vite даёт hot reload: правка кода композиции видна в превью через ~1–2 секунды. Никаких рендеров при итерациях.
- Захват пикселей (автоматически, когда на фрагменте есть GL-возможности — эффекты, 3D, маски, движение дорожки, любые переходы, перекрытия): невидимое offscreen-окно гонит кадры композиции (≤1280 px по ширине) прямо в компоновщик — фрагмент становится обычным GL-слоем, и всё (3D-перспектива, маски, переходы, сияние, порядок дорожек) работает живьём. Убрали эффект/3D — захват сам выключается, возвращается лёгкий iframe.
Порядок слоёв в превью. iframe лежат поверх GL-канваса, поэтому раньше непрозрачный фрагмент на нижней дорожке закрывал в превью все обычные клипы над ним (в экспорте, который компонуется на GPU, всё было верно). Теперь фрагмент, над которым в то же время лежит что-то, рисуемое на GL (видео, текст или фрагмент в режиме захвата), сам уходит в захват пикселей, а iframe выстраиваются снизу вверх — превью совпадает с экспортом.
Скорость превью. Проект с восемью тяжёлыми 3D-фрагментами раньше почти невозможно было смотреть, особенно на стыках сцен. Что изменилось:
- каждая страница фрагмента загружает только свой фрагмент — раньше каждая грузила все фрагменты рабочей папки (сотни), и одна сломанная ломала все;
- каждая страница работает в своём процессе: загрузка следующей сцены больше не замораживает ту, что играет;
- 3D рисуется по требованию и в размере показа: на паузе и в ожидающей странице — ноль отрисовок (было около сотни в секунду на каждую), при игре — одна на кадр;
- соседние клипы одного фрагмента, продолжающие друг друга, играют в одной странице, без перезагрузки на стыке.
Замер на том проекте: первый кадр следующего фрагмента — 42–76 мс вместо 2.3 с, худший провал на стыке — 42–76 мс вместо 0.5 с, память страницы — 62 МБ вместо 380.
Снимки тяжёлого 3D. Снимок ждёт, пока страница фрагмента действительно
нарисовала нужный кадр (а не только «перешла на него»), поэтому
kadr_snapshot и контакт-листы больше не возвращают пустое 3D.
Hot reload для фрагментов проекта. Код фрагмента сохранённого проекта лежит в его папке, а в workspace — только ссылка на неё. Наблюдатель файлов vite не следит за ссылкой, появившейся после старта сервера, поэтому правки во фрагменте, созданном «на ходу», раньше не доходили до превью до перезапуска редактора. Теперь сервер сам находит такие папки и передаёт их изменения в превью.
При экспорте каждый фрагмент рендерится remotion render-ом один
раз в полном качестве (кадры в PNG; прозрачные — VP9 с альфа-каналом,
непрозрачные — H.264) и подставляется как видеослой; дальше работает
обычный WYSIWYG-конвейер. Рендеры кэшируются по хешу содержимого папки
фрагмента: повторный экспорт без правок берёт готовый файл мгновенно.
Рендерятся только кадры, которые показывает монтаж (плюс полсекунды по
краям): если фильм собран из «окон» одной длинной композиции, каждое окно
больше не рендерится с самого начала фильма. На 26-минутном ролике это
93 тысячи кадров вместо 1,6 миллиона — часы вместо полутора суток. Готовый
полный рендер, если он уже есть на диске, используется как прежде.
Фрагменты с устаревшим запечённым звуком (§19) перед рендером
перезапекаются.
Рендер фрагмента идёт в две фазы — отрисовка кадров («Rendered») и сборка их в видео («Stitched»), — и прогресс показывает обе. Раньше вторая фаза не отражалась никак, и на тяжёлом прозрачном фрагменте экспорт минутами «стоял» на одном проценте. «Отмена» экспорта и закрытие редактора останавливают и рендер фрагмента, причём всё дерево процессов: Remotion запускает Chrome в отдельной группе процессов и на мягкий сигнал успевал поднять новый, который оставался висеть. Временные кадры рендера удаляются.
Чего избегать в прозрачном фрагменте: случайного шума, меняющегося на каждом кадре (плёночное зерно на весь кадр). Такие кадры не сжимаются совсем: на 120 кадрах — 119 МБ и 144 с против 3.6 МБ и 40 с без зерна, временные кадры доходили до 7.9 ГБ. Зерно лучше положить отдельной дорожкой — коротким зацикленным клипом с альфой: медиа длиннее своего источника в Kadr повторяется само.
~/kadr-fragments/ общий workspace (зависимости)
package.json remotion, @remotion/player, react, vite
player.tsx страница плеера (управляется редактором)
src/Root.tsx регистрация композиций для remotion render
src/fragments/
index.ts авто-генерируемый реестр
<имя>-<id> → символическая ссылка на папку в проекте
<папка проекта>/kadr-fragments/
<имя>-<id>/
index.tsx ← код композиции (правьте свободно)
meta.json размер/fps/длительность/прозрачность
Композиции пишутся на <Video> (не <OffthreadVideo>): нативный
компоновщик Remotion требует свежую glibc и есть не на всех системах, а
<Video> работает везде.
Правила: модуль экспортирует fragment = { component, meta };
длительность в meta.json держите в согласии с клипом; медиа для
композиции кладите в папку фрагмента и импортируйте
(import bg from './bg.jpg') — абсолютные пути не переживут финальную
сборку рендера.
У сохранённого проекта есть папка <папка проекта>/kadr-lib/ — общий код и
ресурсы для всех его фрагментов, без копирования в каждый:
<папка проекта>/kadr-lib/
film.tsx общий код (например, весь «фильм» как функция времени)
models/ 3D-модели проекта (§25, «3D-модели»)
media/ видео, подготовленное для фрагментов
fonts/ шрифты — подключаются сами, имя семейства = имя файла
Во фрагменте: import { Film } from '@lib/film', import clip from '@lib/media/clip.mp4'. Правка в kadr-lib перезагружает превью всех
фрагментов проекта и заставляет их перерендериться при экспорте. Шрифты
из kadr-lib/fonts (Inter-700.woff2 → Inter 700) регистрирует сам
редактор — и в превью, и в рендере, — поэтому они не теряются, когда
компонент, который их грузил, размонтируется.
Модули Kadr для фрагментов: @kadr/runtime (шрифты, объявления для
проверки, параметры) и @kadr/three (3D-кит). Проверка типов одного
фрагмента — kadr_typecheck: только его ошибки, с правильными типами
three.js и @lib.
Всё, что подбирается на глаз (ракурс, задержка, размер, цвет), можно вынести в ползунки:
import { defineParams, useParams } from '@kadr/runtime'
const P = defineParams({
az: { value: -35, min: -180, max: 180, step: 1, label: 'Азимут' },
glow: { value: '#9c7ad8', label: 'Подсветка' },
grid: { value: true, label: 'Сетка' }
})
const Film = () => { const p = useParams(P); /* p.az, p.glow, p.grid */ }У выделенного клипа фрагмента в Инспекторе появляется секция «Параметры
фрагмента»: ползунки, цвет, переключатели. Превью следует за ними сразу,
без перезагрузки; отпущенное значение сохраняется в params.json папки
фрагмента, который читает и рендер — экспортируется то, что выставлено.
Файл можно править и руками: превью подхватит, ваша правка не затрётся.
«Сбросить» возвращает значения из кода.
Кнопка «Подготовить для фрагмента» на плитке видео в корзине (и
kadr_fragment_media) делает копию в kadr-lib/media: развёрнутую по
метаданным, в SDR, H.264 с ключевым кадром каждые 30 кадров (фрагмент
перематывается постоянно, а у телефонного видео ключевые кадры редки) и не
больше размера проекта. Строка импорта копируется в буфер.
Кнопка «Проверка» в тулбаре таймлайна (и kadr_check) проверяет
фрагменты по тому, что они сами о себе объявляют:
import { defineInspect } from '@kadr/runtime'
export const fragment = { component: Film, meta, inspect: defineInspect({
events: [{ t: 2.0, kind: 'big', label: 'сборка' }],
texts: [{ from: 2.3, to: 4.6, text: 'Ось шарнира', role: 'title', box: [110, 150, 520, 110] }],
camera: (t) => cam(t),
continuous: true
}) }| Проверка | Правило |
|---|---|
| события и ритм | крупное событие — на «раз» (±40 мс), любое — не мимо доли, ничего в паузах |
| время чтения | 1–3 слова ≥ 0.8 с, длиннее ≥ max(1.2 с, 0.3 с/слово), подзаголовок +0.7 с |
| текст | читаемый текст не движется (> 20 px/с), одна главная надпись за раз, без перекрытий |
| контраст | по реальным пикселям кадра: заголовки ≥ 3:1, остальное ≥ 4.5:1 |
| стыки | соседние окна одного «фильма» (continuous) склеиваются незаметно |
| камера | нет ступенек скорости, скачков и дрожания |
| пересечения | детали 3D-кита не проходят друг сквозь друга |
Результат — список с переходом к месту на таймлайне; под дорожкой фрагмента видны объявленные события и отмеченные проблемы. Контраст, стыки и пересечения рендерят кадры и включаются галочками.
Файлы STL, 3MF, STEP, OBJ и GLB/glTF импортируются в kadr-lib/models
(kadr_model_import) и появляются в корзине плиткой с миниатюрой и
размерами в миллиметрах. 3MF читается так, как его собирает слайсер —
с позициями деталей, компонентами из других файлов пакета и единицами
(без этого модель в 150 мм выходила размером в 2 мм). Ось Z из CAD
становится Y, тяжёлые сетки упрощаются до 200 тыс. треугольников, у каждой
детали есть размеры и ориентированная коробка. «Вставить как
3D-фрагмент» (или двойной клик по плитке) создаёт фрагмент с моделью на
вращающейся камере — отправная точка.
3D-кит @kadr/three: useModel (модель по импорту, 1 единица = 10 см),
студийный свет, единая камера по ключам (монотонный сплайн без рывков и
остановок), деталь с «слоем печати», контуром и рентгеном, выноски с
неподвижным текстом и линией к точке модели, выноски разнесённого вида и
переход «чертёж → реальность» в портретное видео.
Кнопка в транспорте кладёт кадр видеоклипа полупрозрачно поверх превью — над фрагментами тоже. Нужна, чтобы совместить 3D-камеру со съёмкой: без неё приходилось переключать дорожки и запоминать картинку. Берётся выделенный видеоклип, иначе тот, что под плейхедом; выделение фрагмента (чтобы крутить его ползунки) её не сбивает. Ползунок — прозрачность, режим «разница» показывает |превью − съёмка| (где совпало — черно). В снимки и экспорт не попадает.
- через встроенного Claude (основной путь, §26–27);
- программно:
kadrEditor.createFragment({ name, start, end, transparent }); - авто-субтитры создают фрагмент сами (§22).
Клип ложится на верхнюю свободную видеодорожку, но не ниже дорожки, где в этом месте уже что-то есть — иначе титры оказались бы под видео; если такой нет, создаётся новая дорожка сверху.
Кнопка «Волна» в панели таймлайна (активна при выделенном диапазоне — Shift+drag) генерирует фрагмент со светящейся неоновой линией, которая «дышит» громкостью звука: частота и высота изгибов следуют за огибающей громкости (тот же алгоритм, что у «Bake Sound to F-Curves» в Blender: атака 5 мс, спад 200 мс). В диалоге выбирается источник звука — весь микс диапазона или одна аудиодорожка — и три ручки: амплитуда, свечение, скорость.
- Клип непрозрачный (чёрный фон), размера проекта, ≥60 fps; ложится на свободную видеодорожку ровно на диапазон и сразу живёт в превью.
- Вид: бегущая синусоида в статичном «окне», градиент синий→пурпур по высоте (B-сплайн-рампа), свечение и лучи (Glare Streaks), хроматическая дисперсия и линзовое искажение — финальный проход честно повторяет формулу Lens Distortion из компоузера Blender на WebGL-шейдере.
- Тонкая настройка — в
index.tsxфрагмента: объектSхранит все параметры стиля, массивENV— громкость по кадрам. Превью перезагружается горячо; после изменения звука под клипом волну нужно сгенерировать заново (громкость запечена). - Программно:
kadrEditor.neonWave({ range, source, style? }); у встроенного Claude есть инструментkadr_neon_wave.
Кнопка «Claude» в топбаре открывает терминал (xterm) с настоящим интерактивным Claude Code, подключённым к открытому проекту.
- запускается ваш CLI
claudeв PTY — полный интерактивный TUI, как в обычном терминале; авторизация берётся из~/.claude, отдельный вход не нужен; - если Claude ходит в сеть через прокси — задайте его в
~/.config/kadr/claude-env.json({ "env": { "HTTPS_PROXY": "..." } }), не забывNO_PROXY=localhostдля локального MCP-моста; - при первом запуске Claude спросит «Do you trust this folder?» — Enter;
- рабочая папка — папка
.kadr-файла (или домашняя); - повторное нажатие кнопки или ✕ — сессия и мост убиваются; открытие панели всегда даёт ровно одну сессию, даже если панель быстро закрыть и открыть снова: запуск и остановка выполняются строго по очереди, а вывод «чужого» процесса в терминал попасть не может;
- мост между Claude и редактором защищён: он живёт только пока
открыта панель, слушает исключительно
127.0.0.1и требует секрет сессии в заголовке запроса, а запросы с признаком браузерной страницы отклоняет. Через этот мост исполняется произвольный код в редакторе, а редактор умеет писать файлы — поэтому доступ к нему есть только у вашего Claude, но не у других программ на машине и не у открытой веб-страницы; - окно панели перетаскивается за заголовок и растягивается за края и нижние углы; позиция и размер запоминаются между запусками;
- переопределение запуска:
~/.config/kadr/claude-env.json—{ "command": "...", "args": [...], "env": {...} }.
Через MCP-сервер kadr (подключается автоматически, не заменяя ваши
собственные MCP-серверы):
- читает весь проект: дорожки, клипы, тайминги, пути всех медиафайлов, транскрипты;
- выполняет любые операции редактора (с undo-метками);
- запускает экспорт и транскрипцию, создаёт Remotion-фрагменты;
- плюс обычные инструменты Claude Code: файлы, Bash (ffmpeg/ffprobe доступны), ваши другие MCP.
Вместе с редактором устанавливаются навыки Claude (в
~/.claude/skills/), и они составные: kadr-editor — основа (как
смотреть, править и проверять, интерфейс, фрагменты, озвучка), а
kadr-music (есть музыка), kadr-motion (титры, субтитры, графика) и
kadr-3d (модели, продукт, механизм) подключаются по типу проекта — часто
вместе. Правила в них — умолчания, а не законы: ваши слова важнее. Главные
из них выросли из реальной работы: перед большой сборкой — вопросы о стиле,
ритме, количестве текста и звуке и раскадровка из опорных кадров; без
шаблонных приёмов (HUD, неон, вспышки, тряска, пульсация) без просьбы;
многосценовый ролик — один «фильм» как функция времени; не экспортировать
без просьбы. Навыки, которые Kadr больше не поставляет, удаляются; ваши
собственные kadr-* без его отметки — никогда.
- «Что сейчас на таймлайне?»
- «Отрендери все куски аудио в mp3, где нет видео, и положи в отдельную папку.»
- «Сделай на выделенном диапазоне анимированную заставку с названием канала.» — создаст фрагмент и будет править его код по вашим правкам, изменения видны в превью через секунды.
- «Перенарежь субтитры по 2 слова и сделай их жёлтыми.»
- «Поставь кроссфейды по 0.5 с между всеми клипами на V1.»
Полный список инструментов сервера kadr:
Снимок живого состояния: проект целиком (дорожки → клипы со всеми параметрами; ассеты с абсолютными путями; texts — транскрипты с путями к файлам), путь проекта, выделение, плейхед, доступные пресеты экспорта.
Выполнить JavaScript в странице редактора (тело async-функции,
return — результат). Доступно всё API window.kadrEditor (§31): store
с действиями (pushHistory, updateClip, insertClipFromAsset,
splitAtPlayhead, setTransition…), probeMedia, чтение/запись
проектов. Документация по API встроена в описание инструмента.
Отрендерить проект (или диапазон) и дождаться завершения: outputPath, presetId, start/end, motionBlur, frameBlending. Тот же WYSIWYG-конвейер, что и кнопка «Экспорт».
Распознать речь: либо весь медиафайл (assetId), либо диапазон
таймлайна (start+end); модель, язык, режим таймкодов, слов в
реплике. Пишет SRT+TXT рядом с исходником, регистрирует в проекте,
возвращает пути и превью реплик. Файлы Claude может читать и править
напрямую — панель субтитров подхватит.
Создать Remotion-фрагмент на [start, end): имя, прозрачность.
Возвращает id, путь к TSX и URL живого плеера. Дальше Claude правит файл
обычными инструментами — превью обновляется горячо; рендер один, при
экспорте.
Снять текущий кадр в PNG — «глаза» ассистента. Кадр берётся из того же компоновщика, что и экспорт, в разрешении проекта, а на время снимка превью переключается на оригиналы вместо 540p-прокси и прогоняет все фрагменты через попиксельный захват: на снимке будет ровно то, что уйдёт в рендер, а не приблизительно похожая картинка.
| Инструмент | Что делает |
|---|---|
kadr_sheet |
контакт-лист: много кадров одной картинкой с подписями времени (и такта) |
kadr_check |
проверка фрагментов (§25, «Проверка ролика»); pixels и collisions — по желанию |
kadr_typecheck |
проверка типов одного фрагмента с @lib и @kadr |
kadr_model_import |
импорт 3D-файлов в kadr-lib/models, по желанию — сразу фрагмент |
kadr_models |
модели проекта: имена, размеры, детали |
kadr_fragment_media |
подготовить видео для <Video> во фрагменте |
| Инструмент | Что делает |
|---|---|
kadr_voice_speak |
синтезировать текст и положить клип на таймлайн (§23) |
kadr_voice_check |
прогнать детектор дефектов по озвучке (§24) |
kadr_voice_mark |
поставить свою отметку на отрезок |
kadr_voice_verdict |
вынести решение по найденному месту |
kadr_voice_regenerate |
перегенерировать только подтверждённые фразы |
kadr_voice_learn |
посчитать корпус; переобучение — только по явному подтверждению |
Правило «регенерация действует только на подтверждённое» — не формальность: она тратит платные запросы и переписывает файл, поэтому решение остаётся за вами, а не за моделью.
Готовая аудио-реактивная «неоновая волна» по громкости диапазона
(start, end, опционально trackId — только одна дорожка): создаёт
фрагмент, возвращает id, клип и путь к TSX для перестилизации (§25).
| Инструмент | Что делает |
|---|---|
kadr_beats |
карта музыки: доли, размер и «раз», такты, разделы, паузы, смещение бочки — метками на таймлайне (§19) |
kadr_audio_react |
запечь звук под фрагментом, чтобы он двигался в музыку |
kadr_sounds |
найти эффект или музыку в библиотеке: по назначению, мягкости, своим звукам |
kadr_sound_add |
поставить звук на таймлайн так, что на долю встаёт его удар |
kadr_sound_label |
подписать свой звук: для чего он, теги, заметка (переживает повторный разбор) |
kadr_fragment_create запекает звук сразу, так что свежий фрагмент может
двигаться в музыку без отдельного шага. Правила, по которым встроенный
Claude монтирует под музыку по умолчанию (крючок в первые секунды, время
на чтение текста, текст — на каждую 2-ю или 4-ю долю, удар звука — точно
на долю, уровни эффектов под музыкой, вкус в реакции на звук), записаны в
его навыке и действуют без отдельной просьбы.
Кнопка «Экспорт» в топбаре.
Исходники с поворотом в метаданных или в HDR идут в экспорт через промежуточный файл ffmpeg (быстрый декодер браузера не знает ни того, ни другого). Прозрачные фрагменты сжимаются VP9 с построчной многопоточностью — быстрее при том же качестве.
| Пресет | Контейнер | Видео | Примечание |
|---|---|---|---|
| YouTube 1080p | MP4 | H.264 1920×1080 | поток WebCodecs без перекодирования |
| YouTube 4K | MP4 | H.264 3840×2160 | |
| Shorts/Reels 1080×1920 | MP4 | H.264 вертикальный | |
| 720p | MP4 | H.264 1280×720 | |
| Project size | MP4 | H.264, размер проекта | универсальный |
| WebM VP9 | WebM | VP9 (перекодирование) | |
| MP3 | MP3 | только аудио | рендер видео пропускается |
Если на таймлайне выделен диапазон (Shift+драг по линейке) — рендерится только он; без диапазона — весь проект.
- Размытие движения (по умолчанию вкл.) — §29.
- Frame Blending (по умолчанию вкл.) — §29.
- Рендер Remotion-фрагментов — если есть; один раз на фрагмент, с кэшем по содержимому.
- Рендер видео — офлайн-проход тем же GL-компоновщиком, что и превью: кадры уходят в ffmpeg x264 с битрейтом пресета (или, по галочке «Быстрый кодировщик», в WebCodecs) и пишутся во временный MP4.
- Аудио и мастеринг — ffmpeg микширует звук по сегментам, пропускает микс через мастер-лимитер на −1 dBFS (§19) и муксует/перекодирует в финальный контейнер по пресету.
Экспорт можно отменить на любой фазе — отмена останавливает и рендер
Remotion-фрагмента, если он идёт. Одновременно идёт только один
экспорт: кодировщик видео у приложения один, и второй экспорт,
запущенный рядом (например, скриптом через window.kadrEditor или
встроенным Claude, пока открыт диалог), писал свои кадры в чужой
кодировщик — оба падали в самом конце. Теперь второй сразу отказывается с
понятным сообщением. Диалог сохранения помнит последнюю
папку экспорта. По окончании рендера играет короткий сигнал — понятно
из другого конца комнаты, что длительный процесс закончился.
Быстрый путь декодирования: mp4box-демультиплексация + WebCodecs-декодер
на клип, последовательное чтение с упреждением — ~8× быстрее
покадровых перемоток. Медленный путь (перемотка <video> покадрово) стоит
около 0.2 секунды на кадр, поэтому редактор старается не попадать на
него никогда:
| Исходник | Как читается |
|---|---|
| Обычный MP4/MOV (H.264, VP8/VP9, AV1) | быстрый путь напрямую |
| MP4 с индексом (moov) в конце — типичная запись экрана и экспорт без faststart | подхватывается «хвост» файла, дальше быстрый путь |
| Видео с альфа-каналом (VP9+alpha WebM, ProRes 4444, HEVC-alpha) — в том числе все прозрачные Remotion-фрагменты | один раз строится упакованный промежуточный файл (цвет + альфа-матовый канал в одном H.264, без потерь), дальше быстрый путь |
| Кодеки, которые Chromium не умеет (HEVC без VAAPI, mpeg4, ProRes) | один раз строится H.264-посредник, дальше быстрый путь |
| Всё остальное (битый файл, экзотика) | откат на покадровую перемотку: медленно, но никогда не ломается |
Промежуточные файлы кэшируются в userData/decoded по содержимому
исходника; папка сама подрезается, когда переваливает за 10 ГБ.
Замер на реальном проекте (11 минут, 1080p60, почти сплошь прозрачные Remotion-фрагменты): экспорт целиком 13 минут вместо нескольких часов, в среднем 58 кадров/с с включёнными Motion Blur и Frame Blending.
Превью и экспорт — один код рисования: одинаковые трансформации, маски, эффекты, переходы, цветовые матрицы (untagged-потоки приводятся к той же эвристике, что у превью: HD→BT.709, SD→BT.601). Что видите — то и получите.
Галочка в диалоге экспорта (по умолчанию включена):
- 180°-затвор: каждый кадр — среднее 8 подкадров, распределённых по половине кадрового интервала;
- между подкадрами движутся трансформации, маски, движение дорожки, переходы — быстрые анимации получают киношный смаз вместо стробоскопа;
- декодирование не дорожает: подкадры переиспользуют кадры видео.
Галочка в диалоге экспорта (по умолчанию включена):
- проблема: исходник 25 fps в проекте 60 fps повторяет кадры неравномерно (2-3-2-3) — движение внутри клипа пульсирует;
- решение: соседние кадры источника смешиваются пропорционально точной фазе времени — движение контента становится равномерным; помогает и замедленным клипам;
- включается только там, где нужно (скорость·fps исходника < fps проекта): совпадающие и более быстрые источники не трогаются вообще — проверено бит-в-бит.
Часы воспроизведения «якорные»: время проецируется от точки старта по vsync-меткам кадров, дрожание таймера не накапливается — движение в превью равномерное.
- Прокси 540p для тяжёлых исходников в превью (§5).
- Пауза почти бесплатна: без изменений превью перерисовывается ~4 раза в секунду вместо 60 (загрузка текстур видео не бесплатна).
- GL-текстуры кэшируются по клипам; неиспользуемые выгружаются.
- Захват фрагментов ограничен 1280 px по ширине и включается только при необходимости (§25).
- Экспорт не трогает аудио-двойники видеоклипов (звук идёт из ffmpeg-микса) и декодирует каждый кадр ровно один раз.
- Рендеры фрагментов и прокси строятся очередями по одному — слабые CPU не захлёбываются.
- Аппаратный энкодер (VAAPI) используется автоматически, если Chromium его поддерживает; иначе — программный.
- Motion Blur не тратится впустую: если внутри «затвора» кадра ничего не движется (нет ключевых кадров, фейдов, переходов и анимации эффектов — то есть на большей части готового монтажа), 8 подкадров дали бы пиксель в пиксель одно и то же, и редактор рисует их один раз. Картинка не меняется — проверяется хэшем каждого отрисованного кадра.
- Выгрузка кадра из GPU идёт конвейером (pixel-pack buffer): пока считывается предыдущий кадр, GPU уже рисует следующий.
- Альфа-видео больше не тормозит экспорт: раньше каждый его кадр стоил
~0.2 с (перемотка
<video>), теперь ~1 мс — см. таблицу в §28. - Длинные проекты не «устают» к концу. Превью держало медиаэлемент для каждого клипа, до которого доходил плейхед, и навсегда подключало его к звуковому графу. На проекте в 19 минут с 1080 звуковыми клипами к концу их набиралось больше тысячи, кадр превью вырастал с 7 до 23 мс, и звук начинал запинаться: сначала изредка, к концу — чаще раза в секунду. Теперь элементы держатся только для клипов рядом с плейхедом и отключаются от графа, когда уходят. Тот же проект целиком: 7 запинок вместо 169, не больше 15 элементов вместо 1082.
- Таймлайн большого проекта. Рисуются только клипы рядом с видимой
частью (и выделенные); клип шириной в несколько пикселей — одним
элементом; при прокрутке перерисовываются только клипы на краях;
положение и ширина клипов — одна CSS-переменная масштаба; зум —
растягиванием во время жеста (§6). Волновая форма читает для пикселя два
заранее посчитанных максимума вместо сотен значений — а картинка
совпадает со старой попиксельно (
node scripts/check-timeline.mjs). - Фрагменты в превью — см. §25, «Скорость превью».
window.kadrEditor — публичная поверхность для скриптов, тестов и MCP:
| Поле | Что это |
|---|---|
useEditor |
zustand-store: getState() → проект, выделение, плейхед и все действия (см. ниже) |
useSettings |
язык, высота дорожек |
usePosePresets / useFxPresets |
пресеты поз и эффектов |
PRESETS |
пресеты экспорта |
startExport(project, preset, path, onProgress, range?, opts?) |
экспорт |
transcribe(opts) |
транскрипция (asset/range, модель, язык, таймкоды, maxWords) |
parseSrt / cuesToSrt / segmentsToCues / docTimeToProject |
работа с субтитрами |
createFragment / ensureFragmentServer |
Remotion-фрагменты |
autoCaptions(opts) / captionsTsx(cues, style) |
авто-субтитры |
neonWave(opts) / neonWaveTsx / NEON_WAVE_DEFAULTS |
неоновая волна по громкости диапазона |
autosaveNow() / activity |
автосейв: ручной тик и флаги занятости |
openProject(path) |
открыть проект (со ссылками фрагментов) |
contactSheet({ times, cols?, width? }) |
контакт-лист кадров одним PNG |
runChecks({ clipIds?, pixels?, collisions? }) |
проверка фрагментов (§25) |
importModels(paths, opts?) / insertModelFragment(name) |
3D-модели проекта |
prepareForFragment(assetId) |
видео для <Video> во фрагменте |
setParam(fragmentId, name, value) / resetParams(fragmentId) |
параметры фрагмента |
setOnion(on) / useOnion |
луковая кожура |
previewPoolStats() / audioStats() / silencePreview(on) |
здоровье превью: элементы, перемотки, расхождение, узлы звукового графа; тихий режим для замеров |
projectDuration(project) / evalAnim(anim, t) / uid() |
утилиты |
Ключевые действия store (useEditor.getState()):
pushHistory(labelKey)— один раз перед дискретной правкой низкоуровневыми сеттерами (высокоуровневые —addTrack,insertClipFromAsset,splitAtPlayhead,deleteSelection,addTexts,insertFragmentClip— кладут историю сами);updateClip(id, patch),setClipDuration,setClipSpeed;insertClipFromAsset(assetId, trackId|null, atSec),addAsset;addTrack(kind),addTrackNear(trackId);select(ids),setPlayhead(t),setRange({start,end}|null);splitAtPlayhead(),deleteSelection(),copySelection(),pasteAtPlayhead();setTransition(clipId, type|null)— переход наложения;setEdgeTransitions(...)— торцевые переходы;addMarker(t)/moveMarker(id, t)/removeMarker(id)— маркеры таймлайна (§6);setProject(project, path?)— загрузить проект целиком.
window.kadr — IPC-мост к main-процессу: probeMedia, readProject /
writeProject / autosaveProject, readTextFile / writeTextFile /
statFile, transcribe, fragment*, claude*, экспортные вызовы.
Все времена везде — секунды. tracks[0] — верхняя видеодорожка.
| Путь | Содержимое |
|---|---|
<папка проекта>/имя.kadr |
проект (JSON) |
<папка проекта>/имя.autosave.kadr |
автосохранение (перезаписывается) |
<рядом с медиа>/имя.srt, имя.txt |
транскрипты |
~/.config/kadr/pose-presets.json |
пресеты поз |
~/.config/kadr/fx-presets.json |
пресеты эффектов |
~/.config/kadr/last-dirs.json |
последние папки диалогов |
~/.config/kadr/claude-env.json |
переопределение запуска Claude (опц.) |
~/.config/kadr/tts-settings.json |
настройки озвучки (без ключа) |
~/.config/kadr/elevenlabs-key.json |
ключ ElevenLabs, права 0600, читает только главный процесс |
~/.config/kadr/recent-projects.json |
недавние проекты (нужны панели хранилища) |
~/.config/kadr/proxies/ |
кэш превью-прокси |
~/.config/kadr/fragment-renders/ |
кэш рендеров фрагментов |
~/.config/kadr/decoded/ |
промежуточные файлы для быстрого декода (лимит 10 ГБ) |
~/.config/kadr/reversed/ |
отрендеренные реверсы клипов |
~/.config/kadr/imported/ |
скачанное и вставленное из буфера |
~/.config/kadr/ttsqc-runs/ |
прогоны детектора дефектов и корпус разметки |
~/.config/kadr/sfx/<семейство>/ |
ваши собственные звуки для библиотеки «Звуки» |
~/.config/kadr/sfx/kadr-sfx.json |
их разбор (разметка, удар), пересчитывается при изменении файла |
<папка фрагмента>/audio.json, audio.ts |
запечённый звук под фрагментом (§19) |
<программа>/resources/ |
встроенные звуки и музыка, лицензии — resources/CREDITS.md |
~/.cache/kadr/ttsqc/ |
кэш декодированного звука детектора (~3.8 МБ на минуту) |
~/kadr-fragments/ |
workspace Remotion-композиций (ссылки на папки проектов) |
<папка проекта>/kadr-fragments/ |
исходники фрагментов этого проекта |
<папка проекта>/kadr-lib/ |
общий код, модели, медиа и шрифты фрагментов проекта (§25) |
<папка фрагмента>/params.json |
значения параметров фрагмента (§25) |
~/.config/kadr/luts/ |
3D-LUT для перевода HDR в SDR |
~/.config/kadr/gpu.json |
выбор видеокарты |
/tmp/kadr-export-*.mp4 |
временные файлы экспорта (удаляются) |
Медиа отдаётся странице редактора по внутреннему протоколу kadr://, и
каждая такая ссылка подписана одноразовым ключом текущего запуска. Это
важно из-за Remotion-фрагментов: их код (написанный руками, ассистентом
или приехавший внутри чужого проекта) исполняется в отдельной песочнице
и без такого ключа мог бы прочитать через этот протокол любой файл,
доступный вам. Ключ живёт только внутри редактора, песочница его не
видит. На работу с медиа это никак не влияет — ссылки строит сам
редактор.
Кнопка в топбаре показывает, сколько всего этого накопилось, и делит по одной-единственной границе — восстановимо или нет:
- Восстановимое — прокси, промежуточные файлы декода, рендеры фрагментов, кэш детектора. Их имя вычисляется из исходника (хеш пути, размера и времени правки), поэтому удаление стоит только времени: то же имя получится снова, и проект, который на него смотрит, найдёт файл обратно. Чистится точечно — по типу данных и по проекту.
- Невосстановимое — реверсы клипов, скачанные файлы, озвучки. Они записаны в проекте по пути и второй раз не выводятся ниоткуда, поэтому панель их считает и показывает, кому они принадлежат, но одной весёлой кнопкой не удаляет.
Принадлежность считается заново из путей известных проектов, а сами проекты различаются по пути, а не по имени: у всех нас половина проектов называется «Untitled».
Страница не может назвать файл на удаление: она присылает только группу и область, а главный процесс сам пересканирует и решит, какие это файлы. И ничего не удаляется без явного подтверждения — запрос без него только считает.
Обещание, ради которого всё это писалось: удалите прокси, откройте проект через год — он подхватится сам. Редактор проверяет запомненный прокси на диске, забывает пропавший и строит его заново, а клип тем временем играет из оригинала.
Кэши можно безболезненно чистить: прокси и рендеры фрагментов перестроятся при необходимости.
Все кэши пишутся атомарно: сборка идёт в файл ….part.<ext> и
переименовывается в итоговое имя только при успехе. Поэтому файл с
итоговым именем всегда означает «готов», а прерванная сборка (закрыли
редактор, упал процесс) не может подсунуть следующему экспорту обрезок.
Оставшиеся .part-файлы удаляются при следующем запуске редактора.
Превью почернело, а в углу надпись про видеоконтекст — видеокарта отобрала у редактора контекст (сброс драйвера, другая программа заняла всю видеопамять). Редактор запрашивает его обратно сам и восстанавливает картинку за доли секунды; если надпись не уходит — перезапустите Kadr. Экспорт в такой ситуации не молчит: он прерывается с ошибкой, а не записывает чёрный файл.
Превью дёргается на тяжёлом видео — дождитесь постройки прокси (бейдж ⚙ на карточке), оно включится само.
Готовый файл «дёргается» при просмотре, а превью плавное — почти
наверняка ваш плеер не вытягивает программный декод 1080p60. Проверьте
файл на другом устройстве или плеером с аппаратным декодом
(mpv --hwdec=vaapi). Сам файл равномерный — тайминги и движение
проверены инструментально.
В рендере «нет» эффекта/перехода — проверьте, тот ли файл вы открыли: типичный случай — просмотр старого рендера из другой папки. Диалог экспорта показывает, куда пишет.
Whisper придумал текст в тишине/музыке — включены все фильтры, но на экзотике возможно: перегенерируйте с явным языком вместо «авто» или моделью large-v3; правьте реплики в панели субтитров.
Фрагмент показывает «unknown composition» — клип ссылается на
удалённую композицию: удалите клип или восстановите папку фрагмента в
~/kadr-fragments/src/fragments/.
Claude не запускается в панели — проверьте, что CLI claude
работает в обычном терминале; нестандартный путь/окружение задаётся в
~/.config/kadr/claude-env.json.
Экспорт упал на конкретном файле — экспорт сам откатывается на
медленный надёжный путь декодирования; если файл совсем битый —
переконвертируйте его (ffmpeg -i in -c copy out.mp4).
Порт 5621 занят — это dev-сервер фрагментов; живой сервер от
предыдущего запуска переиспользуется автоматически, осиротевший —
убивается сторожем. Вручную: pkill -f kadr-fragments.
| Эффект | Описание |
|---|---|
| Без перехода | жёсткая склейка в точке начала второго клипа |
| Кроссфейд | плавное растворение A в B (по умолчанию) |
| Через чёрное | A гаснет в чёрный, из чёрного появляется B |
| Шторка влево / вправо / вверх / вниз | граница-шторка с мягкой кромкой |
| Круг — раскрытие | B раскрывается кругом из центра |
| Круг — закрытие | A схлопывается кругом |
| Сдвиг влево / вправо | кадры уезжают как слайды |
| Растворение | шумовое растворение (плёночное зерно границы) |
| Пикселизация | мозаика укрупняется на A и собирается в B |
| Наезд (зум) | A наезжает с размытием, B выезжает |
| Радиальный | развёртка по углу, как стрелка часов |
| Эффект | Характер |
|---|---|
| Зум-блюр · наезд | экспоненциальный наезд со спектральным размытием и вспышкой экспозиции |
| Зум-блюр · отъезд | то же в обратную сторону |
| RGB-расхождение | каналы разъезжаются с веерным размытием |
| Вип-пан влево/вправо/вверх/вниз | хлёсткий бросок камеры по параболе с наклоном и смазом (1.45 экрана пути) |
| Вращение с размытием | рывок поворота с радиальным смазом |
| Засветка (вспышка) | пересвет в белое с растеканием света |
| Глитч | цифровой сбой: RGB-сдвиги, полосы, дрожь |
| Упругое растяжение | кадр тянется как резина и отщёлкивается |
| Линзовое искажение | волна «линзы» прокатывается по кадру |
Все торцевые эффекты проходят через квартическую кривую с пиком скорости в точке склейки и виньетку; основные — со спектральным (RGB) расщеплением вдоль направления движения.
Project {
name, width, height, fps, background
tracks: Track[] // tracks[0] — верхняя видеодорожка
assets: MediaAsset[] // импортированные файлы (пути, метаданные)
texts: TextDoc[] // транскрипты/субтитры (ссылки на файлы)
}
Track {
kind: 'video' | 'audio'
name, muted, locked, gain // gain видео = непрозрачность слоя
motion?: Transform3D // 🌐 движение всей дорожки (анимируемое)
clips: Clip[]
}
Clip {
kind: 'media' | 'text' | 'remotion'
assetId? | text+textStyle? | fragmentId+fragmentMeta?
start, duration, inPoint, speed // секунды; duration сверх исходника = луп
fadeIn?, fadeOut?
gain: Anim, muted
transform: { x, y, scale, rotation, opacity, rotX?, rotY?, z? } // все Anim
mask?: { left, top, right, bottom } // кромки, Anim
maskShapes?: MaskShape[] // до 8 фигур
effects: Effect[] // glow и будущие
transitionIn?, transitionOut?: { type, duration } // duration 0 = наложение
linkId? // связка видео+аудио
}
Anim { value: number, keyframes?: { time, value, easing }[] }- Все времена — секунды; времена ключей — от начала клипа; движение дорожки — в абсолютном времени проекта.
transitionInсduration > 0— торцевой переход; сduration = 0— тип смешивания для зоны наложения.- Эффект:
{ id, type: 'glow', enabled, params }.
Документ соответствует состоянию редактора на момент коммита, в котором
он добавлен. История изменений — в git log.