Product Launch Motion — навык для Claude Code, который снимает промо-ролики продукта кодом

· 8 мин чтения
skills claude-code video-generation animation ffmpeg
📂 Исходный код на GitHub

Навык для Claude Code, который делает промо-ролики уровня Dribbble из кода: один элемент без монтажных склеек, пружинная анимация, курсор, который управляет всеми изменениями, звуки под биты и 60 fps. Вторая версия рассчитана на Claude Opus 5.5.

Product Launch Motion — навык для Claude Code, который снимает промо-ролики продукта кодом

Product Launch Motion — это навык для Claude Code, который делает промо-ролик продукта из кода. Вы ставите навык, показываете Claude Code свой продукт и говорите: «Сними ролик запуска для моего продукта example.com. Ты режиссёр». Дальше навык сам придумывает сцены, собирает их в один HTML-файл и рендерит ролик в MP4.

Главная идея простая и необычная: ролик не монтируют из готовых кусочков. Каждый кадр считается из времени. Один и тот же элемент меняет форму, размер и цвет и перетекает из сцены в сцену — без единой монтажной склейки. Музыка идёт первой: сетку битов измеряют заранее, а каждый звук интерфейса синтезируют и ставят на его собственную измеренную вершину удара. На выходе — 60 fps с настоящим размытием движения.

Демо-ролик длиной 27 секунд сделан для cheerful.ai. Ни After Effects, ни готовых шаблонов, ни нейросетей для видео. Его можно скачать в 1080p и 60 fps со звуком. Вторая версия ролика сделана с WebGL-стеклом: прозрачные объёмные фигуры плывут сквозь все сцены.

Установка и первый запрос

npx skills add AbubakrChan/product-launch-motion

После установки достаточно одного запроса:

Сделай ролик запуска для моего продукта на example.com. Ты режиссёр.

Вторая версия навыка перебрана на более простом стеке и рассчитана на Claude Opus 5.5. Модели поменьше правила соблюдают, но упускают детали.

Семь правил, из-за которых ролик выглядит дорого

Каждое правило выросло из замечаний при проверке настоящего ролика. Все промпты и заметки лежат дословно в references/prompts.md.

  1. Один элемент, без склеек. Каждое состояние — это тот же самый элемент, который меняет размер, скругление и цвет. Переходы бывают трёх видов: превращение формы, движение камеры или наезд камеры в элемент, который становится следующей сценой.
  2. Смена содержимого через короткое размытие. Текст внутри меняющегося контейнера уходит рано и быстро, новый текст влетает на пружине. Старый и новый текст никогда не накладываются.
  3. Пружины с самым маленьким перелётом. Затухающие пружины в замкнутой форме, без резиновых смягчений. Кнопка переключателя и указатель вкладок растягиваются потому, что их края идут по разным пружинам.
  4. Курсор ведёт все изменения. Настоящие клики с нажатием и кругами расходятся от точки клика, настоящие перетаскивания возвращаются пружиной при отпускании. Агент самого продукта может стать вторым курсором.
  5. Камера обрамляет каждое состояние. Пустой кадр — это ошибка. Отъезд камеры показывает масштаб: одно письмо превращается в стену из сотен.
  6. Музыка идёт первой. Сетку битов измеряют с помощью numpy, дроп приходится на главный момент, а каждый синтезированный звук интерфейса ставится по своей измеренной вершине и попадает в бит.
  7. Настоящие данные и свои сцены. На цифровых барабанах крутятся реальные числа, логотипы клиентов бьются по одному на бит, а ничего из сайта продукта не копируется.

Восьмое правило — вы получаете режиссёра. Навык сам принимает творческие решения и записывает каждое отдельной строкой DECISION:. Одно ответное сообщение — и вы отменяете любое из них.

Что лежит в репозитории

Путь Что внутри
SKILL.md Творческая установка и порядок работы, который соблюдает Claude
references/prompts.md Исходные промпты и все замечания дословно
references/technique.md Код пружин, камеры, курсора, барабана с цифрами, звука и рендера
legacy/ Первая версия навыка: ролики под дикторский текст на GSAP и HyperFrames, 34 ловушки

Требования

Что нужно Зачем
Claude Code с Opus 5.5 Режиссура и сборка ролика
Node 20 или новее и Playwright Рендер кадров
FFmpeg Размытие движения, кодирование, проверка громкости
Python 3 и numpy Сетка битов и синтез звуков
Свободная песня примерно 120 BPM Необязательно. Лицензию на каждый трек нужно проверять: в некоторых бесплатных библиотеках есть ограниченные треки

Всё считается локально и ничего не стоит денег.

Как устроен рендер

Каждый кадр — чистая функция времени. Схема работы такая:

бриф → список состояний по сетке битов → один HTML-ролик, каждый пиксель = f(t) в seek(t)
     → по кадру на бит, контактный лист, правки
     → Playwright: 4 подкадра на кадр
     → ffmpeg tmix (размытие движения) → 60 fps H.264 + звук → раскадровка и поиск швов

Из этого следует главное свойство: рендер повторяемый. Если перемотать на любой момент, получатся те же самые пиксели. Именно это делает возможным проверку по битам и параллельный рендер.

Пружины в замкнутой форме

Вместо CSS-переходов и таймеров используется аналитическая формула отклика затухающей ступени. Она считает значение в любой момент без накопления состояния между кадрами:

function stepR(tau, {w, z}) {            // closed-form damped step response, 0 -> 1
  if (tau <= 0) return 0;
  if (z >= 1) { const x = w * tau; return 1 - Math.exp(-x) * (1 + x); }
  const wd = w * Math.sqrt(1 - z * z);
  return 1 - Math.exp(-z * w * tau) * (Math.cos(wd * tau) + (z * w / wd) * Math.sin(wd * tau));
}
class Track {                            // many target changes = sum of one spring per change
  constructor(v0) { this.v0 = v0; this.cur = v0; this.ev = []; }
  to(t, v, sp) { if (v !== this.cur) { this.ev.push([t, v - this.cur, sp]); this.cur = v; } return this; }
  at(t) { let v = this.v0; for (const [ti, d, sp] of this.ev) v += d * stepR(t - ti, sp); return v; }
}

Затухание от 0.72 до 0.9 даёт самый маленький перелёт. Для камеры и текста берут единицу, то есть без перелёта. Цель, которая должна прийти к моменту T, задают примерно на 0.3 секунды раньше. Для зацикленных роликов складывают ещё периоды k = -1 и k = -2, чтобы последний кадр совпадал с первым.

Камера и слои

Слои такие: #bg с градиентом бренда, #thr с холстом для следа курсора, #world со сценой, которую двигает камера, и #hud с накладками в координатах экрана. Камера — это translate и scale на #world. Масштаб считается в логарифме: линейный зум ощущается неправильно.

Растяжение краёв

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

T.tgL = new Track(4).to(TOG, 44, {w: 19, z: 0.9});   // trailing
T.tgR = new Track(44).to(TOG, 84, {w: 34, z: 0.9});  // leading

Барабан с цифрами

У каждой цифры своя полоса 0–9, 0, а ячейка подогнана под ширину последнего знака. Обрезка идёт только по вертикали, через clip-path. Формула для цифры с номером p двигает её только тогда, когда нижняя цифра уже переносит единицу:

// digit p: floor(v / 10^p) % 10 + max(0, (v % 10^p) - (10^p - 1))

Звук под биты

numpy находит темп через спектральный поток и автокорреляцию, а удары — по диапазону низких частот. Дальше окно песни подбирается так, чтобы дроп попал на главный момент ролика. Отметки времени берутся из самого ролика, поэтому источник истины один:

cue(g) = g * PERIOD / 0.5 + PEAK_OFF   // переводит время ролика в измеренное время удара

Сами звуки синтезируются: клик, щелчок, клавиша, нота, звонок, удар, свист, шум в полосе, блип, мерцание, подъём, плёнка. Звук перетаскивания следует за измеренной скоростью элемента. Сведение простое: песня 0.5 и звуки 0.62, затем одно постоянное усиление до пика 0.93. Ограничитель не нужен — так цикл остаётся бесшовным.

Рендер кадров

Playwright в headless-режиме снимает 1920×1080, на каждый кадр приходится четыре подкадра, и ffmpeg смешивает их в размытие движения:

ffmpeg -framerate 240 -i s%05d.png \
  -vf "tmix=frames=4:weights='1 1 1 1',select='eq(mod(n\,4)\,3)',setpts=N/(60*TB),scale=out_color_matrix=bt709:out_range=tv,format=yuv420p" \
  -r 60 -c:v libx264 -preset slow -crf 15 -tune film

Рендер идёт порциями: 960 подкадров в сегмент, затем PNG удаляются, сегменты склеиваются без перекодирования, сверху добавляется звук AAC. Три рабочих процесса. Скрипт терпит сбои: подкадр повторяется с чистой страницей, браузер перезапускается при разрыве связи.

Один элемент вместо одиннадцати сцен

Второй пример из репозитория показывает саму идею в чистом виде. Один элемент переходит через одиннадцать состояний интерфейса: кнопка, загрузка, галочка, динамическая полоса, видеолента, ползунок, переключатель, вкладки, график, палитра команд и всплывающее уведомление — и снова кнопка. Содержимое меняется через короткое размытие, курсор выполняет все клики и перетаскивания, последний кадр совпадает с первым. Ролик длиной 14 секунд идёт бесшовным циклом в формате 1440×1440, тоже со звуком: скачать.

Что запрещено

Список запрещённого пришёл из исходного задания и остаётся в силе:

  • резиновые смягчения вместо пружин,
  • вспышки частиц, свечения и градиенты на элементах интерфейса,
  • разная толщина линий у иконок,
  • пустые кадры и паузы,
  • вид готового шаблона.

Ещё запрещено брать текст, интерфейс, статистику и картинки с сайта продукта целиком. Сцены придумываются своими.

Ловушки, которые стоят часов

Их собрал автор SKILL.md, и они сэкономят много времени:

  • will-change на элементе, который масштабирует камера, делает текст размытым,
  • пружину запускают в момент события: цель, которая должна прийти к T, задают на 0.3 секунды раньше,
  • функция hide(), обнуляющая прозрачность, должна отменяться функцией отрисовки, иначе элементы остаются невидимыми,
  • в барабане с цифрами пропорциональные цифры прыгают: ячейку подгоняют под последний знак, обрезают только по вертикали,
  • на сервере с тесным диском Chromium первым попадает под ограничение памяти: рендерят порциями по 4 секунды, браузер перезапускают, а посторонний /tmp/inspect.py перекрывает стандартную библиотеку, поэтому Python запускают из папки проекта.

Первая версия и вторая

v1 (legacy) v2
Тайминг По словам дикторского текста По измеренной сетке битов музыки
Движение Таймлайны GSAP Пружины в замкнутой форме, чистый seek(t)
Рендер HyperFrames Подкадры Playwright и tmix в ffmpeg
Структура Сцены и переходы Один элемент без склеек
Звук Готовые звуки из библиотеки Синтезированные звуки по измеренной вершине
Глубина Камера на CSS Пружины камеры и необязательный WebGL-стекло

Для ролика с дикторским текстом первая версия всё ещё лучше. Она живёт в папке legacy.

Лицензия

MIT для навыка и материалов — LICENSE.

Демо-ролики не распространяются: они сделаны для Cheerful и принадлежат ему. Про это и про сторонние материалы — музыку, видео, шрифты — написано в NOTICE.

Источник: https://github.com/AbubakrChan/product-launch-motion