Весь «банк живости» одного видео — отдельная стадия 00_Setup/06_Enrichment/ (бывш. _analysis/ внутри Review — теперь свой этап, рядом с 05_Review). Реальна с 25.06.2026 — YTCR01 переведён на эту раскладку (enrichment_build_v41.py), _analysis/ сохранён. Нумерация подпапок = порядок пайплайна (конвенция playbook §1). Важно: сам JSON для монтажа UXP читает не отсюда, а из 02_Assembly/parts/ (↓). Клик по имени папки — копирует его в буфер.
01_Ingest · 02_Assembly · 03_Pre-Edit · 04_ScreenCues · 05_Review — и рядом ↓{CODE}_part_Inserts_v{N}.json только отсюда. Стадия enrichment доставляет сюда готовый overlay-JSON_analysis/). Строится с PreEditing, питает Review + Edit<scene>/<clip>_<k>.jpg. derived — не правим руками, истинный tc — в frames.jsonREADME.txt): {stem}_en.json (words[]·{w,s,e}) канонически живут в 01_Source/Transcription/per_clip/<scene>/; банк линкует их по stem, не копируетlive_catalog.json (entries{"scene/clip_id"} → emotion/liveliness/beauty/live_moment/best_tc/moments)inserts.json (src_in=best_tc)frames · catalog_gen · merge · index_build · index_html · picks_gen · picks_merge · en_emit · build) — копипастится в новый проектROOT·CODE·SRC·TRANSCR·FPS·ENRICH. Цель: скрипты читают пути отсюда (донорские пока хардкодят ROOT — рефактор).vN — вне работыt_sec (frame-level tc); пути кадров относительные (01_frames/…)ytai-part-v1). Рабочую копию стадия доставляет в 02_Assembly/parts/ ↑ — именно её читает UXP Review06_Enrichment/01_frames/<scene>/. Больше нигде.06_Enrichment/03_catalog/ (vision-каталог), сводка — в full_source_index.json.frames.json (кадр→секунда) и full_source_index.json (мастер). Стабильные имена, без версий.02_Assembly/parts/: вкладка Review читает overlay-вставки только оттуда. Стадия enrichment производит JSON и доставляет его туда — внутри 06_Enrichment/ лежит лишь мастер-зеркало. Это та же машинерия, что у вкладки Parts (один движок buildPartSequence + схема ytai-part-v1); Review ≠ Parts только по полю build_model (↓ Схемы).source_path (→ 01_Source) + числовым таймкодам, а не к своему месту. Пути кадров — относительные (от корня стадии). Подробнее ↓ «Перенос · точность».ytcr01_v12_*, что лежали плоско в 01_Media/Source/Setup/Review/_analysis/; APFS-clonefile, _analysis/ цел, операция обратима). Тулинг: scripts/999_extra/enrichment_build_v41.py. Новые проекты заводим сразу по этой структуре; v4.1-донор YTCR04 пока в 00_Setup/05_Review/_analysis/.| слой | что это | где (путь от 06_Enrichment/) | таймкод |
|---|---|---|---|
| 📸 экраны | стиллы исходников по сценам, ~3–8/клип | 01_frames/<scene>/<clip>_<k>.jpg | frame (в карте) |
| 🗺 карта кадров | кадр → клип @ секунда | frames.json | frame t_sec |
| 🎙 транскрипты | пословный тайминг речи | 01_Source/Transcription/per_clip/<scene>/{stem}_en.json | word s/e |
| 🧠 анализ экранов | vision-оценки + точечные моменты | 03_catalog/live_catalog.json | frame best_tc·moments[] |
| 📚 мастер-индекс | все клипы: оценки + транскрипт + tc | full_source_index.json | word + frame |
| 🎬 подбор вставок | живые перебивки под абзацы ката | 04_picks/inserts.json | frame src_in=best_tc |
| 🖥 вход UXP | overlay-JSON, что читает вкладка Review | 00_Setup/02_Assembly/parts/{CODE}_part_Inserts_v{N}.json | frame source_in_sec |
frames.json склеивает их: любой кадр из анализа всегда резолвится в исходник @ секунду.Сцена ценна не «клипом целиком», а конкретным моментом. Поэтому каждый слой несёт оба таймкода, и они сквозными.
{stem}_en.json → words[]·{w,s,e}. Для точного премонтажа фраз — где именно произнесена реплика, чтобы резать ровно по слову.frames.json → frames[].t_sec. Кадр назван {clip}_{k}.jpg (k — порядковый, не tc), истинная секунда — в карте. Сильнейший момент — best_tc: в коде clamp[0,dur], а попадание в реальный сэмпл-кадр обеспечивает vision-промпт («возьми один из ДАННЫХ таймкодов кадров») — ~99% на практике, не отдельным snap-шагом.src_in берётся из best_tc каталога (тайминг от vision), а не от LLM — момент всегда точный.Два вопроса, которые решает раскладка: не теряются ли точные данные при переносе стадии и как таймкод доходит до Premiere без потерь.
source_path (→ 01_Source/Video, не двигается) и числовым таймкодам — не к своему месту. При переносе стадии / смене диска сохраняется точно: все t_sec · s/e · best_tc · moments[], оценки, транскрипты, clip_id/scene. К месту привязан лишь путь к jpg-кадрам — а это derived-кэш: перегенерится или правится prefix-replace'ом (у YTCR01 уже отработано — _path_fix_backup_*). Канон: пути кадров относительные → перенос = ноль правок.HH:MM:SS:FF), не по долям: на границе с Premiere/UXP frame = round(sec × fps) — frame-accurate; fps из project.env (YTCR = 25, per-scene dominant, не форсить 50). Точность сверх кадра нужна для выбора кадра, не для укладки.ytai-part-v1 уже несёт оба: source_in_sec (float-сек, истина) + tc_in:"MM:SS.mmm" (мс-строка) → UXP конвертит в кадры по fps. Так Premiere получает точный кадр, а данные остаются lossless. Сравни с DNA-памятью DJI-sync: μs-точность + frame-correction на границе монтажа.● шаги 1–4 можно гнать заранее на PreEditing (банк готов до монтажа) · ● шаги 5–6 — на Review. Стадия 06_Enrichment одинаковая, где бы ни собиралась.
ffmpeg-граб кадров адаптивно по времени (видео: ~2.5с шаг, 3–8 кадров; <6с → 3 кадра; stills → 1 кадр без -ss). У каждого кадра — точный t_sec. Идемпотентно.
Каждый клип со спичем получает пословный тайминг. Один mlx-джоб за раз (RAM/OOM), фоном. Немые сцены (офис/волейбол/B-roll) пропускаем.
Кадры из 01_frames чанкуются по сценам и идут в vision-агентов (через Workflow). На клип — описание + оценки «под лайв» и точечные моменты с их таймкодами. Честно отсеивают мусор (репост-баннеры, плоские инфографики, блюр) → usable=false.
Сводим ВСЕ клипы (каталог + карта + транскрипты) в один индекс и строим браузерную витрину в стиле портала — фильтр/сортировка по эмоции/живости/красоте/live_moment, превью на best_tc, 🕒.
Vision-ранкер по приоритету live_moment → beauty → emotion предлагает живые перебивки под абзацы ката. src_in не у LLM — берётся из best_tc на merge (тайминг от vision). Реальный шут в приоритете, инста — текстура.
Пересобираем монтажный лист (полный текст + вставки + превью) и overlay-JSON, который доставляем в 02_Assembly/parts/ — оттуда вкладка Review («Build Review-Overlay») кладёт рендер на V1, вставки сверху на V2/V3. Каждая вставка — на свой track/audio_track, keep_audio, in/out в секундах и в таймлайне. Это тот же движок, что у вкладки Parts (buildPartSequence + ytai-part-v1); Review = режим build_model:"overlay_on_base", Parts = absolute-сборка куска.
| поле | значение | 0 → 5 |
|---|---|---|
| emotion | сила эмоции в кадре | 0 = нет · 5 = смех/радость/драма |
| liveliness | движение / действие / спонтанность | 0 = статика · 5 = много движения |
| beauty | кинематографичность | 0 = невзрачно · 5 = golden hour / скайлайн / композиция |
| live_moment | живой момент (bool) | смех · реакция · объятие · спонтанный жест |
| onbrand | по DNA канала (bool) | реальный Дубай / жизнь героя ≠ инста-глянец |
| usable | годен ли вообще (bool) | false = репост-баннер / инфографика / блюр |
| best_tc / moments[] | точный тайминг | секунда сильнейшего кадра + точечные моменты |
moments[].t_sec), а не одну оценку на весь клип. Сводная метрика — live_score = beauty + emotion + liveliness (+3 если live_moment).{
"C5285": { // ключ = clip_id
"scene": "dubai_driving", // keys: scene·d·dur·is_still·source_path·frames·n
"d": "01_frames/dubai_driving", // папка кадров (относительная)
"dur": 31.4, "is_still": false,
"source_path": ".../01_Source/Video/dubai_driving/C5285.MP4", // абсолютный (реальное медиа)
"frames": [
{ "k": 0, "file": "01_frames/dubai_driving/C5285_0.jpg", "t_sec": 1.47 }, // k = порядковый, НЕ tc
{ "k": 1, "file": "01_frames/dubai_driving/C5285_1.jpg", "t_sec": 4.10 }
],
"n": 2
}
}
{ "generated":"…", "project":"…", "cut":"YTCR1_v9_Arty_Dzis.mp4", // рендер, под который индекс
"n":1129, "n_live_moments":207, "n_with_transcript":216, "scenes":{…},
"clips": [ {
"scene":"07_new_office", "clip_id":"C7770", "source_file":"C7770.MP4", "source_path":"…", "dur":29.76,
"usable":true, "visual_type":"talking_head", "desc":"…", "energy":"high",
"emotion":null, "liveliness":3, "beauty":null, "broll_quality":2,
"live_moment":false, "onbrand":true, "tags":["hero_arty","office_work"],
"best_tc":0, "moments":[], // frame-level
"has_transcript":false, "n_words":0, "transcript_text":"", // word-level
"live_score":3.0, "src":"v12" // провенанс прохода
} ] }
{ "schema":"ytai-part-v1",
"part": { // ⚠ part — ОБЪЕКТ, не строка
"code":"YTCR01", "name":"Review_v9_live_inserts", "stage":"Review", "fps":25,
"build_model":"overlay_on_base", // ⚠ ОБЯЗАТЕЛЬНО — иначе скоринг Review-Overlay не выберет файл
"base_clip":"YTCR1_v9_Arty_Dzis.mp4", "base_clip_path":".../03_Exports/…mp4", // рендер → V1
"sequence_name":"YTCR01_5_Review_v9_overlay", "color":"Mango"
},
"tracks":{…}, "audio_policy":"…", "counts":{…}, "changelog":[…],
"segments": [ {
"role":"shown", "track":"V3", "audio_track":"A3", "keep_audio":true,
"scene":"dubai_driving", "clip_id":"C5285", "source_file":"C5285.MP4", "source_path":"…", "is_still":false,
"source_in_sec":0.0, "source_out_sec":3.0, // in = best_tc (vision)
"timeline_in":"00:00.000", "timeline_out":"00:03.000", "timeline_in_sec":0.0, "segment_id":"…"
} ] }
02_Assembly/parts/ — вкладка Review («Build Review-Overlay») выбирает лучший по build_model==='overlay_on_base' × версия × число сегментов, кладёт base_clip на V1, вставки сверху на V2/V3. Тот же движок buildPartSequence, что у вкладки Parts — разница лишь build_model (overlay_on_base ↔ absolute). keep_audio сохраняет аудио вставки (VO-над-B-roll), source_in_sec = момент из каталога. (Обратная сортировка по одинаковому tc — в отдельном «recommended»-пути UXP, не в этом overlay-билдере.)Эталон — донор YTCR01: набор ytcr01_v12_* (frames · catalog_gen→workflow · merge · index_build/html · picks_gen/merge · build + en_emit). С 25.06.2026 собран в 06_Enrichment/_tools/ (см. enrichment_build_v41.py). Для нового видео — скопировать _tools/ и заполнить project.env. Оговорка: донорские скрипты пока хардкодят ROOT на старте модуля — чтение из project.env это запланированный рефактор.
00_Setup/05_Review/HANDOFF_source_video_enrichment.md в проекте — самодостаточный бриф (что готово, что добить).06_Enrichment/_tools/ и заполнить только project.env (ROOT·CODE·SRC·TRANSCR·FPS) — скрипты читают пути оттуда, сам код не трогаем.00_Setup/06_Enrichment/ (нумерованные подпапки + _tools/project.env); донор-исток плоский: v4.0 — 01_Media/Source/Setup/Review/_analysis/, v4.1 — 00_Setup/05_Review/_analysis/ (имена {code}_v12_* без подпапок). Привести к канону: enrichment_build_v41.py --project <path> --execute.-ss
🎙 один mlx за раз (OOM)
🧹 vision: usable=false на мусор
🔢 планировщик даёт clip_id с префиксом scene/ → стрипать