| name | podcast-episode |
| description | Подготовка описания нового выпуска подкаста «Два Ивана» (репо doubleivan.ru) на основе данных из Riverside, короткого описания от пользователя, или импорт пост-фактум по ссылке на уже опубликованный выпуск Mave. Используй этот скилл, когда пользователь говорит «подготовь выпуск», «новый эпизод», «опиши выпуск», «импортни выпуск», присылает данные с полями content type / summary / chapters / sound bites / guest name (это формат экспорта Riverside), даёт ссылку вида `https://doubleivan.mave.digital/ep-NN`, упоминает Mave, или работает в директории `doubleivan.ru` и просит сделать описание подкаста. Срабатывай даже если пользователь не называет скилл явно — любой ввод про новый или существующий выпуск подкаста двух Иванов это про этот скилл. |
Подкаст «Два Ивана» — подготовка выпуска
Этот скилл создаёт ветку, файл выпуска для Hugo-сайта doubleivan.ru и текст описания для Mave-плеера. Пользователь сам проводит ревью, мерж и докручивает технические поля (mp3, длительность, telegram_discussion и т.д.).
Контекст и принципы
Пользователь — соведущий подкаста. Он присылает один из трёх типов ввода:
- Короткое описание — буквально пара предложений про тему и гостя. Pre-публикация (выпуск ещё не на Mave).
- Большой блок из Riverside — с полями
content type, primary goal, summary, keywords, key topics, guest name, Titles, sound bites, Chapters, resources. Pre-публикация. Блок намеренно избыточный — нужен Claude как контекст, а не как контент для вставки.
- Ссылка на Mave (
https://doubleivan.mave.digital/ep-NN) — выпуск уже опубликован, но в репо его ещё нет. Пост-фактум импорт. Не синтезируй ничего нового — текст и таймкоды уже подобраны, надо только распарсить страницу Mave и привести в формат репо. Перейди сразу к «Шаг 0. Пост-фактум импорт с Mave».
Главный принцип для типов 1-2: синтезируй, а не пересказывай. Riverside-ввод это сырьё для понимания темы, а не текст для копипаста. Готовый файл выпуска должен выглядеть как соседние выпуски в репозитории, а не как AI-сводка.
Главный принцип для типа 3: минимум вмешательства. Текст на Mave — финальная редакция, не переписывай его и не «улучшай», просто переноси в формат репо.
Шаг 0. Пост-фактум импорт с Mave
Используется только если пользователь дал ссылку на уже опубликованный выпуск Mave. Если ввод — Riverside или короткое описание, этот шаг пропусти и иди в Шаг 1.
Получи данные со страницы
Mave — это Nuxt SPA, обычный curl без User-Agent отдаёт пустую страницу. Но если запросить с десктопным UA, в HTML есть строка с window.__NUXT__-данными, где лежит всё: заголовок, описание (HTML), главы, UUID обложки/mp3, длительность в секундах, дата публикации.
curl -sL -A "Mozilla/5.0" "https://doubleivan.mave.digital/ep-NN" -o /tmp/mave.html
Из HTML извлекай:
grep -oE '<title>[^<]*</title>|og:site_name" content="[^"]*"' /tmp/mave.html
grep -oE '"description":"[^"]{0,5000}"|"storage/podcasts/[^"]+"' /tmp/mave.html
В описании Mave таймкоды лежат как <ul><li>(HH:MM:SS) Заголовок</li>...</ul> — это и есть главы для frontmatter, без укрупнения (они уже подобраны вручную при публикации).
Поля, которые получишь напрямую из HTML:
- Заголовок выпуска — из
<title> (отрежь часть — Подкаст «...»).
- Сезон — из
og:site_name (например 45 выпуск 4 сезона → season: 4).
- Номер эпизода — из заголовка (
№NN после Два Ивана). Внимание: это НЕ совпадает с номером в URL Mave (ep-NN) — Mave использует свою внутреннюю нумерацию.
- Описание (HTML) — из поля
"description":"...". Содержит HTML-теги <p>, <a>, <ul><li>. Конвертируй в markdown.
- UUID эпизода — из путей
storage/podcasts/<podcast-uuid>/images/<ep-uuid>.png и .../episodes/<ep-uuid>.mp3. Это полные пути для image и mp3, добавь префикс https://cdn.mave.digital/.
- Длительность — из числа после описания (например
5289 секунд). Конвертируй в HH:MM:SS.
- Дата публикации — ISO-строка типа
"2026-02-18T09:00:00.000Z". Используй дату, но время приведи к T06:00:00+00:00 (конвенция репо).
Затем — HEAD-запросом получи length:
curl -sI "https://cdn.mave.digital/storage/podcasts/<podcast-uuid>/episodes/<ep-uuid>.mp3" | grep -i content-length
Конвертация описания в тело markdown
Описание из Mave — это HTML с структурой типа:
<p>Абзац 1.</p><p>Абзац 2 с <a href="https://...">ссылкой</a>.</p><p></p><ul><li>(00:00:00) Глава 1</li>...</ul><p></p>
Правила:
<p>...</p> → markdown-абзац (разделяй пустыми строками).
<a href="X">Y</a> → [Y](X).
<ul><li>(HH:MM:SS) ...</li></ul> — это таймкоды, не вставляй их в тело, переноси в timecodes frontmatter.
- Пустые
<p></p> отбрасывай.
Что пропускается в этом режиме
- Не задавай уточняющие вопросы про имя гостя, заголовок, темы — всё уже на Mave.
- Не создавай ветку автоматически. Пользователь сам решает, делать ли её — он мог запустить импорт как часть другой ветки.
- Не готовь описание для Mave (Шаг 5) — выпуск уже опубликован, дублировать не нужно.
- Не укрупняй таймкоды — на Mave они уже финальные.
- Не предлагай свои варианты заголовка — заголовок на Mave финальный.
Что остаётся обязательным
- Прочитай 1-2 свежих файла в
content/podcasts/ для сверки актуального формата frontmatter (поля могут меняться).
- Сохрани файл по конвенции
content/podcasts/YYYY_MM_DD_NNNN_<slug>.md.
telegram_discussion оставь пустой строкой (если пользователь не дал) — пользователь докрутит сам.
Шаг 1. Прочитай несколько последних выпусков
Перед тем как писать, прочитай 2-3 последних файла из content/podcasts/2025_*.md или 2026_*.md. Это нужно, чтобы:
- увидеть актуальный формат frontmatter (поля, кавычки, типы значений),
- поймать тон и длину интро-абзаца (обычно 3-5 предложений, разговорный стиль, без bullet-ов),
- понять количество и формулировки таймкодов в реальных выпусках.
Особенно важно: никогда не повторяй структуру и формат, который ты помнишь по памяти — всегда сверяйся с актуальными файлами, потому что соавтор иногда меняет конвенции.
Шаг 2. Уточни критичные данные у пользователя
Riverside часто ошибается с именем гостя (определяет по голосу/тексту и подставляет случайное имя). Всегда подтверждай имя+фамилию гостя и финальный заголовок выпуска перед записью в файл. Заголовки идут в одном из двух форматов:
Два Ивана №NN <Тема> с <Имя Фамилия> #гостевой — для гостевых выпусков
Два Ивана №NN <Тема> — для выпусков без гостя
Тема часто бывает игровой — «Отменяем X», «Про Y», «Тайпчекеры» и т.п. Riverside в поле Titles присылает свои варианты, но они часто канцелярские — лучше предложить пользователю свой вариант, опираясь на ключевую идею выпуска.
Также спроси номер эпизода, если он не очевиден. Не просто бери последний номер + 1 из директории — пользователь может «пропускать» номера или восстанавливать пропущенные.
Шаг 3. Создай ветку
Имя ветки: episode_NN_<slug>, где slug — либо тема (code_review, open_source), либо фамилия гостя (pakhomov, sobolev). Смотри на примеры в git log для понимания, какой стиль чаще встречается.
git checkout -b episode_NN_<slug>
Шаг 4. Создай файл выпуска
Путь: content/podcasts/YYYY_MM_DD_NNNN_<slug>.md, где:
YYYY_MM_DD — дата публикации (если не указана, используй сегодня или ближайшую пятницу — выпуски обычно публикуются по пятницам в 06:00 UTC)
NNNN — номер эпизода с ведущими нулями до 4 знаков (0047, 0123)
Frontmatter
Используй YAML-frontmatter ровно как в свежих выпусках. Вот опорный шаблон (актуальные значения смотри в content/podcasts/2025_11_*.md):
---
title: "Два Ивана №NN <Тема> с <Имя Фамилия> #гостевой"
date: YYYY-MM-DDT06:00:00+00:00
summary: "<1-2 предложения для превью на сайте и в RSS>"
image: ""
mp3: ""
season: 3
episode: NN
length: 0
duration: ""
telegram_discussion: ""
timecodes:
- data: ["00:00:00", "Вступление"]
- data: ["00:06:06", "Путь до коммиттера в Apache"]
...
---
Поля, которые ты заполняешь сам, как только дана ссылка на обложку:
image — ссылка на обложку с Mave CDN, в формате https://cdn.mave.digital/storage/podcasts/<podcast-uuid>/images/<episode-uuid>.png (расширение бывает .jpg).
mp3 — выводится из image-URL автоматически: тот же UUID эпизода, замена images/ → episodes/ и расширения на .mp3. Mave использует один UUID и для обложки, и для аудио-файла.
length — размер mp3 в байтах. Получи через HEAD-запрос: curl -sI <mp3-url> | grep -i content-length. Не качай файл целиком.
duration — длительность в формате "HH:MM:SS". ffprobe умеет работать с URL напрямую: ffprobe -v error -show_entries format=duration -of default=nw=1:nokey=1 <mp3-url>. Получишь число секунд (с дробной частью), сконвертируй в HH:MM:SS округлением вниз.
Поля, которые заполняет пользователь (не выдумывай, оставляй пустыми если не дано):
telegram_discussion — короткий путь типа ostrovok_tech/164. Пустая строка по умолчанию.
Если ссылки на обложку нет — оставляй image, mp3, length, duration пустыми/нулевыми. Не выдумывай URL и не качай рандомные файлы.
Сезон: каждый календарный год = новый сезон. 2025 → сезон 3, 2026 → сезон 4 и так далее. Если не уверен — смотри последний выпуск в соответствующем году.
Таймкоды
Это самая частая точка фейла. Riverside выдаёт 25-30+ чанков, многие дублируют темы или стоят слишком близко по времени. Объединяй в 10-15 крупных смысловых блоков (а лучше ещё меньше) — сравни с реальными выпусками, там обычно ровно столько.
Правила объединения:
- Несколько подряд идущих чанков на одну тему → один блок с самым ранним временем.
- Очень близкие по времени блоки (<2 минут) → объединяй, даже если темы немного разные.
- Первый блок в 00:00:00 — почти всегда «Вступление», даже если Riverside его так не назвал.
- Последний блок — «Заключение» или похожее.
Формат времени в YAML — всегда HH:MM:SS (с нулевым часом для коротких выпусков: 00:33:26, не 33:26).
Тело (после ---)
Один абзац, 3-5 предложений, разговорный стиль. Структура примерно такая:
- Кто пришёл в гости и в каком контексте (или «два Ивана решили обсудить...» если без гостя).
- Что обсудили — ключевые темы пакетом, не списком.
- Завлекательная закрывающая фраза с приглашением слушателя в разговор: вопрос, провокация, CTA. Не «Получился разговор про...» (констатация), а «Попытались разобраться, кому и чему мы готовы доверять. А что бы выбрали вы?» (с открытым вопросом). Цель — чтобы человек, прочитав, захотел нажать play.
Ссылки в теле
В каждом гостевом выпуске бывает несколько типов ссылок — обязательно спроси про каждый тип, если пользователь не упомянул их сам:
- Каналы гостя: телеграм, ютуб, личный сайт, другие подкасты. Часто — несколько.
- Перекрёстные ссылки на прошлые выпуски: если в разговоре отсылались к предыдущей теме, надо линковать через Mave URL
https://doubleivan.mave.digital/ep-N.
- Литература/статьи/инструменты, упомянутые в выпуске.
Поиск Mave-ссылок на прошлые выпуски можешь делать сам: Mave нумерует выпуски по своей внутренней схеме (отличается от наших номеров), но <title> тег на странице эпизода содержит название с нашим номером. Скан:
for n in $(seq 1 50); do
title=$(curl -s "https://doubleivan.mave.digital/ep-$n" | grep -oE '<title>[^<]*</title>')
echo "ep-$n: $title"
done | grep -i "<тема, которую ищешь>"
Или, если знаешь наш номер выпуска, найди через grep по теме.
Формат ссылок в markdown (важна верстка — смотри на свежих выпусках):
Галлюцинации LLM в resources от Riverside: если в ресурсах присутствуют example.com, youtube.com/канал с кириллицей в slug, неполные URL, амазон-ссылки без ID товара — не вставляй их. Лучше пропустить раздел совсем, чем вставить мусор. Реальные ссылки уточни у пользователя.
Шаг 5. Сформулируй описание для Mave
Mave (https://doubleivan.mave.digital) — отдельная платформа со своим UI. Текстовая часть Mave-описания должна полностью совпадать с телом markdown-файла (тот же интро-абзац, те же ссылки на каналы, те же перекрёстные ссылки, та же литература). Отличаются только: формат ссылок (на Mave обычно plain-URL), отсутствие HTML-комментариев, и в конце добавляются таймкоды с круглыми скобками.
Формат:
<тот же интро-абзац, что в теле markdown — со всеми ссылками>
<те же абзацы про каналы гостя, что в markdown>
Таймкоды:
(00:00) Вступление
(06:06) Путь до коммиттера в Apache
...
(1:20:53) Заключение
Правила:
- Содержимое описания = содержимое тела markdown, отличие только в форматировании ссылок и в добавлении таймкодов в конце. Если в markdown добавил линк на канал гостя или прошлый выпуск — добавь и в Mave.
- Таймкоды всегда в круглых скобках:
(06:06) Заголовок. Это критично, Mave парсит таймкоды по этому шаблону.
- Время без ведущего часа для коротких меток (
06:06 вместо 00:06:06), и с часом без ведущего нуля для длинных (1:02:27, не 01:02:27).
- Нет YAML-обёртки — это plain-text для копипаста в Mave dashboard.
Выводи это в чат как блок кода — пользователь копирует в Mave вручную.
Sync-чек перед завершением: убедись, что текстовая часть Mave-описания идентична markdown-телу (за вычетом синтаксиса ссылок). Если правил тон или ссылку в одном месте — поправь и в другом.
Шаг 6. Не делай PR/мерж
Пользователь сам проводит ревью и мержит. Скилл закончил работу когда:
- ветка создана,
- файл выпуска записан,
- текст для Mave показан в чате.
Не делай git add, git commit, git push, gh pr create — пользователь делает это сам.
Что не делать
- Не вставляй сырой Riverside-ввод в файл — он избыточный по дизайну.
- Не сохраняй все 25 таймкодов от Riverside — укрупняй до 10-15.
- Не угадывай имя гостя из Riverside-блока без подтверждения — оно часто неверное.
- Не выдумывай ссылку на обложку, mp3, telegram_discussion, sound bites в виде цитат, ресурсные ссылки.
- Не делай резюме своей работы длинной портянкой в конце — пользователь видит созданный файл и описание для Mave, этого достаточно.
Пример входа и выхода
Вход (фрагмент Riverside):
guest name: Михаил
summary: Обсуждение культуры open source, ревью кода в Apache...
chapters:
00:00 Отмена код-ревью и новые подходы
06:06 Процесс участия в проектах Apache
11:58 Процесс оффбординга в open-source
... (ещё 25 пунктов) ...
01:20:53 Заключительные мысли и пожелания слушателям
Уточнение у пользователя: «Riverside пишет что гость Михаил — это точно? И как назвать выпуск?»
Ответ пользователя: «Гость Саша Пахомов, заголовок: Два Ивана №47 Отменяем архитектуру с Сашей Пахомовым #гостевой».
Выход — файл content/podcasts/2026_05_01_0047_pakhomov.md:
---
title: "Два Ивана №47 Отменяем архитектуру с Сашей Пахомовым #гостевой"
date: 2026-05-01T06:00:00+00:00
summary: "После отмены код-ревью два Ивана берутся за следующий процесс — архитектурное ревью..."
image: ""
mp3: ""
season: 3
episode: 47
length: 0
duration: ""
telegram_discussion: ""
timecodes:
- data: ["00:00:00", "Вступление"]
- data: ["00:06:06", "Путь до коммиттера в Apache"]
- data: ["00:15:34", "Культура контрибьюции в ClickHouse"]
... (всего 12-13 пунктов) ...
- data: ["01:20:53", "Заключение"]
---
После выпуска про отмену код-ревью два Ивана берутся за следующий процесс и зовут в гости Сашу Пахомова. Обсудили...
И блок для Mave в чате.