Multi-Project Архитектура

Как организован ~/video-projects/, что лежит в каждом проекте, как Claude находит нужный проект из user-команды, что внутри project.yaml и brand.yaml.

Корневая директория

~/video-projects/
├── director.db                       # ← shared SQLite (schema v8)
├── _specs/                           # внутренние RFC и заметки по архитектуре
├── basdent/                          # ← project 1 (стоматология)
├── apparatus/                        # ← project 2 (медтехника B2B)
├── sweepstake/                       # ← project 3
├── performante-ai-agency/            # ← project 4 (внутренний — собственное агентство)
└── ...другие проекты...
Важно: director.db лежит в КОРНЕ ~/video-projects/, а НЕ в папке отдельного проекта. Все db.py скрипты ищут БД на один уровень выше своей --project-dir. Если ты запустил db.py внутри ~/video-projects/basdent/scripts/ и БД пустая — посмотри уровнем выше.

Структура одного проекта

~/video-projects/basdent/
├── project.yaml                      # ← главный конфиг проекта
├── brand.yaml                        # ← для creative-* скиллов (colors/fonts/voice)
├── brief.md                          # ← бриф клиента (что за бизнес, услуги, тон)
├── api_keys.db                       # ← per-project API keys (опционально)
│
├── references/                       # ← reference photos для Veo / Gemini Image
│   ├── ref_doctor_avatar.jpg
│   ├── ref_clinic_interior.png
│   └── ref_xray_machine.jpg
│
├── creatives/                        # ← шаблоны creative-reference для разных услуг
│   ├── checkup.md                    # ← reference creatives для услуги «чекап»
│   ├── implants.md
│   └── braces.md
│
├── transcripts/                      # ← расшифровки лучших клиентских роликов
│   ├── client_2024_q4_top1.txt
│   └── ...
│
├── clips/                            # ← клипы из Veo / user-uploaded (физические файлы)
│   ├── clip_001_doctor_smile.mp4
│   ├── clip_002_office_pan.mp4
│   └── ...
│
├── voiceovers/                       # ← сгенерированные .mp3 (ElevenLabs)
├── videos/                           # ← готовые .mp4 (после director'а)
├── posters/                          # ← статика (после creative-poster)
│   └── carousel_/             # ← одна папка на одну карусель
│       └── slides/                   # ← PNG-секвенция слайдов
│
├── carousel-remotion/                # ← per-project Remotion app для каруселей (NPM-проект)
│   ├── package.json
│   ├── src/
│   │   └── ...
│   └── public/photos/                # ← копии refs для slides
│
├── explainer-remotion/               # ← per-project Remotion app для explainer-видео
│   ├── package.json
│   └── ...
│
└── prfmnt-creo/                      # (опционально) кастомный final-output dir
                                      # см. project.yaml → final_output_dir

Зачем `carousel-remotion/` и `explainer-remotion/` per-project?

Чтобы можно было редактировать TSX-шаблоны под конкретного клиента не ломая других. init_project.py копирует remotion_template/ из скилла в проект и патчит src/lib/brand.ts цветами из brand.yaml. Если клиенту нужен особенный layout слайда — правится TSX в его папке.

project.yaml — главный конфиг

Это «паспорт» проекта. Все скиллы читают project.yaml при старте и берут оттуда параметры (вместо хардкода или повторного спрашивания юзера).

name: "Bas Dent"                       # отображаемое имя
slug: basdent                          # машинное имя = имя папки
niche: dentistry                       # для матчинга на competitor_refs.niche
city: Almaty
language: ru

# Бизнес-контекст
service_directions:
  - slug: checkup
    name: "Чекап (consultation)"
    description: "Первый приём с осмотром и снимком"
    price: "10 000 ₸"
    reference_creatives: "creatives/checkup.md"
  - slug: implants
    name: "Импланты"
    description: "..."
    price: "от 250 000 ₸"
    reference_creatives: "creatives/implants.md"

# Demographics для Veo
veo:
  demographics:
    age_range: "25-50"
    gender_skew: "60% female"
    region: "Almaty / Kazakhstan"
  scene_context: |
    Modern dental clinic in Almaty. Patients are middle-class
    Kazakhstanis, doctors are local. NO equipment branding visible.

# Voiceover settings
voiceover:
  default_voice_id: "21m00Tcm4TlvDq8ikWAM"   # ElevenLabs
  model: eleven_multilingual_v2
  speed: 1.0

# Director settings
director:
  aspect: "9:16"                       # default output aspect
  fps: 30
  transitions: "cuts_only"             # cuts_only / fades / mixed
  music_ducking: -10                   # dB under voiceover
  default_music_volume: 0.20           # 0.20 для TTS, 0.08 для real-mic

# Captions settings
captions:
  style: karaoke                       # karaoke / bold / minimal / pop / tiktok
  language: ru
  highlight_color: "#FFD700"

# Brand для Remotion (motion graphics)
remotion:
  brand:
    primary: "#0B5FAE"
    accent: "#FFD700"
    font_display: Unbounded
    font_body: Manrope

# Опционально — кастомный final-output для готовых видео
# (по умолчанию это videos/ внутри проекта)
final_output_dir: "/Users/anatolijstepanov/Desktop/basdent_final/"

# Опционально — Meta Ads config (для perf-import)
meta:
  ad_account_id: "act_804392739179929"
  page_id: "123456789"
  pixel_id: "..."
Минимальный project.yaml — только name, slug, niche, city, language. Остальное опционально (скиллы используют дефолты). Полный конфиг постепенно достраивается по мере роста клиента.

brand.yaml — для creative-* скиллов

Отдельный файл потому что brand.yaml — это про визуальный стиль (как выглядят креативы), а project.yaml — про бизнес-логику (что за услуги / какой voiceover). Творческие команды могут править brand.yaml не лазая в project.yaml.

name: "Bas Dent"
tagline: "Стоматология нового поколения"

colors:
  primary: "#0B5FAE"      # основной (для bg, headlines)
  navy: "#062A5C"         # тёмный bg
  cyan: "#00BFFF"         # accent для подзаголовков
  red: "#E63946"          # для пометок «акция», urgency
  gold: "#FFD700"         # для PROFIT-цифр (без кнопки!)
  white: "#FFFFFF"
  text_dark: "#0E1B2C"

fonts:
  headline: Unbounded
  body: Manrope

voice:
  tone:
    - дружелюбный
    - экспертный
    - без агрессии
    - короткие предложения
  forbidden_words:
    - дешево
    - распродажа
    - акция только сегодня
    - последний шанс

references:
  - path: "references/ref_doctor_avatar.jpg"
    role: "doctor face"
    notes: "Используется в hero shots"
  - path: "references/ref_clinic_interior.png"
    role: "clinic interior"

# Для creative-explainer-video — VO settings (если отличаются от project.yaml)
vo:
  provider: elevenlabs
  voice_id: "21m00Tcm4TlvDq8ikWAM"
  model: eleven_multilingual_v2
  stability: 0.5
  similarity_boost: 0.7

Project resolution — как Claude находит проект

Когда юзер пишет «сделай 3 ролика для basdent», video-orchestrator резолвит target project по такой логике:

ПриоритетИсточникПример
1Explicit slug в команде«для basdent» → ~/video-projects/basdent/
2Explicit path в команде«в ~/video-projects/apparatus»
3State-файл текущего проекта~/.claude/state/current-project.json (опционально)
4Спросить юзера«Какой проект: basdent / apparatus / sweepstake?»
Все скиллы должны явно передавать --project-dir или --project <slug> своим скриптам. Никогда не предполагай «текущий проект» в Python-скриптах — это путь к багам когда юзер работает с двумя проектами параллельно.

Как создать новый проект

Используй скилл video-project-setup:

You: «добавь новый проект для клиники Boston Dental в Шымкенте»

→ skill запускается, задаёт уточняющие вопросы:
  - slug? (boston-dental)
  - niche? (dentistry)
  - city? (Shymkent)
  - language? (ru)
  - service_directions? (чекап, импланты, виниры?)

→ создаёт ~/video-projects/boston-dental/ со всей структурой
→ генерит project.yaml (минимальный)
→ генерит brief.md (с шаблоном)
→ создаёт references/, creatives/, voiceovers/, videos/ папки
→ регистрирует в `projects` таблице через INSERT
→ опционально: линкует voices/music от других проектов

После этого можно сразу запускать любой пайплайн.

Cross-project ресурсы (junction-таблицы)

Один клип / голос / музыка может принадлежать нескольким проектам. Это полезно для evergreen-материалов (например, общий B-roll для всех стоматологий).

Механика: ресурс лежит в основной таблице (clips, voices, music), связь с проектом — в junction-таблице (project_clips, project_voices, project_music).

-- Добавить клип, который доступен и basdent, и boston-dental
INSERT INTO clips (path, description, duration) VALUES (...);
-- clip_id = 42

INSERT INTO project_clips (project_id, clip_id) VALUES (1, 42);   -- basdent
INSERT INTO project_clips (project_id, clip_id) VALUES (5, 42);   -- boston-dental

Подробнее по всем junction-таблицам и SQL-запросам — на странице БД.

API-ключи: где хранятся и как резолвятся

3 источника, в порядке приоритета:

  1. --api-key <key> аргумент CLI (для тестов)
  2. ~/video-projects/<slug>/api_keys.db — per-project SQLite-таблица api_keys (name, value)
  3. $GOOGLE_API_KEY, $ELEVENLABS_API_KEY, и т.д. в env

Per-project хранение нужно когда у одного клиента свой ElevenLabs-аккаунт (разделение биллинга), у другого — другой Gemini API-key. По дефолту берём из env.

Что лежит в `_specs/`

Внутренние RFC и заметки по архитектуре. Не обязательно для запуска системы, но полезно если хочешь понять «почему так сделано».

~/video-projects/_specs/
├── 2025-10-multi-project-design.md      # как пришли к junction-tables
├── 2025-12-creative-poster-rules.md     # почему запрещены CTA-кнопки в poster
├── 2026-01-gr1-preview-pages.md         # обоснование GR-1
└── ...

🔓 Backend-agnostic (2026-05-19)

Higgsfield AI был required dependency для нескольких частей системы. После аудита в мае 2026 — стал опциональным backend. Higgsfield дёргаем только там где он реально незаменим. Остальные пути — local или альтернативные провайдеры.

До → после

Часть pipeline Было (Higgsfield-required) Стало (backend-agnostic)
Brand auto-fetch при онбординге higgsfield marketing-studio brand-kits fetch --url DEFAULT = scripts/brand_fetch.py (BeautifulSoup + meta theme-color + CSS HEX + Google Fonts detection + logo extraction). Higgsfield через --use-higgsfield только если local confidence < 0.5
Product page parsing higgsfield marketing-studio webproducts fetch --url DEFAULT = scripts/product_fetch.py (schema.org Product JSON-LD + OpenGraph + gallery scraping для Shopify/WooCommerce/Amazon)
Product-photoshoot (10 modes) higgsfield product-photoshoot create --mode DEFAULT = Gemini 3 Pro Image через creative-poster с явными prompt templates для всех 10 modes. Higgsfield opt-in только для auto-branding с brand_kit_id
Scene regen в video-clone-competitor Жёстко video-clipgen-higgsfield/gen_video.sh regenerate.py --backend {auto | higgsfield | veo}. Auto разводит сцены: Soul-ID / cinematic camera → Higgsfield; generic → direct Veo. ~50% экономия.
MCSLA prompt knowledge Документировался как Higgsfield-specific Явная пометка: backend-agnostic — MCSLA, 10 жанров, Cinema Studio docs работают для Veo / Sora / Runway / Luma / Pika тоже

Что осталось Higgsfield-only (и почему оправдано)

  1. Soul-ID face training — единственный generally-available video AI provider с persistent face training. Veo/Runway/Sora не умеют. Mitigation: используется только для проектов где critical face consistency (talking-head, founder-led ads).
  2. Cinematic Studio V2/V3 camera moves (robo-arm orbit, vertigo, FPV drone, dolly zoom) — Veo не контролирует надёжно. Mitigation: auto-routing в clone-competitor определяет это по keywords в MCSLA.camera и направляет только нужные сцены через Higgsfield.
  3. Marketing Studio auto-branding (логотип + цвета overlay) — опционально, только если есть brand_kit_id от прошлого auto-fetch И юзер явно хочет.

Cost reduction (реальные примеры)

СценарийOld (Higgsfield-heavy)New (mixed/local)Savings
Brand auto-fetch при онбординге$0.06$0.00100%
5 static ad creatives$1.00 (Higgsfield)$0.20 (Gemini)80%
10-сценовый clone reel$10-15$5-7 (auto-routing)~50%
Cinematic founder portrait orbit$1.50$1.50 (Higgsfield-only)0% — оправдано

Финальная картина зависимостей

                                       ┌─────────────────────┐
            ┌──────────────────────────│  HARD dependencies  │
            │                          │  (нельзя убрать)    │
            │                          └─────────────────────┘
            │
            ↓
  Higgsfield CLI/Cloud (Soul-ID + Cinematic Studio camera moves)
  Google Cloud Veo 3.1 (direct video gen — основной video backend)
  ElevenLabs (TTS — single-vendor для voiceover)
  Anthropic Claude (LLM — single-vendor для in-session reasoning)
  Google Gemini 3 Pro Image (Image gen — основной static backend)

                                       ┌─────────────────────┐
            ┌──────────────────────────│  Now backend-       │
            │                          │  agnostic           │
            │                          └─────────────────────┘
            ↓
  Brand/product extraction → local scraper (default) → Higgsfield (optional)
  Image gen → Gemini (default) → Higgsfield (when auto-branding)
  Video regen в clone → direct Veo (default) → Higgsfield (Soul-ID/camera only)
  Instagram discovery / analysis → HikerAPI (no Higgsfield)
  Concept generation → LLM in-session (no external API)

Дальше