◂ Шортсы из выпускаRYA.AEShorts · Cases, Checks, Knowledge — шортсы машиной: случаи, проверки, знания, ошибкиэтап · 5 окт 2026
Этап шортсов на 02.10.2026 целиком: все случаи, которые он уже прошёл (разговор за столом, документальный выпуск с перебивками, из собранного фильма, из исходных дублей, разделённый кадр, выноски и музыка, пересборка с 4K, фильм фонда с вшитыми экранами — два пакета), модели и движки с версиями, проверки с порогами из кода, файлы, в которых этап учится, грабли и что остаётся руками. Как устроен сам этап по шагам — на Shorts from a Finished Episode; главное одним экраном — в тикете.
📌 Три решения Романа 02.10.2026, ставшие кодом. Героя слушаем, а тех, о ком он говорит, показываем перебивками в эти же моменты (поле broll, плашка — чем человек важен зрителю). Рез — в паузе между словами с точностью до кадра, с автопроверкой (edges, edges.strict). Новых сущностей не создавать: шортсы в 04_Shorts, новая версия номером в имени, прежняя рядом.
Одним взглядом
20–⁠60с
длина куска: 20 ≤ dur < 60
отборщику задано 25–⁠59 с
≤ 0,30с
тишины после последнего слова
перед первым ≤ 0,15 · до чужого слова ≥ 0,05
≥ 1,0с
речи на своём крупном плане — плашка
держится 2,8 с (YTFP 3,6), гаснет со сменой кадра
~10в сутки
заливок нового канала, удалённые в счёт
упёрлись — стоп сразу, доливка pending.py раз в 2 ч
1Схема2Случаи3Модели4Ворота5Проверки6Знания7Грабли8Сдача9Команды10Где лежит

15.2 · 1Схема: от мастера до выхода

📥 Вход
Мастер 16:9 4Kвыпуск · чистый мастер фильма · мастер из дублей
+
Слова с ролями.words.json · SRT с ролями · JSON-реплики
+
Профиль + заданиеshorts_profile.json · {CODE}_shorts_job.json
🎯 Отбор
transcriptреплики с ролями + задание отборщику
→
Draper8–10 кандидатов, пять с take
→
picksдлина, запреты, keep_out, broll
→
Пятёркаутверждает Роман
🎞 Кадр
scoutсклейки, каталог кадров, лица
→
brollкадры к фразам — человек
→
probe · gfxодежда, места; знак, плашки
→
viz · musicвыноски, трек под длину
✂️ Края и рендер
edges --fixCTC + огибающая + кадр
→
render --dryплан по секундам
→
render --version N04_Shorts; сам сверяет края и мелькания
→
sheetлист кадров — глазами
▶️ Выход
uploadunlisted, --sni-bypass
→
pending.pyлимит ~10/сутки → доливка раз в 2 ч
→
scheduleпо слову Романа
→
launchd → publicкаждые 5 мин, ⛔ в Telegram
🗂 Сдача
telegram«Избранное», превью на 1 с
+
drive04_Shorts + исходники 07_Shorts
+
ledgerContentList ✓, Trello
+
statusчто на YouTube, что осталось
+
Хаб, Related videoруками
машиначеловек решает или смотритагент Claudeитог дорожки

Фиолетовая рамка — агент Draper; пунктир — человек. Из кода этапа ни LLM, ни VLM не вызываются: отбор — агент по заданию, проверка — код.

15.2 · 2Случаи, которые этап уже прошёл

1Разговор за столом из готового выпускаYTTRBM01
  • один–четыре человека, камеры на штативах; ведущие и места за столом — в профиле канала (hosts · seat), одежда дня — в задании (wear)
  • крупный план → кроп 608×1080; общий → наезд 456×810 на говорящего; рамка не чаще раза в 1,2 с
  • выход каждые 6 ч (cadence_hours), пять шортсов за вечер
  • мастер был 1080p — растяжение ×1,78–2,37; ждёт 4K → v3
задание в ~/.cache/ytai/shorts/YTTRBM01_07_Shorts/
2Документальный выпуск: один герой, перебивкиYTFP01
  • broll 37–47 % времени шортса: 3–6 перебивок по 2–5 с, открывает всегда герой (broll.from 2,5)
  • плашка словарём {lines, sub} и стиль .plate.lead: «Мама двоих детей с кохлеарными имплантами», имя подписью; держится 3,6 с; plate_from
  • crop.close_face 100, у героя только seat (ложные лица на телевизоре и игрушках); keep_out — красная линия канала и чужой материал; edges.strict
  • титры глав: кусок начинать после титра, вопрос возвращать уточнением в скобках; карта кадра по ключевым кадрам делается руками
три версии за день: v1 08:32 → v2 13:10 → v3 19:00
3Из собранного фильмаautocut → shorts
  • shorts_master.py words · map · build · verify --head N --name CODE_vN: чистый мастер 4K на времени фильма — камера во весь кадр, речь и воздух без музыки и графики
  • words — расшифровка в формате wordrole с ролями из листа (= ключи people); map — кто говорит · что в кадре · какой экран · ✂ скачки внутри камеры
  • crop.close_face поднимать над лицами общего плана (165), иначе при двух «крупных» лицах рамка уходит на молчащего; плашка только на кадре во всю высоту
{cache}/shorts_master/<имя>_clean_4K.mp4 · 00_Setup/07_Shorts/<имя>.words.json
4Из исходных дублейYTEVO02
  • решение Романа: «монтаж шортсов лучше делать из исходников» — src_master.py plan · video · audio · encode · words в _session_tools проекта: 7 отрезков двух камер, цвет и чистка речи фильма, −14 LUFS, без музыки
  • слова расшифровок исходников перенесены на время мастера; реплики-JSON: одна реплика = один субтитр, начало по острову речи (cues_build.py)
  • конец шортса — конец этой же мысли: слушать, что звучит ПОСЛЕ реза (listen.py), смотреть последний кадр
YTEVO02_src_clean_4K.mp4 · YTEVO02_src.words.json
5Разделённый кадрYTEVO02
  • спикер сверху, панель графики снизу: отдельное задание …_job_split.json с crop.headroom 0,24 — лицо по центру верхней части (обычный общий план — 0,31, по умолчанию 0,36)
  • панель — выноска viz на весь шортс, включая последний кадр (viz_all.py FULL)
  • всё значимое левее 945 px — справа кнопки YouTube; плашку человеку с общего плана — в выноске
…_job_split.json
6Варианты: выноски и музыкапо желанию
  • viz: number (счётчик за 0,8 с) и phrase, ≤ 2 на шортс, низ карточки 1215 px, ≥ 1,2 с до конца; проект viz/S{NN}/ можно дорисовать скиллами /hyperframes
  • music --find → --track <id>: трек ≥ 45 с без вокала, EditRecording ровно под длину; уровень = LUFS речи − 21 дБ (below_db), фейды 0,3 / 0,8 с
  • сменилась длина шортса — music --track и viz заново (допуск 0,5 и 0,2 с); render --plain — без вариантов
viz/S02.mov · music/S02.wav
7Пересборка с 4K-мастераYTTRBM01
  • find4k по Drive проекта (видео горизонтальное, длина ±2 с, меньшая сторона ≥ 2160) → иначе 4K-экспорт того же монтажа у монтажёра
  • check сверяет новый мастер по звуку с эталоном master_ref.m4a: ✅ тот же · ⚠ сдвиг → master_offset · ⛔ другой монтаж
  • render --version N только невышедших → upload → schedule без --start; эталон — только из самого мастера (копия с YouTube отстаёт на 36 мс)
master_ref.m4a пишется при первом рендере, 6 МБ
8Соседний трек — вкладка Shorts в Premiereне этот этап
  • кадр ставит монтажёр во вкладке Shorts панели UXP; build_brief.py, annotate_frames.py с локальной VLM Qwen2-VL-2B
  • когда шортсу нужна сложная графика или кадр, который машина не поставит
пилот YTCR01 v16
9Фильм фонда с вшитыми экранами — два пакетаYTCH14
  • мастер — фильм кодом (0511_doc_cut), в картинку вшиты все экраны: подписи, вопросы из-за кадра, цитаты, главы, «шторки» с QR. keep_out считается из листа экранов тем же временем, что ставило их в фильм (±0,12 с, 58 мест), scope broll: кусок со звуком идёт через экран, а его картинку закрывает перебивка — проверка check_cover.py «всё закрыто»
  • каталог кадров фильма для перебивок из листа edl_vN.json: каждый кадр между склейками, что в нём, части «можно брать» вне keep_out — по нему Draper сам ставит broll (дети, малыш, вещи, дом)
  • два пакета: YouTube без субтитров в кадре (captions.burn: false) + дорожки RU/EN у каждого шортса; Инстаграм — render --insta в 04_Shorts/Instagram; реплики — из вычитанных субтитров фильма (ru + en)
  • одежда для плашек — probe на финальном мастере: цвет новой версии развернул оттенки (у героини тёплый серый, у куратора холодный), допуск ±9; два лица на диване, где крупнее молчащая, — рамка на говорящей руками, перебивками «губы в такт» (тот же кадр фильма)
  • мелькания: кусок рамки в 1 кадр между перебивками; край перебивки прилипает к смене рамки ближе 8 кадров (0,3 с × 25) и открывает хвост экрана фильма; источник перебивки после прилипания вылезает на кадр за склейку — края встык, дальше 8 кадров от смены, источник раньше на 0,05 с
5 шортсов по ссылке с дорожками RU/EN · правки по листам: S02 v2, S01 v3 · Инстаграм-пакет рядом · плейбук канала YTs/YTCH/TICKET_YTCH_playbook_from_YTCH14.md
YTFP01: три версии за день
08:32
v1 — одна говорящая головаРоман вернул: детей не видно; мелькнул кадр — 12 кадров в 4 шортсах из 5
13:10
v2 — перебивки broll, 37–⁠47 %рез внутри слова: «хоро|шо», «молод|цы», хвост «-тей»
19:00
v3 — край по словамedges --fix + edges.strict: рез в паузе, до кадра

Каждая версия оставила проверку: мелькнувший кадр (v1), поле broll с проверками (v2), край в паузе (v3). Счёт кадров v1 — README этапа.

15.2 · 3Модели и движки

ДвижокГде в кодеГде работает · замокВеса, ключи
mlx-whisper large-v3 (word_timestamps, condition_on_previous_text=False; --language ru)wordrole_transcribe.pyмак; замок сам не берёт — запускать под mlx_queue.pyHF-кэш
pyannote speaker-diarization-3.1wordrole_transcribe.pyмак, MPS~/.cache/huggingface/token
torchaudio MMS_FA (CTC, with_star)edges.pyмак, процессор; flock mlx.lock, ждёт до 1800 с~/.cache/torch/hub/checkpoints/model.pt — 1,26 ГБ, вне git
YuNet cv2.FaceDetectorYN (score 0,6, NMS 0,3, top_k 50)render.py · scout.pyмакenvironment/models/face/yunet.onnx — вне git
Агент Draper (rya-draper) по PICKS_PROMPT.mdtranscript → picks.jsonClaude Code; модель сессиииз кода LLM не вызывается
headless Chrome (--headless=new, virtual-time-budget 8000, прозрачный фон)gfx.pyмакшрифт с Google Fonts — без сети подменится
HyperFrames 0.8.106 + GSAP 3.14.2 (lint → render --format mov --workers 1)viz.pyмакProRes 4444 с альфой 1080×1920
Epidemic Sound MCP (JSON-RPC без Claude: SearchRecordings, EditRecording, Poll, Download)music.pyмак, работает и из launchdEPIDEMIC_SOUND_API_KEY или ~/.config/ytai/epidemic_sound.env (600)
ffmpeg libx264 -preset slow -crf 12 -maxrate 40M, AAC 320k 48 кГц, +faststart; склейки -fps_mode passthroughrender.py · job.pyмак; без videotoolbox и без очереди рендерасубтитры — поток PNG (libass нет); эталон звука — моно 8 кГц AAC 24k
YouTube Data API v3: videos.insert (resumable, 8 МиБ, дедуп по названию) · list(status) · update → publicupload_youtube.py · shorts.py · scheduled_publish.pyмак; --sni-bypass через www.googleapis.com, IPv4токен канала в channels.json: youtube.upload + force-ssl
Telethon: SaveBigFilePart 512 КБ × 8 потоков, до 2 ГБtg_send.py/opt/homebrew/bin/python3~/.config/ytai/tg_user.session
rclone copy --bind en0 --drive-chunk-size 64M; Drive API v3; Sheets v4; Trello RESTshorts.py drive · ledger.pyмакgdrive_rscore · token.json · trello.env

Memex этап не использует. render_gate.py — только у src_master/shorts_master (сборка мастера), не у render.

15.2 · 4Ворота шортса: от отбора до выхода

Каждый шаг пропускает шортс дальше только через свой порог; подробно — в таблице «Проверки» ниже.

1
ОтборагентDraper: 8–⁠10 кандидатов, пять в работу✓ picks: 20 ≤ dur < 60 с · keep_out · forbid
2
Края по словаммашинаedges --fix: CTC + огибающая + кадр✓ ≤ 0,30 с после · ≤ 0,15 до
3
Рендер версиимашинаrender --version N → 04_Shorts⇒ ⚠ мелькнул кадр, растяжение > ×1,25✓ edges.strict: рез в слове — стоп
4
Лист и «ок» Романачеловекsheet — кадр из каждого куска рамки; черновики — файлами
5
Заливка по ссылкемашинаupload, --sni-bypass✓ forbid · ~10 в сутки → pending.py
6
Выход по графикумашинаschedule → launchd раз в 5 мин → public⇒ сбой → ⛔ в Telegram
↺ правка — новая версия: render --version N+1 → upload → schedule без --start
машиначеловекагент
Пороги из кода на шкале
Длина кускас · picks, render
< 60 — YouTube20 — гейт кода
04080

Код пускает 20 ≤ dur < 60 с, отборщику задано 25–⁠59 (job.py: duration 20…60).

Воздух на краю кускас тишины до слова · edges.py
0,30 после последнего0,15 перед первым
0

Не ближе 0,05 с к чужому слову; смычка согласной 40–⁠110 мс — не пауза; рез на границе кадра.

Плашка: речь на своём крупном планес · render
≥ 1,0 — ставится
01234

Держится plate.seconds 2,8 с (YTFP 3,6); место, где простоит ≥ 1,5 с; гаснет со сменой кадра.

Растяжение кадра из мастера× · render печатает ⚠
×1,25×1,78×2,37 YTTRBM01
123

Мастер 1080p → find4k по Drive проекта, check по звуку; невышедшие — новой версией.

нормана гранибрак

15.2 · 5Проверки: пороги из кода

ПроверкаКогдаНормаОткуда взялась
Длина кускаpicks · render (гейт ok)20 ≤ dur < 60 с (отборщику задано 25–59)YouTube считает шортсом ≤ 60 с
Запретные участкиpicks · renderкусок не задевает keep_out (all | pieces); перебивка — не из keep_out (all | broll)красная линия канала, мультфильм и песня — чужой материал (YTFP01)
Упаковкаpicks · uploadtitle ≤ 70 знаков; slug 2–6 слов; нет forbid в title/description/tags (подстрока без регистра)ссылки и стоп-слова канала («Сколково» у YTTRBM)
Уточнения и выноскиpicksid внутри кусков; текст без скобок совпадает с репликой ≥ 0,7; выносок ≤ 2выноска вставала на чужую реплику
Перебивки brollpicks · renderначало ≥ broll.from; длина ≥ 1,0 с; src внутри мастера; x 0…1, zoom 1…2; без наложений; зазор либо встык, либо ≥ 1 с; край ближе 0,3 с к смене рамки прилипает к ней; короче 2 кадров — не ставитсяYTFP01 v2: поле broll новое, каждая ошибка — отдельная проверка
Край в паузеedges · renderпосле последнего слова ≤ 0,30 с тишины, перед первым ≤ 0,15; не ближе 0,05 с к чужому слову; порог тишины 5-й перцентиль + 0,35·(95-й − 5-й); пауза < 0,12 с — рез посередине; рез на границе кадра; допуск сверки 0,011 сYTFP01 v2: «хоро|шо», «молод|цы», хвост «-тей»
Буква не чужаяedgesбуква, отделённая тишиной > 0,15 с, отбрасывается; слова слиты (склейка выпуска) — рез на склейке в ±0,15 скрайняя буква цеплялась за похожий звук соседа
edges.strictrender⛔ край → не собирать (обход --no-edges)решение Романа 02.10: автопроверка реза
Мелькнувший кадрrender → warn → statusполоса кадра crop=iw:ih*0,375; всплеск > 12 в ≥ 60 % блоков и > 4× 75-го перцентиля соседей; две склейки ближе max(2 кадра, 0,1 с)YTFP01 v1: 12 кадров нового ракурса со старой рамкой
Склейкаrenderразность кадров 192×108 > max(14, 5×медиана), не чаще 0,2 с; склейки < 0,1 с вливаются в соседнююкороткая склейка выбрасывалась — картинка короче звука на 62 мс
Рамкаrenderлицо ≥ close_face 120 px → крупный план; наезд, если лицо видно ≥ 60 % речи; дорожка ≥ 12 % замеров; имя по одежде ≥ 30 % и ≥ 2 замера; держится в пределах 70/50 px, не чаще раза в 1,2 срука и тень давали «лицо»; ведущая затылком
Плашкаrenderтолько крупный план и речь ≥ 1,0 с; держится plate.seconds (2,8; YTFP 3,6), ищется место, где простоит ≥ 1,5 с; гаснет со сменой кадра; не раньше plate_fromYTFP01 v1: плашка героини легла на педагога из перебивки
Растяжение кадраrender → warn≤ ×1,25 (⚠ выше)YTTRBM01: из 1080p ×1,78–2,37, мягко
Фейдыrenderне длиннее тишины у края, минимум 5 мс (по умолчанию 0,08 / 0,15)фейд 40 мс съедал хвост гласной
Та же версия уже залита · файл версии уже лежитrenderотказ (обход --force)нельзя затереть прежнюю версию в 04_Shorts
Мастерrender · check · find4k16:9; check: окна 12 с, сходство ≥ 0,3, FRAME 45 мс → ✅ same / ⚠ offset / ⛔ other; find4k: длина ±2 с, сторона ≥ 2160тишина давала «сходство 124» — тихие окна не сравниваются
Заливкаuploadпропуск при forbid, ok=false, нет файла; 300 с без вывода — стоп; uploadLimitExceeded → стоп сразу + команда pending.py add; прочие сбои — до 40 повторов40 повторов упирались в лимит
Графикschedule--start с поясом; шаг --every или cadence_hours; replaced снимаются; ⚠ приватный; ⛔ задача launchd не загружена; без --start нужно прежнее время в будущемpublishAt делал ролик приватным
Публикатор и доливкаlaunchd3 повтора запроса; удалён → gone + ⛔; сбой → ⛔ сразу и не чаще раза в час; доливка не позже чем за 20 мин до срока; залито, но не в графике → ⛔первые боевые срабатывания — 03.10
Что на YouTubestatusвышел / по ссылке / ⚠ приватный / ⚠ нет на YouTube / ⚠ не в графике; прежняя версия в графике; все warnпосле каждой заливки — запросом к YouTube, не по журналу
Звук = видео по длине—отдельной проверки пока нетхэндофф «Что дальше»: одна команда приёмки

15.2 · 6Где этап учится: файлы знаний

ФайлЧто хранитКто и когда пишет
YTs/{CH}/shorts_profile.json (ytai-shorts-profile-v1)channel · accent · gfx · captions.{font,size,max_width,bottom,…} · plate.{x,y,seconds,min_speech} · brand · hosts.<Имя>.{plate,role,seat} · youtube.{slug,category,language,tags} · cadence_hours · forbid[] · rules[] · hashtags[] · sheet · trello · broll.from · edges.strictсессия по решению Романа, причина в *_note (YTFP: broll_note, edges_note, plate_note); новый канал — копия у YTTRBM
YTs/{CH}/shorts_gfx.html#brand, .plate, .plate.lead, <!--PLATES-->руками по бренду; .plate.lead есть у YTFP — другим каналам добавить до использования
{CODE}_shorts_job.json (ytai-shorts-job-v1)master · cues · roles · picks · version · master_offset · people.<Имя>.{wear, seat, plate | {lines, sub}, role, big_face} · wear_order · tags · drive · masters · drive_work · keep_out[{from,to,why,scope}] · crop.* · edges · music.below_db · captions.max_width · pad · audio_fadeчеловек или агент на выпуск; факты дня съёмки (одежда) — только сюда, не в профиль
picks.jsoncandidates[{rank, take, pieces[{from_id,to_id} | {start,end}], scores, why, title, description, slug, clarifications, viz, broll, plate_from}]Draper; broll — человек по каталогу scout; edges --fix переписывает куски (3 знака), сдвигает broll.at и plate_from
PICKS_PROMPT.mdзадание отборщику: {PROJECT} {TITLE} {CHANNEL} {TRANSCRIPT} {SPEAKERS} {CONTEXT} {HASHTAGS} {RULES} {PICKS} {CHECK}сессия при новом правиле отбора
edges.json · out/manifest.json · master_ref.m4aкэш краёв; n, name, dur, ok, pieces, cuts, broll, warn, upscale, viz, music, video_id, replaced, publish_at; эталон звука мастеракод; манифест после каждого шортса
broll/README.md · broll/cuts.jsonзанятые кадры выпуска (один кадр не повторять в двух шортсах); склейки мастерачеловек; scout cuts
~/.config/ytai/publish_schedule.json · shorts_pending.json[{channel, video_id, publish_at, done, error_at, gone}] · [{job, only, not_before, told_at}]schedule, pending.py add; читают задачи launchd
README этапа «Каноны», «Грабли»; 07_shorts/README.md; CLAUDE.md «Shorts»каноны этапа и имена {CODE}_S{NN}_v{N}_{slug}сессия после ошибки, тем же коммитом
память: reference_shorts_finished_pipeline · feedback_shorts_show_subject_broll · feedback_shorts_from_sources · reference_whisper_word_edges_unreliableрешения Романа с «почему»сессия в конце работы

15.2 · 7Ошибки и грабли

Каждая — из настоящего прогона; где не указан проект, грабля общая для этапа.

Провал громкости ≠ паузасмычка согласной даёт 40–110 мс тишины внутри слова; Whisper дописывает оборванное слово — MMS_FA + огибающая + edges.strictYTFP01
-r удваивал первый кадр кускасклейки уезжали на кадр, на смене ракурса мелькал кадр со старой рамкой — -fps_mode passthrough + проверка flashesYTFP01 v1
Выброшенные склейки < 0,1 скартинка короче звука на 62 мс — вливаются в соседнююYTFP01
Исходник 30 к/с в мастере 60 к/смедиана разностей ≈ 0 — 75-й перцентильYTFP01
Фейд 40 мс съедал хвост гласнойфейд не длиннее тишины у краяYTFP01
Слово на взрывную согласную«вот», «нет» — конец проверять на слухYTFP01
Роль «Гость» ≠ ключ peopleшортсы без плашек — команды печатают ⚠YTTRBM01
--speaker-names по времени речисверять по transcript_roles.txt, затем --rebuild-onlyYTTRBM01
Абзацы diarized.srt по 10–20 свходом брать {base}.words.jsonYTTRBM01
Ложные лица: телевизор, игрушкиуверенность до 0,95 — crop.close_face 100, у героя только seatYTFP01
Кусок открывается перебивкойчужое лицо получает имя героя — plate_from; лучше начинать кусок на героеYTFP01
Номер ключевого кадра уходит от времени24 с к концу выпуска — привязывать по ptsYTFP01
Титров глав 4 в пометах, 12 на делеискать по склейкам; кусок начинать после титраYTFP01
Чужой материал в кадре или звукепретензия Content ID — keep_outYTFP01
Лимит ~10 заливок в сутки, удалённые считаются40 повторов упирались в стену — стоп сразу + pending.py; черновые версии смотреть файламиYTTRBM01 · YTFP01
Подрезка в плеерефайл в 04_Shorts разошёлся с Drive и YouTube — правка только новой версиейYTFP01 S03
Исходники видит заказчиквнутренние пометки на Drive фонда — drive_work: falseYTFP01
Тишина в новом мастере давала «сходство 124»тихие окна не сравниваются; эталон только из самого мастера (копия с YouTube отстаёт на 36 мс)check
youtube.googleapis.com из РФ рвётся--sni-bypass; первый запрос висит 60 с — повторы; заливка замерла — прервать после 5 мин тишины, удалить черновик в Studioupload
Бот Telegram шлёт до 50 МБTelethon от своего аккаунта; сессия занята — ждать и повторятьtelegram
rclone --include и --exclude вперемешкуправила одним списком --filterdrive
Альфа HyperFrames в несколько потоковпервый кадр куска пустой — --workers 1viz
Субтитр 900 px заходит под кнопки YouTubeкнопки с 947 px — сузить captions.max_width (решение Романа)YTTRBM01
Папка задания из очереди лежала в /tmpдержать в постоянном месте (~/.cache/ytai/shorts/<CODE>_07_Shorts/)YTTRBM01
Соседняя сессия рендерила живым этапомсемь минут в render.py стояла ошибка — править атомарно, сухой прогон сразу, или worktreeYTEVO02 · YTFP01
Журнал доливки обрезает начало сообщениякосметика, не исправлено — поправить вместе с коммитомpending.py
Экраны вшиты в мастерв кропе 9:16 режутся подписи и вопросы фильма — keep_out из листа экранов + перебивки, проверка check_cover.pyYTCH14
Край перебивки прилип к смене рамкипорог broll.snap 0,3 с = 8 кадров при 25 к/с: конец уехал назад и открыл затухание цитаты — ставить край дальше 8 кадров или ровно на сменуYTCH14
Кусок рамки в 1 кадрдве перебивки стыкуются после прилипания к разным точкам — в render --dry искать куски по 0,04 с, края встыкYTCH14
Одежда замерена на прошлой версииновый цвет мастера развернул оттенки — героиню узнавали как куратора; probe на финальном мастереYTCH14
ID ролика с дефисом в началеargparse принимает «-BuNLfHLUeg» за флаг — передавать --video-id=<ID>YTCH14

15.2 · 8Сдача и что остаётся руками

🤖 Команды сдачи

  • telegram — видео 1080×1920 в «Избранное», превью на 1 с, подпись: название + «выход/вышел дд.мм» / «по ссылке» / «не залит»; подводка без подписи для заказчика — проектный tg_forward.py
  • drive — мастера {CODE}_S*_v*.mp4 → {drive}/04_Shorts (--ignore-existing); исходники → 00_Setup/07_Shorts по --filter (json/txt/md/srt/m4a, gfx, music, viz/S*, broll, logs, probe, out/*.json|jpg); drive_work: false — только мастера
  • ledger — ContentList: ровно одна строка с кодом → Shorts = TRUE + чип папки; Trello: ровно одна карточка → блок «Шортсы» заменяется целиком
  • status — видимость, график, warn по каждому шортсу — запросом к YouTube

🙋 Руками

  • блок шортсов на хабе канала yt.rya.ae (образец /ytfp/#shorts01)
  • Related video — только в Studio: в API поля нет, у нового канала закрыто до Advanced features
  • удалить прежние версии в Studio; вернуть «Доступ по ссылке», если ролик стал приватным
  • подключить канал в safelist Epidemic Sound до выхода с музыкой
  • хэндофф в {проект}/00_Setup/00_Handoff/ и короткий ответ в чат

15.2 · 9Команды

Один выпуск целиком
V=~/YTAI/environment/.venv_transcribe/bin/python; D=~/YTAI/scripts/07_shorts/0701_finished
S=$D/shorts.py; C=$D/scout.py; JOB={проект}/00_Setup/07_Shorts/{CODE}_shorts_job.json

python3 ~/YTAI/scripts/999_extra/mlx_queue.py wordrole -- $V ~/YTAI/scripts/999_extra/wordrole_transcribe.py --media <мастер> --language ru --plain --num-speakers 2 --speaker-names 'Имя,Имя' --out-dir $(dirname $JOB)  # слова с ролями
$V $S transcript --job $JOB  # задание отборщику → агент Draper пишет picks.json
$V $S picks --job $JOB  # проверка отбора: длина, запреты, keep_out, перебивки
$V $C cuts --job $JOB && $V $C sheets --job $JOB --ranges 0:51-1:00 && $V $C faces --job $JOB 'src,dur'  # каталог кадров для перебивок
$V $S probe --job $JOB --t 4:45 8:25 && $V $S gfx --job $JOB  # одежда и места; знак и плашки
$V $S edges --job $JOB --fix  # края кусков в паузы между словами
$V $S render --job $JOB --dry  # план по секундам: рамка, перебивки, плашки
$V $S render --job $JOB --version 1  # шортсы → 04_Shorts; сам сверит края и мелькания
$V $S sheet --job $JOB  # лист кадров — смотреть глазами
$V $S upload --job $JOB  # YouTube по ссылке; при лимите печатает команду pending.py add
$V $S telegram --job $JOB && $V $S drive --job $JOB && $V $S ledger --job $JOB  # сдача
$V $S schedule --job $JOB --start 2026-10-04T10:00:00+03:00 --every 24  # только по слову Романа
$V $S status --job $JOB  # что на YouTube и что осталось
Варианты, пересборка, очередь
$V $S viz --init --job $JOB && $V $S viz --render --job $JOB  # выноски HyperFrames
$V $S music --find 'calm piano' --job $JOB && $V $S music --track <id> --only S02 --job $JOB  # музыка под длину
$V $S find4k --job $JOB && $V $S check --job $JOB  # 4K-мастер и сверка по звуку
$V $S render --job $JOB --version 2 --only S01,S03 && $V $S upload --job $JOB && $V $S schedule --job $JOB  # новая версия: три шага
$V $D/pending.py add --job $JOB --only S04,S05 && $V $D/pending.py list  # очередь доливки
$V ~/YTAI/scripts/05_editing/0510_autocut/shorts_master.py --project $P words · map · build · verify --head N --name <CODE>_v6  # чистый мастер из собранного фильма

15.2 · 10Где лежит

Проект
{проект}/04_Shorts/{CODE}_S{NN}_v{N}_{slug}.mp4мастера шортсов, все версии рядом
{проект}/00_Setup/07_Shorts/{CODE}_shorts_job.json · picks.json · picks_prompt.md · transcript_roles.txt · edges.json · master_ref.m4aзадание и отбор
{проект}/00_Setup/07_Shorts/out/manifest.json · *_sheet.jpg · pack_S{NN}/ · _tmp/манифест, листы, пакеты описаний
{проект}/00_Setup/07_Shorts/broll/ · gfx/ · viz/ · music/ · probe/ · logs/каталог кадров, графика, варианты
{проект}/00_Setup/07_Shorts/_session_tools/инструменты проекта (src_master.py, cues_build.py, listen.py, viz_all.py, tg_forward.py)
Канал и мак
~/YTAI/YTs/{CH}/shorts_profile.json · shorts_gfx.htmlДНК канала для шортсов
~/.config/ytai/publish_schedule.json · shorts_pending.jsonграфик выхода, очередь доливки
~/Library/Logs/ytai_publish_schedule.log · ytai_shorts_pending.logжурналы автоматов
Код
~/YTAI/scripts/07_shorts/0701_finished/shorts.py · render.py · job.py · edges.py · scout.py · gfx.py · viz.py · music.py · pending.py · tg_send.py · mastercheck.py · ledger.py · README.mdэтап; правки 02.10 не закоммичены
~/YTAI/scripts/08_youtube/upload_youtube.py · scheduled_publish.py · channels.jsonзаливка и публикатор
Шортсы машиной · сверено 02.10.2026 по коду этапа · примеры: YTCH14 (фильм фонда, вшитые экраны, два пакета), YTFP01 (документальный, три версии за день) · YTTRBM01 (разговор за столом)