video-orchestrator
Дирижёр всего видео-конвейера. Получает запрос «сделай 3 ролика для бас дент» и гоняет цепочку copywriter → voiceover → director → captions → music → reviewer. Резолвит проект из команды, поднимает preflight, координирует sub-скиллы и отдаёт готовые .mp4.
Что делает простыми словами
Это top-level дирижёр. Юзер говорит «сделай 3 ролика для имплантов» — а orchestrator под капотом:
- Определяет, какой проект имеется в виду (bas-dent, fitzone, apparatus, etc.)
- Читает
project.yamlэтого проекта → знает язык, ниши, голос-настройки, бренд - Прогоняет preflight check (есть ли клипы, голоса, ключи)
- Запускает copywriter N раз — получает N скриптов
- Запускает voiceover на каждый текст — получает N mp3
- Прогоняет audio_process.py — убирает паузы, нормализует громкость
- Запускает director — собирает по 2-3 варианта на каждый ролик
- Накладывает hook + субтитры (captions через
render_final.py) - Накладывает фоновую музыку (
overlay_music.py) — отдельным шагом - Прогоняет reviewer для QA
- Выдаёт юзеру список финальных
.mp4
Без orchestrator пришлось бы каждый скилл вызывать вручную и держать в голове, где какой файл лежит, какая длительность и какие настройки. С ним — одна команда даёт готовые ролики.
scripts/, передаёт пути и фолбэчит при ошибках.
Два пайплайна (по формату ролика)
Voiceover (дефолтный)
Длительность диктует озвучка (15-60 сек). Музыка — последний шаг, отдельно от assemble.
Textover
Фиксированные 15 сек, без озвучки, без Whisper, без captions. Текст рендерится анимацией поверх видео через Remotion.
Project Resolution
Каждый запуск должен знать «к какому проекту относится команда». Порядок резолва:
- Явно в команде: «сделай 3 видео для бас дент» → slug
bas-dent→ читаемvideo-projects/bas-dent/project.yaml - Единственный проект: если в
~/video-projects/только одна папка сproject.yaml— используем её автоматически - Неоднозначно: если проектов несколько и юзер не указал → спрашиваем
slug → scoping в БД, language → captions/voiceover, service_directions → copywriter, veo.* → clipgen, voiceover.* → voiceover, captions.* → captions, remotion.brand.* → motionfx, director.* → director.
~/video-projects/director.db, не внутри папки проекта. Изоляция через junction-таблицы.
Два режима работы
| Режим | Поведение | Когда выбирать |
|---|---|---|
| auto (default) | Гонит весь pipeline без остановок. Юзер ждёт и получает финал. | Когда юзер доверяет системе и хочет скорости. Команда: «сделай 3 ролика, автомат» |
| semi-auto | Останавливается на чекпоинтах, ждёт approval/edit | Когда нужен творческий контроль. Команда: «покажи тексты перед озвучкой» |
Чекпоинты semi-auto
- После генерации текстов — показать скрипты, ждать approval/edits
- После voiceover — отчитаться о длительности, спросить «ок?»
- После montage plan — показать какие клипы под какой сегмент идут, до сборки
- После выбора caption-стиля — какой preset рендерим (neon/marker/cyber/...)
- Перед overlay_music — какой трек и какая громкость
- После reviewer — показать оценки, спросить нужны ли правки
Preflight: check_project.py
Главный скрипт скилла — pre-flight check, который запускается ДО любого pipeline-run'а. Он проверяет:
| Что проверяет | Зачем |
|---|---|
project.yaml существует и валиден | Без него ничего не запустится |
Проект зарегистрирован в projects | Иначе junction-таблицы не будут работать |
| Brief сохранён | Copywriter без брифа пишет в пустоту |
| Минимум 5-10 клипов в библиотеке | Director не сможет собрать ролик без материала |
| Минимум 1 голос в пуле | Voiceover нужен пул для rotation |
ELEVENLABS_API_KEY в env | Без ключа ElevenLabs упадёт |
ffmpeg + ffprobe в PATH | Все сборки идут через них |
python ~/.claude/skills/video-orchestrator/scripts/check_project.py ~/video-projects/bas-dent
Возвращает структурированный отчёт «что готово / что недостаёт». Если чего-то нет — orchestrator говорит юзеру, какой скилл нужен («запусти clipgen для клипов», «добавь голоса через voiceover add-voice»).
GOOGLE_API_KEY не нужен для core pipeline. Он требуется только если ты ещё и НОВЫЕ клипы генеришь через Veo (clipgen). Для «текст → аудио → сборка» хватает одного ELEVENLABS_API_KEY.
Команды основных шагов
Тексты (Copywriter)
python ~/.claude/skills/video-copywriter/scripts/db.py get-brief <project-dir> python ~/.claude/skills/video-copywriter/scripts/db.py list-transcriptions <project-dir> --json python ~/.claude/skills/video-copywriter/scripts/db.py list-texts <project-dir> --json --limit 10 # Сохранить сгенерированный текст: python ~/.claude/skills/video-copywriter/scripts/db.py save-text <project-dir> \ --type storytelling --for-video --text "<текст>"
Озвучка (Voiceover)
python ~/.claude/skills/video-voiceover/scripts/db.py next-voice <project-dir> python ~/.claude/skills/video-voiceover/scripts/tts.py \ --project-dir <project-dir> \ --text "<текст>" \ --voice-id <voice-id> python ~/.claude/skills/video-voiceover/scripts/audio_process.py \ --input voiceover.mp3 --output voiceover_processed.mp3
Сборка (Director)
python ~/.claude/skills/video-director/scripts/probe_audio.py voiceover.mp3 python ~/.claude/skills/video-director/scripts/db.py list-clips <project-dir> --json # Сборка БЕЗ музыки (для voiceover pipeline!): python ~/.claude/skills/video-director/scripts/assemble.py \ --project-dir <project-dir> \ --voiceover voiceover_processed.mp3 \ --montage-plan '[...]' \ --variant-name "video1_a" \ --transition fade --transition-duration 0.5 \ --sfx-transition <project-dir>/sfx/whoosh.mp3
Hook + Captions (render_final.py)
# Одним проходом Remotion — hook анимация на первой сцене + караоке-субтитры: python ~/.claude/skills/video-captions/scripts/render_final.py \ --video assembled.mp4 \ --text "<полный текст озвучки>" \ --voiceover voiceover_processed.mp3 \ --preset neon \ --caption-style karaoke \ --hook-duration <sec первого предложения> \ --sfx-file ~/video-projects/sfx/text/pop_bright.mp3 \ --project-dir <project-dir> \ --language ru \ --model small
Music overlay (последний шаг)
python ~/.claude/skills/video-director/scripts/overlay_music.py \ --video video_final.mp4 \ --music <project-dir>/music/dramatic.mp3 \ --volume 0.20 \ --fade-in 2.0 --fade-out 2.5
Reviewer (опц. но рекомендуется)
python ~/.claude/skills/video-reviewer/scripts/review_video.py \ --video captioned.mp4 --frames 15
Hook duration — критичная фишка
Замер первого предложения:
python ~/.claude/skills/video-captions/scripts/transcribe_words.py \
--audio voiceover.mp3 --language ru --text "<текст>" --json \
| jq -r '.words | map(select(.word | test("[.!?…]$"))) | .[0].end'
# → 4.3 ← это hook_duration; первый сегмент trim_end тот же
Whisper-кэш ключуется по sha1(audio path + mtime + size + model + lang + text hash) — повторный вызов на тот же mp3 моментален и бесплатен.
Partial runs
Orchestrator умеет запускать только часть pipeline:
| Запрос | Что запускается |
|---|---|
| «только тексты» | copywriter → стоп |
| «только озвучки» | (тексты есть) → voiceover → стоп |
| «только сборка» | (озвучки есть) → director → стоп |
| «только субтитры» | (видео есть) → captions → стоп |
| «тексты + озвучки» | copywriter → voiceover → стоп |
| «сборка + субтитры» | director → captions → стоп |
| «с новыми клипами» | clipgen → full pipeline |
Внутренности
Скрипты
| Файл | Что делает |
|---|---|
scripts/check_project.py | Pre-flight check: project.yaml, DB registration, clips count, voices, API keys, ffmpeg |
scripts/api_keys.py | Резолвит API-ключи из project/api_keys.db или env (общий между скиллами) |
scripts/schema.py | Schema source-of-truth (v8). Копия одинакова во всех скиллах |
Таблицы БД, которые трогает (опосредованно через sub-скиллы)
| Таблица | Через какой скилл |
|---|---|
projects | Read (для резолва) |
brief | copywriter |
generated_texts | copywriter |
voiceover_history | voiceover |
clips / video_clips | director |
videos | director |
Конфиг из project.yaml
Orchestrator сам ничего из yaml кроме project resolution не использует — но передаёт куски всем sub-скиллам. Ключевые блоки, на которые он опирается:
language: "ru" # → captions, voiceover
service_directions: [...] # → copywriter (creative_ref пути)
veo: # → clipgen
demographics: ...
voiceover: # → voiceover
model: "eleven_multilingual_v2"
speed: 1.2
captions: # → captions
style: "karaoke"
remotion: # → motionfx
brand: {...}
director: # → director
default_format: "9:16"
music_ducking: true
final_output_dir: "..." # → копия финала за пределы проекта
Output / Delivery
В конце orchestrator выдаёт summary со списком всех файлов:
Production complete: Video 1 (storytelling, 18s): - variant_a: /path/to/video1_variant_a.mp4 - variant_b: /path/to/video1_variant_b.mp4 Video 2 (direct_offer, 12s): - variant_a: /path/to/video2_variant_a.mp4 - variant_b: /path/to/video2_variant_b.mp4 Total: 4 video files Voices used: Rachel (1x), Bella (1x) Clips used: #3, #5, #7, #8, #12, #15
Gotchas и tips
--music в assemble.py в voiceover-пайплайне. Sidechain ducking в assemble делает музыку неслышной поверх нормализованного голоса. В voiceover-pipeline музыка ВСЕГДА накладывается отдельно через overlay_music.py после captions. --music в assemble оставлено только для textover (без голоса — нечем ducking-ать).
audio_process.py убирает их (~5 сек экономии на 30-сек ролике), нормализует до -16 LUFS, чистит низы/верха EQ. Использовать processed-файл для всех последующих шагов, не оригинал.
hook_overlay.py и remotion_captions.py работают standalone — полезно для отладки hook-пресета без перерендера captions. Orchestrator же использует render_final.py по дефолту.
skills/. Если orchestrator в /path/to/skills/video-orchestrator, то copywriter — в /path/to/skills/video-copywriter. Относительно своего пути.
Место в пайплайне
Orchestrator = «зонтик» над всеми остальными. Юзер видит его как точку входа в production. Под капотом — координация и preflight.
Когда использовать orchestrator, а когда — sub-скиллы напрямую: orchestrator — для production-batch'ей («сделай 3 ролика»). Sub-скиллы напрямую — для ручных правок («перегенери только captions», «замени hook»).