scroll-world: скилл, который собирает лендинг-3D-мир, управляемый скроллом
📂 Исходный код на GitHubСкилл, превращающий любой бренд в 3D-мир-лендинг, который прокручивается: связные изометрические диорамы, бесшовные перелёты камеры и scroll-scrub движок на vanilla JS, MIT-лицензия.
Сайт, который выглядит так, будто летишь сквозь мир: при прокрутке камера сначала висит над сценой снаружи, потом ныряет внутрь неё, вылетает и без единого монтажного склея уходит в следующую. Графика сгенерирована AI, видео тоже, а скролл не управляет объектами — он управляет временем. Именно так работают скролл-страницы продуктов Apple, и именно этот приём воспроизводит репозиторий scroll-world: 9,5 тысяч звёзд, MIT-лицензия, JavaScript.
Собственно говоря, scroll-world — не библиотека и не фреймворк, а агентный скилл: папка с файлом SKILL.md и несколькими reference-файлами, которые кладутся в skills-каталог Claude Code, Codex или любого агента, понимающего этот формат. Агент сам проводит интервью, сам генерирует ассеты и сам собирает страницу.
Что делает scroll-world
Скилл собирает лендинг-«мир» для любой отрасли или бренда. Механика жёстко зафиксирована: непрерывный полёт сквозь мир, без склеек. Визуальный слой состоит из двух частей:
- Сцены-диорамы — изометрические миниатюры в стиле low-poly пластилина с тёплым светом и эффектом tilt-shift. По умолчанию генерируются моделью
gpt_image_2на Higgsfield (или через встроенныйimage_genв CLI от OpenAI, если он есть — та же модель, но списывается с подписки ChatGPT, а не с кредитов). - Видеопролёты камеры — ролики, в которых камера ныряет в сцену, а потом улетает к следующей. Рендерятся моделью Seedance 2.0.
Дальше всё это склеивается в нечто вроде сайта логистической компании Emons, только про вашу тему.
Ключевая особенность: скилл framework-agnostic. Движок в references/scrub-engine.js — самодостаточный vanilla JS, который строит собственный DOM и подключает свой CSS в переданный контейнер. Он одинаково заезжает в статический HTML, Next.js, Vue или страницу, отдаваемую Python-сервером. Ценность скилла не в фреймворке, а в пайплайне, шаблонах промптов и методе сшивки швов.
Как проходит сборка
Вызов скилла разворачивается в три крупные фазы.
1. Интервью. Агент задаёт открытый вопрос о теме (без выдуманного списка отраслей — это смещает пользователя), уточняет бренд-кит (импорт с сайта, переданные вручную цвета или предложенные агентом), арт-дирекшн и стиль камеры. Стиль арт-дирекшна превращается в общий style preamble, который дословно повторяется в каждом промпте — именно он делает мир цельным. Отдельно и обязательно спрашиваются мобильная версия и бюджет: сметка показывается до того, как что-то сгенерировано.
2. Генерация ассетов. На каждую сцену — один стил, на каждую сцену — один ролик ныряния, плюс ролики-коннекторы, которые связывают соседние сцены. Коннекторы генерируются из реальных отрендеренных кадров соседей, а не из исходных картинок.
3. Сборка страницы. Конфигурационный скролл-движок играет всю цепочку как один полёт, а на телефонах автоматически отдаёт портретные версии и постеры.
Стиль камеры выбирается из трёх вариантов, и это не техническая деталь, а «характер» фильма: полёт сквозь мир с постоянной сменой ракурсов, один непрерывный проход вперёд без откатов или зафиксированное изометрическое скольжение.
Главное правило: швы должны совпадать кадр в кадр
Это единственное, что рушит или делает результат, и SKILL.md ставит его на первое место с формулировкой «прочитай раздел про бесшовную цепочку до того, как сгенерируешь хоть один коннектор».
Суть проблемы: каждая генерация рендерит сцену чуть иначе. Если коннектор заканчивается свежим рендером «кухонной диорамы», а следующий ролик ныряния начинается со своего собственного рендера той же кухни, кадры не совпадут — и на стыке будет щелчок. Лечится передачей точных пикселей:
Для каждого коннектора между dive_i и dive_{i+1}:
start-image = ПОСЛЕДНИЙ кадр, извлечённый из dive_i
end-image = ПЕРВЫЙ кадр, извлечённый из dive_{i+1}
Кадры вытаскиваются из отрендеренного видео, а не из исходных стилов:
ffmpeg -sseof -0.15 -i dive_i.mp4 -frames:v 1 -q:v 2 dive_i_last.png
ffmpeg -ss 0 -i dive_next.mp4 -frames:v 1 -q:v 2 dive_next_first.png
Теперь dive_i.end == connector.start и connector.end == dive_{i+1}.start — шов совпадает с обеих сторон. Seedance при этом приземляется не пиксель в пиксель, а близко (замерено 27,5 dB против 31,6 dB на старте), поэтому движок дополнительно делает короткий кроссфейд в несколько кадров. Но полагаться только на кроссфайд нельзя: большой скачок контента им не спрячешь.
Две архитектуры камеры
A. Непрерывный проход вперёд. Одна камера, которая только скользит вперёд от первой сцены к последней. Ролики генерируются строго последовательно: --start-image следующего ролика — это реальный последний кадр предыдущего. Коннекторов нет вообще, ноги и есть маршрут. Минус — параллелить нельзя, работа идёт дольше.
B. Ныряние плюс воздушный коннектор. Камера ныряет в сцену, коннектор вытягивает её вверх и переносит к следующему острову. Выглядит эффектнее на карте-диораме, но разворачивает направление движения на каждом шве. На реалистичном «от первого лица» это читается как перемотка назад, поэтому такая архитектура рекомендована только для миниатюрной эстетики.
Отдельно SKILL.md описывает «грамматику камеры»: движение внутри одного ролика может быть любым — орбита, боковой трек, подъём коптера, — но каждый ролик обязан заканчиваться спокойным ровным дрейфом вперёд, а следующий — продолжать этот дрейф. Развороты фатальны только на швах, а не внутри клипа. И есть нюанс про скролл: посетитель может крутить вверх, поэтому каждое движение играется ещё и задом наперёд.
Модели, деньги и требования
Видео-модель выбирается не по вкусу, а по способности удержать шов: ролик должен принимать --start-image, а коннектор — ещё и --end-image. Всё, у чего вход только референсный, физически не может продолжить сцену.
| Модель | Start / End image | Примечания |
|---|---|---|
seedance_2_0 (по умолчанию) |
да / да | Полная цепочка, 1080p, фильтр NSFW чувствительный |
kling3_0 |
да / да | 720p без параметра разрешения, звук выключать флагом, разрешённый запасной вариант при срабатывании фильтра |
seedance_2_0_mini |
да / да | Дешёвый черновик 720p, сохраняет frame-locking |
minimax_hailuo |
да / нет | Самый дешёвый пробник, но коннекторы не собрать |
Правило одно на всю цепочку: одна модель на все ролики. Смена модели посередине сохраняет позиционную непрерывность, но сдвигает характер картинки, и это читается как едва заметный щелчок.
Про деньги автор пишет честно. Цепочка из N сцен — это N стилов плюс 2N−1 видео, плюс около 15% запаса на перегенерации, и мобильная цепочка удваивает число видео. При шести сценах в 1080p получается около 27 долларов на Monid — там Seedance 2.0 тарифицируется поклипово, токенами по формуле ширина × высота × 24 × секунды, и это без подписки и без сгорания баланса. На кредитах Higgsfield та же работа обошлась бы примерно в 32 доллара по помесячному плану. Замерено на живых деньгах: ролик 1080p на 8 секунд — около 2,99 доллара, коннектор на 5 секунд — около 1,87; на 720p — 1,21 и 0,76; на 480p — 0,28 и 0,35. Скилл сверяет баланс со сметкой и прямо говорит, если денег не хватит, а цену заменяет на кредиты Higgsfield.
Требования честно перечислены: CLI Monid с ключом и балансом как основной бэкенд видео, аутентифицированный CLI Higgsfield для картинок и как запасной биллер, ffmpeg и ffprobe, Python 3 с Pillow для мобильных холстов. CLI от OpenAI — опционально: если он есть, стили можно генерировать image_gen и платить подпиской ChatGPT.
Отдельная деталь про точность смет: CLI Higgsfield не отдаёт прайс, поэтому скилл не угадывает. Он сначала генерирует одну картинку и один ролик, сравнивает баланс до и после и экстраполирует на весь прогон.
Скролл-движок и мобильная версия
Движок конфигурационный, и монтируется одной функцией:
mountScrollWorld(document.getElementById('world'), {
brand: { name: 'Pearl & Co.' },
diveScroll: 1.3, connScroll: 0.9,
sections: [
{ id:'farm', label:'The Farms', still:'assets/farm.webp',
clip:'assets/vid/farm.mp4',
clipMobile:'assets/vid/farm-m.mp4',
stillMobile:'assets/farm-m.webp',
scroll: 1.6, linger: 0.45,
accent:'#8FB98A', eyebrow:'From leaf to last sip', title:'It starts in the hills.',
body:'…', tags:['Single-origin','Hand-picked'] }
],
connectors: ['assets/vid/conn1.mp4','assets/vid/conn2.mp4'],
connectorsMobile: ['assets/vid/conn1-m.mp4','assets/vid/conn2-m.mp4'],
});
Движок берёт на себя упорядоченную цепочку «ныряние + коннектор», сглаживание скролла через requestAnimationFrame, ленивую подгрузку соседних роликов, кроссфейды на совпавших кадрах, текст секций, рельс маршрута, prefers-reduced-motion и адаптацию под телефон. Настроение сцены задаётся двумя ручками: scroll задаёт, сколько экранов прокрутки длится сцена, а linger (0–1) замедляет камеру в середине ролика ровно в момент, когда читатель дочитывает заголовок, и потом разгоняет её к шву.
Два технических решения стоит знать, потому что на них чаще всего и ломается скролл-видео. Первое: работать надо не с частотой ключевых кадров, а с seekability. Многие статические хостинги и python -m http.server не отдают байтовые диапазоны, из-за чего video.seekable схлопывается в [0,0] и каждое seek упирается в нулевой кадр — видео выглядит замороженным. Надёжный способ — грузить каждый ролик как Blob и играть из in-memory object URL, что скилл и делает. Второе: качество ради плавности ухудшать не надо. Кодировать в нативном 1080p, crf около 20, короткий GOP вместо all-intra и faststart:
ffmpeg -i src.mp4 -an -vf "unsharp=5:5:0.8:5:5:0.0" \
-c:v libx264 -preset slow -crf 20 -pix_fmt yuv420p \
-g 8 -keyint_min 8 -sc_threshold 0 -movflags +faststart out.mp4
Мобильная версия — не кроп десктопного ролика. Это вторая цепочка, отрендеренная нативно в 9:16 и склеенная по тем же законам, но уже под вертикальные холсты: 720 ширины, -g 4, crf 23. Отдав кроп вместо неё, вы получите обрезанные по бокам композиции, поэтому SKILL.md разрешает кроп только как явно оговорённую временную меру. Движок при этом телефон готовит всегда: склеивает seek-запросы, держит картинку-постер, пока ролик не отрисовал первый кадр, и игнорирует ресайз, вызванный появлением адресной строки.
Что внутри репозитория
skills/scroll-world/
├── SKILL.md процедура, правило шва и грабли
└── references/
├── prompts.md чек-лист интервью и все шаблоны промптов
├── pipeline.md готовые батч-скрипты: generate → frames → connectors → encode
├── scrub-engine.js портативный движок: blob-seek, ленивая загрузка, кроссфейд швов
├── index-template.html минимальная самостоятельная страница, которая монтирует движок
└── knockout.py вырезание фона для парящих сцен
Самый ценный файл, если собираетесь делать такое же руками, — SKILL.md. Это плотный документ про грабли, собранные в проде: щелчок на шве из-за использования исходной картинки вместо кадра, зависшее видео из-за отсутствия байтовых диапазонов, лёгкий кроссфейд вместо кадровой подгонки, «не тот объект», NSFW-ложняк на безобидных сценах вроде спальни или бассейна, белый фон из коробки gpt_image_2, параллельные вызовы codex exec, которые делят stdin и потому подвисают, bash 3.2 на macOS без ассоциативных массивов, и циклы по массивам, написанные в zsh, где индексация с единицы.
Как поставить
В Claude Code — как плагин, одной командой:
/plugin marketplace add oso95/scroll-world
/plugin install scroll-world@scroll-world
В Codex и двадцати других агентах — через skills CLI от Vercel:
npx skills add oso95/scroll-world
npx skills add oso95/scroll-world -a codex
Ну и вручную, если хочется просто скопировать папку:
git clone https://github.com/oso95/scroll-world
cp -R scroll-world/skills/scroll-world ~/.claude/skills/
Кому это пригодится
scroll-world — редкий случай, когда агентный скилл продаёт не «фичу в коде», а дизайн-артефакт: упакованный в промпты и скрипты способ сделать дорогую motion-графику, которую иначе пришлось бы заказывать аниматору. Он же честно называет свою цену — десятки долларов и десятки минут ожидания на батче, — что делает его инструментом для запуска, а не для фоновой работы.
Логичный кандидат: продукт, который сам по себе удобно показать как место. Логистика, доставка, производственная цепочка, ремонт, туризм, ресторанный бизнес. Скилл сам подсказывает структуру маршрута — сцены выводятся из цепочки создания ценности субъекта, пять-семь штук работают лучше всего, а последняя обычно отдана главному продукту и призыву к действию.
Лицензия MIT, код на JavaScript, генерируемые ролики в репозиторий не кладутся — они производятся под конкретный проект.
Источник: https://github.com/oso95/scroll-world