Communitygithub.com

hukvadim/edit-video-skill

Монтаж сирого talking-head відео (або запису «екран + камера + окремий мікрофон», який скіл сам синхронізує й складає у спліт) у вертикальний ролик 9:16 для Reels/TikTok/Shorts — вирізає паузи й дублі, чистить звук до −14 LUFS, субтитри з підсвіченим словом, наближення на склейках, титул і плашки, картки-роботи, що вилітають ЗА СПИНОЮ спікера (Remotion + маска Robust Video Matting), повноекранні стокові вставки з переходами, фонова музика з приглушенням. Сам встановлює ffmpeg, whisper.cpp, моделі й npm-пакети, якщо їх немає. Використовуй, коли просять змонтувати / обробити / зробити рілс із відео, або /edit-video <файл>. Edit raw talking-head video into a polished vertical reel.

O que é edit-video-skill?

edit-video-skill is a Claude Code agent skill that монтаж сирого talking-head відео (або запису «екран + камера + окремий мікрофон», який скіл сам синхронізує й складає у спліт) у вертикальний ролик 9:16 для Reels/TikTok/Shorts — вирізає паузи й дублі, чистить звук до −14 LUFS, субтитри з підсвіченим словом, наближення на склейках, титул і плашки, картки-роботи, що вилітають ЗА СПИНОЮ спікера (Remotion + маска Robust Video Matting), повноекранні стокові вставки з переходами, фонова музика з приглушенням. Сам встановлює ffmpeg, whisper.cpp, моделі й npm-пакети, якщо їх немає. Використовуй, коли просять змонтувати / обробити / зробити рілс із відео, або /edit-video <файл>. Edit raw talking-head video into a polished vertical reel.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add hukvadim/edit-video-skill

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

edit-video — конвеєр монтажу вертикальних роликів

SKILL_DIR — «Base directory for this skill», показаний при завантаженні скіла. Усі скрипти лежать у SKILL_DIR/scripts. Проєкт — папка з відео користувача (поточна робоча папка). У ній створюються work/<назва>/, out/, assets/.

Вимоги до результату (структура, темп, стиль, правила b-roll, звук, чекліст) описані в SKILL_DIR/docs/TZ-video.md. Прочитай його перед кроком 2 і виконуй.

Крок 0. Середовище (раз на сесію, ОБОВ'ЯЗКОВО)

node "SKILL_DIR/scripts/setup.mjs"

Скрипт перевіряє й ставить: ffmpeg ≥ 7 (з libass), whisper-cli, модель whisper large-v3-turbo (~570 МБ), модель RVM (15 МБ), npm-пакети (Remotion, onnxruntime-node, ~300 МБ), Chrome Headless Shell для Remotion, звук «вжух», шрифт. Повторний запуск нічого не перекачує. Запускай у фоні, бо перший раз триває довго. Наприкінці друкує таблицю ✅/❌; поки є ❌, далі не йди.

  • Немає Node.js (node не знайдено або версія < 20): Windows → winget install OpenJS.NodeJS.LTS, macOS → brew install node. Після встановлення відкрий нову консоль (PATH) і повтори крок 0.
  • macOS без Homebrew: попроси користувача самого виконати інсталятор з https://brew.sh (потрібен пароль sudo).
  • onnxruntime ❌ на Windows: setup сам копіює новіші msvcp140*.dll у папку onnxruntime, а якщо не допомогло — ставить Microsoft.VCRedist.2015+.x64. Попередь користувача, що може з'явитися вікно UAC.
  • Користувачу коротко скажи, що встановлено і скільки це займе місця.

Два формати запису

  1. Говорюща голова — одне відео (камера/телефон зі звуком). prep <відео>.
  2. Екран + голова + мікрофон — три файли в одній папці, наприклад … Head.mp4, … Screen.mp4, … Sound.wav. prep <папка> сам знайде їх за назвами (Head/голова/cam, Screen/екран, Sound/audio/mic/звук), або явно: prep <head.mp4> --audio <sound.wav> --screen <screen.mp4>. Файли записані неодночасно, тож prep сам синхронізує їх за звуком (крос-кореляція, точність ~1 мс) і пише work/<назва>/sync.json: час_у_файлі = t_мікрофона + зсув. Головна шкала часу (склейки, субтитри, at) — мікрофон, розшифровка теж з нього. Компоновка — "layout": "split": екран зверху (1080×960), камера знизу, жовта лінія на стику.

Крок 1. Розшифровка

node "SKILL_DIR/scripts/vid.mjs" prep <відео | папка> [uk|ru|en|auto] [--audio f] [--screen f]

Запускай у фоні, на слабкому CPU це кілька хвилин. Результат у <проєкт>/work/<назва>/: probe.json, transcript.json (слова з таймкодами), silences.json (паузи −30 дБ ≥ 0.2 с), а в консолі — текст фразами з таймкодами. Терміни, які whisper розпізнав з помилками («джавоскріп» → JavaScript, «гід» → Git), виправ прямо в transcript.json, поле w.

Крок 2. План монтажу → work/<назва>/edit.json

Прочитай розшифровку, silences.json і подивись 1–2 кадри відео (ffmpeg -ss T -i відео -frames:v 1 x.png), щоб зрозуміти, де обличчя і що стоїть перед спікером. Далі за ТЗ:

  • Склейки: паузи > 0.35 с, «еее/ммм», фальстарти. З дублів лишай останній. Межі ставь на ~0.08 с всередину паузи з кожного боку. zoom чергуй 1.0 / 1.12.
  • Хук: титул 2–5 слів (питання або обіцянка), перше слово без паузи.
  • Плашки: 3–5 ключових думок, *слово* підсвічується.
  • B-roll «за спиною» (broll): 3–4 епізоди на словах, які він ілюструє. Картинки клади в <проєкт>/assets/covers/: обкладинки робіт користувача (якщо підключено MCP devguide, бери cover з devguide_catalog_list) або його скріншоти. Предмет перед спікером (мікрофон, чашка) задай в avoid, інакше картка його перекриє.
  • Стокові вставки (cutaways): 2–3 по 3–4 с на фразах із конкретним образом. Бери з Mixkit (див. «Ассети»).
  • Музика: assets/music/*.mp3, volume 0.3–0.4.
  • Інтервали: між b-roll, вставками й плашкою ≥ 0.5 с; fly-b-roll і плашка не одночасно.
  • Формат 2 (спліт): перед вибором focus витягни кадр екрана в середині кожного сегмента (ffmpeg -ss <t + sync.screenOffset> -i screen.mp4 -frames:v 1 -vf scale=480:-2 sN.png, склей у контакт-лист) і наведи focus: [x, y, w] (пікселі запису екрана, висота = w / 1.125) на те, про що йде мова: вікно гри, код, кнопку, заголовок. w 800–1215: менше — крупніше, але текст має лишатися цілим. Де запис уже наближений самою програмою запису, бери повну висоту (w 1215). Наближення міняй на склейках. headX — де обличчя на камері (0…1). B-roll у спліті вимкнено, плашки стоять угорі екрана, субтитри — на стику. Покажи користувачу таблицю «час → текст, що лишається» + титул/плашки/b-roll/вставки/музику й дочекайся «ок».

Крок 3. Прев'ю

node "SKILL_DIR/scripts/vid.mjs" preview <проєкт>/work/<назва>/edit.json

Запускай у фоні. Вийде preview.mp4 (540×960) і frame_*.png: перші кадри знято на піках b-roll і вставок. Перший запуск рахує маску людини (RVM на CPU ≈ 1 кадр/с, лише на відрізках b-roll) і кліпи Remotion. Далі обидва беруться з кешу (matte_<hash>.mkv, broll_<hash>.mov), поки не зміняться склейки чи props. Переглянь кадри сам (Read) за чеклістом ТЗ: голова перед картками, без ореолу, обличчя й avoid-зона не перекриті, субтитри не нижче 22% кадру, плашки не на обличчі. Склади кадри в один контакт-лист (ffmpeg hstack) і покажи користувачу разом із прев'ю. Перевірити один лейаут без повного рендеру: node SKILL_DIR/node_modules/@remotion/cli/remotion-cli.js still SKILL_DIR/motion/index.ts Broll x.png --props=p.json --frame=40 --public-dir=<проєкт>/assets

Крок 4. Фінал

node "SKILL_DIR/scripts/vid.mjs" render <проєкт>/work/<назва>/edit.json

Вийде <проєкт>/out/<назва>_final.mp4 (1080×1920, H.264 + AAC). Скрипт друкує LUFS і true peak (ціль ≈ −14, пік ≤ −1). Перевір ffprobe-ом формат і тривалість, витягни 3–4 кадри. Нагадай користувачу послухати ролик: звук перевірено лише вимірами.

Схема edit.json

Усі часи — у секундах вихідного відео; скрипт сам перераховує їх після вирізання (елементи у вирізаних шматках відкидає).

{
  "source": "VID_xxx.mp4",
  "site": "devguide.com.ua",
  "avoid": [760, 800, 320, 1120],
  "segments": [{"start": 28.13, "end": 29.49, "zoom": 1.0}, {"start": 29.81, "end": 34.36, "zoom": 1.12}],
  "title":    {"text": "Що питатимуть на співбесіді?", "dur": 2.6},
  "callouts": [{"at": 39.0, "dur": 3.4, "text": "Не пише кожен рядок — *працює з AI*"}],
  "broll":    [{"at": 34.7, "dur": 2.8, "layout": "fan", "images": ["ai-site.webp", "site-3-days.webp"]}],
  "cutaways": [{"at": 31.0, "dur": 3.0, "file": "assets/stock/handshake.mp4", "from": 1.0, "cropX": 0.5}],
  "music":    {"file": "assets/music/track.mp3", "volume": 0.4},
  "style":    {"subY": 520, "calloutY": 330, "titleY": 360},
  "cropX": 0.5
}

Формат 2 додає поля (решта — як вище; music.file може бути ../assets/..., якщо музика спільна для кількох папок):

{
  "source": "День 5 - Відео 1 Head.mp4",
  "audio":  "День 5 - Відео 1 Sound.wav",
  "screen": "День 5 - Відео 1 Screen.mp4",
  "layout": "split",
  "headX": 0.77,
  "segments": [{"start": 6.05, "end": 9.30, "zoom": 1.0, "focus": [346, 0, 1215]},
               {"start": 25.52, "end": 27.82, "zoom": 1.12, "focus": [230, 40, 880]}],
  "sync": {"head": 22.094, "screenOffset": 2.024}
}
  • face: [x, y] — центр обличчя на кадрі камери (частки 0…1, визнач за кадром). Обличчя стає по центру нижньої половини, на ~38% її висоти. headZoom (типово 1.25 ≈ по 10% з боків) — наскільки крупно; zoom сегмента множиться на нього.

  • bgBlur (типово true у спліті): фон за спікером розмивається й трохи темніє, людина лишається різкою (маска RVM 384×342 @15 fps на весь ролик, рахується раз і кешується як headmatte_<hash>.mkv).

  • sync необов'язковий: за замовчуванням береться з sync.json. Вписуй вручну, лише якщо губи явно не збігаються.

  • layout: "head" при наявному screen — лише камера на весь кадр (звук з мікрофона), b-roll знову доступний.

  • Екран коротший за мовлення → останній кадр тримається; камера має покривати весь діапазон склейок.

  • captions: {"style": "clean" | "classic", "emphasis": ["годин", "сайт"], "accent": "#FFD200"}. clean (типово) — Montserrat ExtraBold, малі літери, слова з'являються по одному з «попом», м'яка тінь; emphasis — початки ключових слів (акцентний колір і +12%). classic — старий стиль: ВЕЛИКІ, жовте поточне слово.

  • Титул і плашки — кінетичний текст Remotion (motion/Kinetic.tsx): "підводка *акцент*" → дрібний білий рядок і великий акцентний, слова влітають із розмиттям. textStyle: "classic" повертає старі ASS-плашки. Пиши коротко: акцент ≤ 3–4 слова, інакше він не влізе у 2 рядки.

  • site — підпис в адресному рядку карток b-roll (порожньо — без нього).

  • avoid — [x, y, w, h] у кадрі 1080×1920: зона предмета перед спікером, куди картки не заходять.

  • broll.layout: fan (2–3 картки виринають з-за голови) | fly (3 картки залітають з країв, паралакс) | wall (3D-стіна з усіх робіт, для «хто я» / CTA). images — файли з assets/covers/.

  • cutaways: file — стоковий кліп, from — секунда початку в ньому, cropX — куди наводити кроп (0…1). Звук переходу береться з assets/sfx/whoosh.mp3 проєкту, а якщо його немає — зі SKILL_DIR/tools/sfx/whoosh.mp3.

  • style: пікселі кадру 1080×1920 (subY — від низу до субтитрів, інші — центр по Y). cropX — кроп горизонтального відео.

  • icons (застаріле, але працює): [{"at","dur","file","pos","size"}] — PNG-іконки. Краще b-roll.

Ассети: де брати й що можна

  • Стокові відео, музика, звуки — Mixkit. Пряме CDN: assets.mixkit.co/videos/<id>/<id>-1080.mp4 (або -2160), assets.mixkit.co/music/<id>/<id>.mp3, assets.mixkit.co/active_storage/sfx/<id>/<id>-preview.mp3. Можна лише Free License: у HTML сторінки кліпу JSON-LD має містити "copyrightNotice":"Free". Кліпи з Mixkit Restricted License не бери. ID шукай на сторінках mixkit.co/free-stock-video/<тема>/. Роби небагато запитів: сайт вмикає Cloudflare-перевірку, і її не можна обходити (тоді спробуй пізніше або попроси користувача). Горизонтальні кліпи бери в 4K/1080p, бо кроп у 9:16 бере ~1/3 ширини.
  • Музика також з Pixabay Music, але лише треки без позначки «Content ID Registered». Скачати автоматично не вийде (403 / браузер не зберігає файл), тож дай користувачу посилання, щоб поклав файл у assets/music/.
  • Медіа не коміть у репозиторій скіла: ліцензії стоків забороняють перепоширювати файли окремо.

Troubleshooting

СимптомЩо робити
ERR_DLOPEN_FAILED onnxruntime (Windows)node SKILL_DIR/scripts/setup.mjs — сам покладе DLL або поставить VC++ Redistributable
Маска дуже довгоНорма для CPU (~1 кадр/с). Рахується лише на відрізках b-roll і кешується. Менше b-roll → швидше
Перші слова фрази зникли із субтитрівwhisper склеїв їх у паузу; retime у скрипті це виправляє — перевір межі сегментів
Квадрати замість літерНемає шрифту: Windows — Segoe UI Black (системний), macOS — SKILL_DIR/fonts/Montserrat-Black.ttf
Картка перекрила мікрофонЗадай avoid
Музики не чутиvolume 0.4–0.5; під голосом вона має бути на ~12–15 дБ тихіше (див. ТЗ §9)
ffmpeg … -/filter_complex невідомийffmpeg < 7, онови (setup показує версію)

Habilidades Relacionadas