🎬 Регламент нарезки рилов из длинного видео
Полный пошаговый процесс + все правила. Отработано на 20 рилах Влада Ясько. Держать под рукой на каждый новый исходник.
ГЛАВНЫЙ ПРИНЦИП. Каждый рил = 4–6 смысловых битов (ХУК → РАЗВИТИЕ → ЭКСПЕРТ → ЦЕННОСТЬ → СУТЬ → CTA), нарезанных дословно с плёнки по явным таймкодам. Никакого пересказа, никакого «примерно». Один рил проходит цикл: данные → реальные tc → перегон → сверка → кадр → звук → утверждение Арта → деплой.
0. Что нужно на старте (один раз на видео)
- Исходник — горизонтальное видео (4K/1080), положить в
reels_analysis/<имя>/<имя>.mp4
- Транскрипт SRT — сделать
reels_analysis/transcribe.py (Groq large-v3-turbo, --cloud). Это карта смыслов, НЕ источник точных tc (см. правило про SRT ниже).
- Groq API ключ — в
~/.zshrc (gsk_...). Bash его не читает автоматически — подтягивать: GK=$(grep -oE 'gsk_[A-Za-z0-9_-]+' ~/.zshrc|head -1)
- Данные рилов —
reels_analysis/_gen_scenarios.py (список R: 20 рилов, у каждого title + биты).
- Движок —
_batch_reels.py генерит per-рил скрипты из шаблонов рила-1 и гонит 3 стадии. Эталон: _reel01_smart.py / _reel01_stage2.py / _reel01_render.py → montage.py.
1. Пошаговый процесс на КАЖДЫЙ рил
ШАГ 1 — Сценарий (биты). Определить тему рила и 4–6 битов. Каждый бит = завершённая мысль, дословная фраза Влада. Структура: ХУК (цепляет с 1 секунды) → РАЗВИТИЕ → ЭКСПЕРТ (методология/цифры) → ЦЕННОСТЬ (что получу) → СУТЬ (главный инсайт) → CTA. Записать в _gen_scenarios.py.
ШАГ 2 — Найти РЕАЛЬНЫЕ позиции. SRT-таймкоды ВРУТ (на 19:19 в SRT может быть уже CTA). Реальные позиции берём двумя способами:
- Если бит уже резался — из smart-лога:
grep -E "tc≈|align ratio|cut \[" _reelNN_smart.log. Смотреть align ratio: <0.6 = бит провалился.
- Точные границы по словам — Groq пословно:
GK=$(grep -oE 'gsk_[A-Za-z0-9_-]+' ~/.zshrc|head -1)
ffmpeg -y -ss 1758 -to 1818 -i <видео> -ar 16000 -ac 1 /tmp/w.mp3
curl -sS https://api.groq.com/openai/v1/audio/transcriptions \
-H "Authorization: Bearer $GK" -F file=@/tmp/w.mp3 \
-F model=whisper-large-v3 -F language=ru \
-F response_format=verbose_json -F "timestamp_granularities[]=word" \
| python3 -c "import json,sys;d=json.load(sys.stdin);print(' '.join(f\"[{1758+w['start']:.1f}]{w['word']}\" for w in d.get('words',[])))"
Получаем каждое слово с точным временем → ставим границы бита ровно от первого до последнего нужного слова.
ШАГ 3 — Явные таймкоды. В _gen_scenarios.py у бита вместо "19:13" писать диапазон "19:09.5-19:13.2" (mm:ss.d). Это режет РОВНО по окну, минуя капризный fuzzy-align. Обязательно для битов, которые сидят близко друг к другу (в одном прогоне речи) — иначе fuzzy их крамит: дубли, пропажи, обрезки.
ШАГ 4 — Перегон + сверка. BATCH_ONLY=NN python3 _batch_reels.py. Потом сверить результат транскриптом (Groq по финалу) — все биты на месте? дублей нет? не обрезано? Транскрипт финала:
ffmpeg -y -i нарезка/NN_final.mp4 -ar 16000 -ac 1 /tmp/r.mp3
curl ... -F response_format=verbose_json -F "timestamp_granularities[]=segment" ...
ШАГ 5 — Проверить КАДР. Выдернуть 3–5 кадров по длине (ffmpeg -ss T -i final -frames:v 1 f.jpg) и глазами: в кадре Влад (не Данил/не экран), он не в углу, субтитры на груди (не на лице/над головой), «Claude Desktop» на одной строке.
ШАГ 6 — Звук. Авто: _batch_reels.py в конце дублирует левый канал в оба (голос Влада в исходнике только слева). Проверка: оба канала ~равны по mean_volume.
ШАГ 7 — Утверждение Арта. Открыть рил (open final.mp4), показать что починил. Ждать «ок/заебись/дальше» — только потом деплой.
ШАГ 8 — Деплой. Пересжать в 720p под новым именем NN-vX.mp4 (X больше прошлого!), поправить index.html, wrangler pages deploy. Новое имя = кэш не подсунет старьё.
2. Правила НАРЕЗКИ (движок)
| Правило | Как |
| Явные tc для близких битов | Биты в одном прогоне речи (напр. 28:00–28:40) крамятся fuzzy → писать диапазоны mm:ss.d-mm:ss.d. Форс-кусок в stage2 идёт БЕЗ чистки (он уже цельный). |
| Якорь кадра | Когда рядом чужое лицо (Данил) или экран сбивает трекер: "41:09-41:25@cx,ey,zoom" — статичный кроп на Владе, мимо трекера. Пример: @0.32,0.46,1.5. cx/ey — доля кадра (0.32=слева), zoom — крупность. |
| Границы по словам | Начало бита — на первом слове, конец — сразу за последним. Иначе цепляет соседнюю фразу («Пожалуйста. Все») или обрезает панч-слово («живи в моём…» без «Telegram»). |
| Текст = звук | Текст бита в данных должен совпадать с тем, что реально сказано. Сильно короче звука → субтитр «зависает» (слова размазываются). Пропускать 1–2 слова можно, фразу — нет. |
| Кросс-дедуп | Один и тот же кусок НЕ должен быть в двух рилах. Вести учёт: продавец «10 лет» → только рил 12; «бот спишь / ты один» → только рил 20; ДНК-триггеры → только рил 10. |
| Битый бит убрать | Если бит провалился (align<0.3, 0.4с мусора) и рил без него цельный — просто удалить бит (глитч-огрызок в конце уйдёт). |
3. Правила СУБТИТРОВ (Стиль 1)
- Тело — Союз Гротеск, акцент — Good Vibes рукописный оранжевый #E66615.
- Акцент визуально = тело по x-height →
emph_scale 1.42 (не по числам).
- На груди (между подбородком и пупком), никогда на лице →
caption_top 0.55.
- По словам, живая анимация. Не висят весь ролик, не в 2 замороженных ряда (это симптом over-bracket → лечится явными tc).
- Межстрочный зазор ≈ ширина пробела →
line_gap 0.70.
- Анти-сирота: последнее слово фразы не уезжает на отдельную карточку («Desktop» остаётся с «Claude»). Уже зашито в
regroup_single_line.
- Субтитры никогда не налезают друг на друга — если слиплись, это баг тайминга (обычно от крама) → явные tc.
4. Правила КАДРА
- Динамический eye-lock: кадр плавно следует за лицом Влада, глаза высоко в кадре.
- Стоя (раннее, высоко в 4K) →
eye_crop 0.43; сидя (демо) → 0.32 (поднять Влада ~12%). Авто по медиане высоты глаз.
- Опознавать Влада по ТЁМНЫМ ОЧКАМ — рядом сидит Данил, трекер прыгает на него. Приоритет лицам с «shade» (тёмная полоса глаз).
- Если трекер всё равно ловит Данила/экран → якорь (см. правила нарезки). Данила показывать только как перебивку 3–4×2–3с на его реакциях, не 40%.
- Грейд натуральный (не жёлтый), слабая виньетка. Никаких стат-попов/тайтл-карт/SFX/AI-бролла.
5. Правила ЗВУКА
- Голос Влада в исходнике только в ЛЕВОМ канале → дублировать левый в оба уха:
ffmpeg -af "pan=stereo|c0=c0|c1=c0". Зашито в _batch_reels.py (авто после рендера). Проверять оба канала.
- Музыка: ровный фон, база
0.10, без дакинга. 1 трек на 3–4 рила (разнообразие). Дроп на ключевой мысли — опц.
6. Правила CTA
- Кодовое слово во ВСЕ рилы: «Напиши кодовое слово — я тебе пришлю промпт» (реальный кусок ~19:28). Зашито в
segs_for() — заменяет любой CTA автоматически.
7. Правила ДЕПЛОЯ
- Всегда Cloudflare Pages (
wrangler pages deploy), проект vlad-reels.
- Кэш-бустинг именем файла: каждую заливку —
NN-v(X+1).mp4, поправить index.html, удалить старое. Иначе браузер/CDN отдают старьё (одинаковое имя = кэш).
_headers: /*.mp4 → Cache-Control: no-cache, no-store, must-revalidate.
- Прод-URL: vlad-reels.pages.dev. Если Арт видит старое — Cmd+Shift+R или инкогнито.
8. ✅ Чеклист приёмки (перед показом Арту)
- Все запланированные биты на месте (ничего не пропало)
- Нет дублей фраз (ни внутри рила, ни с другими рилами)
- Ничего не обрезано на полуслове (особенно панч и концовка)
- CTA «кодовое слово» звучит в конце
- Субтитры по словам, на груди, не висят, не слипаются, «Claude Desktop» вместе
- В кадре Влад (не Данил/не экран), не в углу
- Звук в оба уха (оба канала ~равны)
- Длительность адекватная (не 25с из-за провалов, не 90с)
- Смысл цельный, дословно с плёнки
9. 🔧 Типичные баги → фиксы
| Симптом | Причина | Фикс |
| Фраза повторяется 2 раза | Хук перехватил кусок следующего бита | Явные tc: хук кончается ровно перед фразой развития |
| Бит пропал / рил слишком короткий | Крам близких битов, fuzzy схлопнул | Явные tc по словам на каждый бит |
| Обрезано на полуслове | Неверный tc (SRT врёт) / граница не по слову | Groq пословно → точная граница |
| Субтитры висят / в 2 ряда весь ролик | Over-bracket (речь склеилась в одну «фразу») | Явные tc → тугой кусок |
| Субтитры «ебанулись» за 4–5с до конца | Провалившийся бит = 0.4с огрызок перед CTA | Убрать битый бит |
| Зависание / лаг субтитра в конце | Текст бита короче звука (рамбли-CTA) | Кодовое-CTA (короткий) + текст = звук |
| «Desktop» на отдельной карточке | Перенос последнего слова | Анти-сирота (уже в движке) |
| В кадре Данил вместо Влада | Трекер поймал соседа | Якорь @cx,ey,zoom на позицию Влада |
| Влад в углу / кадр на экране | Трекер поймал лицо на проекции | Якорь на реальную позицию Влада (проверить 4K) |
| Голос в одно ухо | Исходник пишет голос в левый канал | pan дублирует левый в оба (авто) |
| На сайте старое видео | Кэш (одинаковое имя файла) | Новое имя -vX + no-cache + Cmd+Shift+R |
10. Ключевые файлы и команды
# данные всех рилов (title + биты + tc)
reels_analysis/_gen_scenarios.py
# перегнать один рил (или несколько через запятую)
BATCH_ONLY=7 python3 _batch_reels.py
BATCH_ONLY=14,16,18,19 python3 _batch_reels.py
# формат бита в SEGMENTS:
("ХУК","11:32.5-11:34.9","дословный текст","акцент") # явный tc
("ХУК","41:09-41:25@0.32,0.46,1.5","...","...") # + якорь кадра
("ХУК","13:22","...","...") # fuzzy (только если бит одиночный)
# деплой (сменить имя на новую версию!)
ffmpeg -i нарезка/NN_final.mp4 -vf scale=720:1280 -crf 28 ... .deploy-vlad-reels/NN-vX.mp4
cd .deploy-vlad-reels && wrangler pages deploy . --project-name=vlad-reels --branch=main --commit-dirty=true
КОРОТКО, КАК МАНТРА:
Дословно с плёнки · реальные tc из Groq (не из SRT) · явные диапазоны для близких битов · сверять транскриптом · Влад в кадре (не Данил) · субтитры на груди по словам · звук в оба уха · кодовое-CTA · кросс-дедуп · утвердил Арт → деплой под новым именем.