/youtube-publish — контент на личный канал Антона
🧒 Доклад Антону кончается блоком «Простыми словами» ([[eli5-always]]). Описания видео — без ELI5, у них свой голос.
Родился 21.09.2026 из голосовой Антона (tg:-[id], 08:34 UTC). Дословно:
«Публиковать разный контент на личный YouTube-канал. Один из основных источников контента
сейчас — NotebookLM... Как только появляется новый материал из NotebookLM, его нужно выкладывать
на YouTube... Делать качественное описание к видео: что это за видео, о чём оно, зачем создано.
Добавлять небольшой транскрипт или фрагмент транскрипта для лучшего SEO/GEO. Сделать так,
чтобы видео легко находилось через поиск. Обязательно добавлять авторский контекст от Антона.»
Цель контента (его слова): обучение Антона · подготовка к трудоустройству в LLM-компанию ·
публичный YouTube-след вокруг LLM/AI-тем.
Склейка с другими скиллами (он прямо просил «будет склеиваться»): контракт односторонний.
Производители (/teach-podcast, /notebooklm, /episode, любая будущая труба) кладут строку
в очередь $OBSIDIAN_VAULT/05-Resources/NotebookLM/_youtube-queue.md. Этот скилл вычерпывает
её и больше ничего от них не требует. Производитель забыл строку — не беда: движок делает и
свободный скан папок артефактов, файл на диске потерять нельзя (замер 21.09: очередь знала 14
файлов, на диске лежало 35).
Канал — доказан, не угадан
[аккаунт] · UCa_lk_0LTagC9tI6f9NRF_w · «Tony» · 305 подписчиков · 75 видео · с 18.03.2011.
Три независимые улики (21.09.2026):
- YouTube Data API v3 по id из истории браузера вернул title/customUrl/статистику.
browser_history.db: Антон сам открывал Студию этого канала 30.08 и 02.09 из Firefox-профиля
m26xxxkf.anton-clean — значит и канал его, и живой логин лежит именно там.
- На канале уже висят его ролики «моя работа с Claude Code» (30–31.08.2026) — та же тематика.
⚠️ Другого личного канала не искали шире истории браузера. Появится второй — уточнить у Антона,
а не выбирать самому.
⛔ Законы
- Описание несёт ЧЕТЫРЕ обязательных куска (прямой список Антона): (а) о чём видео;
(б) зачем создано; (в) фрагмент расшифровки для поиска; (г) авторский контекст от него.
Нет любого из четырёх — описание бракованное, публиковать нельзя.
- Авторский блок пишется от ПЕРВОГО лица Антона и называет Mycroft. Его формулировка:
«Это видео от Антона, оно сгенерировано моим кофаундером Mycroft». Раскрытие ИИ живёт
внутри этого блока — плашки «AI-generated» отдельно не ставим (§3.3, DR-701: планка =
review control + названное ответственное лицо, а лицо здесь Антон).
- Публичность по умолчанию, приватное не едет. Гейт
privacy_scan перед каждой загрузкой:
почта, имена рекрутёров, вилки денег из переписки, секреты. Сработал — видео пропускается,
строка в леджер blocked-privacy, чиним руками. Наш собственный calendly/WhatsApp/github —
не утечка, это подпись (§1.1).
- Подпись обязательна. Футер = блоки C+E из
$IMPORTS_ROOT/content-factory/_STYLE-footer.md
плюс Linktree и github.com/tonydzi. YouTube = публичная поверхность, карве-аутов нет.
EN-описание НЕ упоминает RU-каналы (правило [коллега] 07.07).
- Язык описания = язык дорожки. Суффикс
-ru / -en в имени файла — истина. RU-эпизод
с английским описанием = брак: YouTube так и проиндексирует.
- Находимость строится тремя рычагами, не тегами одними: (1) субтитры из расшифровки
(
captions.insert) — YouTube индексирует их текст целиком и это сильнее любых тегов для
аудио-контента; (2) defaultLanguage/defaultAudioLanguage проставлены; (3) первые три
тега продублированы хэштегами — они показываются над заголовком.
- Готово = прочитано обратно. После загрузки движок сам делает
videos.list и печатает
реальный privacyStatus. Код ответа 200 доказательством публикации не является (§4.3-бис).
- Выдумывать нельзя. Описание собирается из очереди, пакета урока и расшифровки. Нет
данных — пишем короче, а не сочиняем содержание, которого в видео нет.
- Суточный потолок 5 видео — не вкус, а арифметика квоты: 1600 (videos.insert) + 400
(captions.insert) + 1 (videos.list) ≈ 2001 единица, суточная квота проекта 10 000.
Потолок зашит в
DAILY_CAP и проверяется регрессом.
- Публикуем только вычитанное.
run по умолчанию берёт ТОЛЬКО строки очереди — у них
человеческий заголовок. Файлы свободного скана видны в scan, но наружу без флага
--include-unqueued не идут: заголовок «Hedge 01 inside», собранный из имени файла, на
публичном канале Антона выглядит браком. Нужен нормальный заголовок — строку пишет
производитель (/teach-podcast), а не этот скилл на глаз.
- Серия выходит по номерам, а не по дате файла. «(урок 3)» в заголовке — ключ сортировки.
Урок 15 сделан позже урока 1, но и выйти должен позже.
Рельсы: две, и выбор между ними ЗАМЕРЯЕТСЯ
Рельса A — API (основная, безлюдная)
videos.insert resumable + captions.insert. Всё ставится одним вызовом: заголовок, описание,
теги, категория 27 (Education), язык, видимость. Только эта рельса умеет работать ночью без человека.
⚠️ РИСК, КОТОРЫЙ ОБЯЗАН БЫТЬ ЗАМЕРЕН, А НЕ ПРЕДПОЛОЖЕН. У GCP-проектов, не прошедших
аудит YouTube API, загруженные через API видео могут запираться в private без возможности
открыть их руками. Это заявленное поведение платформы, и оно ломает всю цель («публичный след»).
Поэтому run по умолчанию идёт канарейкой --limit 1 и сразу читает статус обратно:
privacyStatus == public → рельса A рабочая, дальше можно пачкой;
- иначе → движок сам останавливается с кодом 2 и печатает вердикт; переходим на рельсу B.
⛔ До канарейки запрещено говорить «рельса A работает» — это claim (§5.4).
Рельса B — браузер (фолбэк и первый боевой заход)
Firefox, профиль m26xxxkf.anton-clean (там живой логин канала), studio.youtube.com.
Команда manifest печатает и кладёт готовый пакет: путь к mp4 + заголовок + описание + теги
- видимость. Дальше Create → Upload videos → перетащить mp4 → вставить поля из манифеста.
Ban-риска нет: это собственный канал Антона, а не чужая площадка.
Шаг 0. RECALL и состояние
python ~/.claude/scripts/youtube_publish.py scan # что ждёт, сколько уже ушло сегодня
python ~/.claude/scripts/youtube_publish.py ledger # что уже на канале
python ~/.claude/scripts/youtube_publish.py auth check # жива ли рельса A
Леджер ~/.claude/state/youtube_ledger.jsonl — единственный источник «что уже выложено».
Статус в очереди волта — подсказка человеку: очередь под Syncthing, её правят три узла, у неё
уже есть sync-conflict-копии. Сторож не живёт в том, что сторожит ([[watchdog-must-verify-the-item]]).
Шаг 1. Посмотреть описание ГЛАЗАМИ до публикации
python ~/.claude/scripts/youtube_publish.py meta <имя файла>
Печатает ровно то, что увидит зритель, плюс счётчики лимитов (заголовок/100, описание/5000,
теги/500) и вердикт гейта приватности. Первый эпизод серии смотрим глазами всегда — дальше
шаблон уже проверен и можно пачкой.
Сомнение по вкусу текста → /taste-check <файл описания>.
Шаг 2. Рендер (аудио → видео)
YouTube не принимает голый .m4a, нужен видеоконтейнер.
python ~/.claude/scripts/youtube_publish.py render <имя файла>
Делает обложку 1920×1080 (тёмная карточка: строка серии, заголовок в 5 строк, [аккаунт],
Palo Alto AI Research Lab · NotebookLM) и склеивает с дорожкой: h264, 2 к/с, aac 192k,
+faststart. Замер 21.09: эпизод 18 минут → 26,5 МБ за 2 минуты на хабе.
Шаг 3. Заливка
python ~/.claude/scripts/youtube_publish.py run --limit 1 # КАНАРЕЙКА, первый раз всегда так
python ~/.claude/scripts/youtube_publish.py run --limit 5 # рабочий заход после зелёной канарейки
python ~/.claude/scripts/youtube_publish.py run --dry-run # посмотреть план без действий
python ~/.claude/scripts/youtube_publish.py run --include-unqueued # редко: и файлы без строки
Порядок внутри: гейт приватности → рендер → субтитры (faster-whisper локально, 0 токенов) →
загрузка → чтение статуса обратно → строка в леджер → отметка в очереди (best-effort).
Падение на любом шаге пишет причину в леджер и не помечает файл сделанным: упавший эпизод
остаётся в очереди, иначе он теряется молча.
Рельса A мертва или заперла видео → рельса B:
python ~/.claude/scripts/youtube_publish.py manifest --limit 5
Шаг 4. Проверка (§4.3-бис, второй заход другим методом)
verify <videoId> — privacyStatus, uploadStatus, причина отказа, если есть.
- Открыть
https://youtu.be/<id> и посмотреть глазами: звук идёт, обложка та, описание
не обрезано на середине блока.
- Через сутки: видео находится поиском по своему заголовку? Нет — значит находимость не
построена, и это отдельная починка, а не «ну бывает».
- Итог пишется парой: «проверено: … · НЕ проверено: … (почему)».
Шаг 5. Учёт и связи (тем же заходом)
- Леджер пишется движком сам.
- Строка в очереди → «выложено <дата> <ссылка>» (движок делает best-effort).
_teach-curriculum.md: статус урока → «на YouTube» + ссылка.
- Ссылка уходит обратно в учебный контур: в шпаргалку
/interview-prep того звонка,
к которому урок, — строка «Подкаст: <ссылка>».
- Контент-майнер ([[content-miner-reflex]]): вышел эпизод — черновик тизера в воронку.
Один эпизод = один тизер, не веер (§1.5 «спам ≠ громкость»).
- Вердикт о скилле одной строкой: 🔧 обновляю / 📝 обновлю не сейчас / ✅ не надо, с причиной
(§9.3-бис). Рутина судит ещё и собственную инструкцию (§9.3-бис поправка 13.09).
Рутина
youtube-publish-drip — ночное окно 23:00–06:00 Лиссабон (§4.6), раз в сутки, --limit 5.
Почему ежедневно, а не «раз в 2–3 дня», как допускал Антон: суточная квота всё равно режет
до 5 видео, а ежедневный мелкий заход ровнее ложится на производство (/teach-podcast делает
1–5 эпизодов в день). Накопилось больше — само растянется на несколько ночей.
⛔ Рутина НЕ поднимается из сессии, порождённой scheduled-task (§9.2): сид кладётся в
spawn_queue.py, живая сессия его поднимает.
Темп режем по §4.5-тер, если хаб начнёт тормозить.
Грабли, оплаченные при рождении (21.09.2026)
- Порядок чисток в описании. Черновики очереди кончаются фразой «Контакты и CTA — из
_STYLE-footer.md». Снимать надо СНАЧАЛА бэктики, ПОТОМ фразу: иначе точка внутри
_STYLE-footer.md обрывает замену и в публичное описание уезжает хвост «md.». Поймано регрессом test_internal_vault_paths_never_leak`, который на этом краснел.
- Тайм-коды в расшифровке. Дорожки NotebookLM идут с
[00:03] на каждой фразе. В описании
это мусор: YouTube индексирует слова, а не скобки. Движок их снимает.
- Расшифровка машинная и с опечатками («менажмент», «искусном интеллекте»). Правим не
текст, а честность: фрагмент помечен «машинная, с опечатками». Вычитывать чужую ASR-дорожку
ради описания — работа не по цене.
- Очередь знает не всё. 14 строк в очереди против 35 файлов на диске. Поэтому скан
свободный, а не только по очереди.
- Голый
.m4a YouTube не берёт — всегда рендер в mp4.
Потребители
- Антон —
/yt, «выложи на ютуб», «что ждёт выгрузки».
/teach-podcast Шаг 6.3 — кладёт строку в _youtube-queue.md; этот скилл её вычерпывает.
/notebooklm — любой артефакт, который не стыдно показать миру, идёт той же дорогой.
- рутина
youtube-publish-drip — ночной вычерп.
Двери и файлы
- Движок:
~/.claude/scripts/youtube_publish.py (док внутри файла, §5.8).
- Регресс:
~/.claude/scripts/_test_youtube_publish.py — 28 проверок, kill-list в шапке.
- Леджер:
~/.claude/state/youtube_ledger.jsonl.
- Рендер и манифест:
~/.claude/state/youtube_render/.
- Очередь:
$OBSIDIAN_VAULT/05-Resources/NotebookLM/_youtube-queue.md.
- Токен рельсы A:
<secrets>/youtube_token_tonydzz.json (в волт и в always-loaded не кладём, §3.4).
Канон: CLAUDE.md §9.13 (учим Антона подкастом), §1.1 (подпись в каждом касании), §3.3 (голос
и раскрытие), §3.2 (публичные каналы), §5.7 (shadow-first), §4.3-бис (готово = второй заход).
Память: [[teach-anton-by-podcast-default]], [[youtube-publish-channel-and-rails]],
[[everything-becomes-content]], [[outbound-signature]].
<!--kit-footer-->
Like this skill? It is one of 100 in second-brain-starter-kit: the second brain we built for ourselves and run every day at Palo Alto AI Research Lab. Install the whole set with npx skills add tonydzi/second-brain-starter-kit. Everything is open source and free, so take what you need.
Flagships worth a look on their own: secondop-panel (a second opinion from a panel of external models), claude-memory-tidy (stop your agent's memory from rotting), telegram-mcp-kit (your own Telegram over MCP in about 15 minutes).
Author: Anton Dziatkovskii, Palo Alto AI Research Lab. Telegram @tonydzi - WhatsApp +1 341 222 9178 - X @Tony_Stef_
Engineers: want to test-drive this setup? Message me. I hand out free starter seeds to engineers who test and report back, and custom skill requests are welcome.