Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

Craft Podcast – установка скилла для Claude Code

Что это: Скилл для Claude Code, который берёт YouTube-видео и превращает его в русскоязычный подкаст-диалог двух ведущих (мужчина + женщина). Результат – MP3 файл, отправленный в Telegram.

Пайплайн: YouTube URL → субтитры + research → сценарий диалога → Edge TTS → MP3 → Telegram


1. Требования

  • Claude Code (CLI) – установлен и работает
  • Python 3.11+
  • ffmpeg (для склейки аудио)
  • Telegram аккаунт с API credentials (для отправки)

2. Установка зависимостей

# ffmpeg (macOS)
brew install ffmpeg

# ffmpeg (Ubuntu/Debian)
sudo apt install ffmpeg

# Python-пакеты
pip3 install edge-tts pydub telethon youtube-transcript-api

3. Telegram API

  1. Зайди на https://my.telegram.org → API Development Tools
  2. Создай приложение, получи API_ID и API_HASH
  3. Создай сессию Telethon (StringSession):
from telethon.sync import TelegramClient
from telethon.sessions import StringSession

with TelegramClient(StringSession(), API_ID, 'API_HASH') as client:
    print(client.session.save())  # Это твоя SESSION_STRING
  1. Создай файл ~/.craft-podcast-telegram.env:
TELEGRAM_API_ID=12345678
TELEGRAM_API_HASH=abcdef1234567890
TELEGRAM_SESSION_STRING=1BVtsOH...длинная строка...
  1. Создай группу/канал в Telegram для подкастов, узнай его ID (можно через @userinfobot или форвард сообщения боту @getidsbot)

4. Создание файловой структуры

# Папка скилла
mkdir -p ~/.claude/skills/craft-podcast/references

# Папки для данных (пути можно менять)
mkdir -p ~/craft-podcasts/audio
mkdir -p ~/craft-podcasts/transcripts

5. Файл скилла

~/.claude/skills/craft-podcast/SKILL.md

---
name: craft-podcast
description: >
  YouTube video → Russian podcast summary → TTS audio → Telegram.
  Triggers: craft podcast, создать подкаст, подкаст из видео, youtube podcast,
  craft-podcast, podcast summary, саммари видео.
---

# Craft Podcast Generator

YouTube URL → исследование → русский подкаст-диалог → Edge TTS → Telegram

## Quick Start

Пользователь даёт YouTube URL. Скилл выдаёт: MP3 подкаст в Telegram + сохранённый транскрипт.

**ВАЖНО: Полностью автоматический режим. Никаких вопросов, подтверждений или пауз.
Получил URL → Extract → Research → Script → TTS → Telegram. Без остановок.**

## Process

### Phase 1: Extract

**Step 1: Получить video ID**

Парсим из URL (поддержка форматов):
- `youtube.com/watch?v=VIDEO_ID`
- `youtu.be/VIDEO_ID`
- `youtube.com/embed/VIDEO_ID`

**Step 2: Достать субтитры**

\```python
from youtube_transcript_api import YouTubeTranscriptApi

try:
    transcript = YouTubeTranscriptApi.get_transcript(video_id, languages=['ru', 'en'])
    text = ' '.join([t['text'] for t in transcript])
except:
    try:
        tl = YouTubeTranscriptApi.list_transcripts(video_id)
        for t in tl:
            transcript = t.fetch()
            text = ' '.join([t['text'] for t in transcript])
            break
    except:
        text = None  # Нет субтитров - используем research
\```

**Step 3: Метаданные видео**

WebFetch на `https://noembed.com/embed?url=https://www.youtube.com/watch?v={video_id}` → title, author_name.

### Phase 2: Research

Параллельные WebSearch запросы:
- Каждый спикер/гость: `"[Name] background career"`
- Тема видео: `"[Topic] key insights summary"`
- Podcast notes: `"[Video title] podcast notes summary"`

### Phase 3: Script

Написать русский диалог на основе транскрипта + исследования:

**Формат:**
\```
<Person1>Текст ведущего</Person1>
<Person2>Текст эксперта</Person2>
\```

**Правила сценария:**
- Person1: мужской ведущий (энергичный, любопытный)
- Person2: женский эксперт (аналитичный, глубокий)
- 35-45 реплик
- Язык: русский
- Структура: Приветствие → Кто герои → Ключевые инсайты → Обсуждение → Заключение
- Конкретика: цифры, факты, протоколы из видео

**Сохранить транскрипт:**
`~/craft-podcasts/transcripts/transcript_[slug].txt`

### Phase 4: Generate & Send

**Step 1: Генерация аудио**

\```bash
python3 ~/.claude/skills/craft-podcast/references/tts-generator.py \
  ~/craft-podcasts/transcripts/transcript_[slug].txt \
  ~/craft-podcasts/audio/podcast_[slug].mp3
\```

**Step 2: Отправка в Telegram**

Подготовить caption:
\```
🎙 [Название видео]

[2-3 предложения с ключевыми инсайтами]

[YouTube URL]
\```

Отправить:
\```bash
python3 ~/.claude/skills/craft-podcast/references/telegram-sender.py \
  ~/craft-podcasts/audio/podcast_[slug].mp3 \
  YOUR_GROUP_ID \
  "caption text"
\```

## Error Handling

| Ошибка | Решение |
|--------|---------|
| Нет субтитров | Fallback на описание + WebSearch research |
| Edge TTS пустой сегмент | Пропустить (size < 100 bytes) |
| Длинный текст в сегменте | Разбить по предложениям |

## Dependencies

\```bash
pip3 install edge-tts pydub telethon youtube-transcript-api
\```

Также нужен `ffmpeg` (для pydub).

## Rules

- Весь пайплайн автоматический от URL до Telegram
- Русский для контента, английский для имён файлов
- Валидация regex: `r'<(Person[12])>(.*?)</\1>'` - должен найти 30+ совпадений

6. Скрипт TTS-генератора

~/.claude/skills/craft-podcast/references/tts-generator.py

#!/usr/bin/env python3
"""Edge TTS podcast generator - two Russian voices at 2x speed."""

import asyncio
import edge_tts
import re
import os
import sys
import tempfile
import shutil
from pydub import AudioSegment

VOICES = {
    'Person1': 'ru-RU-DmitryNeural',
    'Person2': 'ru-RU-SvetlanaNeural',
}
RATE = '+100%'
SILENCE_MS = 200
BITRATE = '192k'


async def generate_segment(text, voice, output_file):
    communicate = edge_tts.Communicate(text, voice, rate=RATE)
    await communicate.save(output_file)


async def generate_podcast(script_file, output_mp3):
    with open(script_file, 'r', encoding='utf-8') as f:
        script = f.read()

    pattern = r'<(Person[12])>(.*?)</\1>'
    segments = [(m.group(1), m.group(2).strip())
                for m in re.finditer(pattern, script, re.DOTALL)
                if m.group(2).strip()]

    if not segments:
        print('ERROR: No valid segments found')
        sys.exit(1)

    print(f'Found {len(segments)} segments')

    tmpdir = tempfile.mkdtemp()
    combined = AudioSegment.empty()
    silence = AudioSegment.silent(duration=SILENCE_MS)

    for idx, (person, text) in enumerate(segments):
        tmp = os.path.join(tmpdir, f'{idx:03d}.mp3')
        voice = VOICES[person]
        try:
            await generate_segment(text, voice, tmp)
            if os.path.getsize(tmp) > 100:
                combined += AudioSegment.from_mp3(tmp) + silence
                print(f'  [{idx+1}/{len(segments)}] OK')
            else:
                print(f'  [{idx+1}/{len(segments)}] SKIP (empty)')
        except Exception as e:
            print(f'  [{idx+1}/{len(segments)}] ERROR: {e}')

    combined.export(output_mp3, format='mp3', bitrate=BITRATE)

    duration = len(combined) / 1000
    size = os.path.getsize(output_mp3)
    print(f'\nDone! {output_mp3}')
    print(f'{size / 1024 / 1024:.1f} MB, {duration / 60:.1f} min')

    shutil.rmtree(tmpdir)


if __name__ == '__main__':
    if len(sys.argv) != 3:
        print('Usage: tts-generator.py <script.txt> <output.mp3>')
        sys.exit(1)
    asyncio.run(generate_podcast(sys.argv[1], sys.argv[2]))

7. Скрипт отправки в Telegram

~/.claude/skills/craft-podcast/references/telegram-sender.py

#!/usr/bin/env python3
"""Send audio file to Telegram group via Telethon."""

import asyncio
import os
import sys
from telethon import TelegramClient
from telethon.sessions import StringSession

# ПОМЕНЯЙ на путь к своему .env файлу
ENV_FILE = os.path.expanduser('~/.craft-podcast-telegram.env')
DEFAULT_GROUP = -1234567890  # ПОМЕНЯЙ на ID своей группы


def load_env(path):
    env = {}
    with open(path) as f:
        for line in f:
            line = line.strip()
            if '=' in line and not line.startswith('#'):
                k, v = line.split('=', 1)
                env[k.strip()] = v.strip().strip('"').strip("'")
    return env


async def send_audio(audio_file, group_id, caption):
    env = load_env(ENV_FILE)

    client = TelegramClient(
        StringSession(env['TELEGRAM_SESSION_STRING']),
        int(env['TELEGRAM_API_ID']),
        env['TELEGRAM_API_HASH'],
    )

    await client.connect()

    if not await client.is_user_authorized():
        print('ERROR: Not authorized')
        sys.exit(1)

    print('Connected. Sending...')
    result = await client.send_file(
        group_id,
        audio_file,
        caption=caption,
        voice=False,
    )
    print(f'Sent! Message ID: {result.id}')

    await client.disconnect()


if __name__ == '__main__':
    if len(sys.argv) < 3:
        print('Usage: telegram-sender.py <audio.mp3> <group_id> [caption]')
        sys.exit(1)

    audio = sys.argv[1]
    group = int(sys.argv[2]) if len(sys.argv) > 2 else DEFAULT_GROUP
    caption = sys.argv[3] if len(sys.argv) > 3 else ''

    asyncio.run(send_audio(audio, group, caption))

8. Что поменять под себя

Что Где Зачем
ENV_FILE telegram-sender.py строка 10 Путь к .env с Telegram credentials
DEFAULT_GROUP telegram-sender.py строка 11 ID группы/канала в Telegram
Пути ~/craft-podcasts/ SKILL.md (Phase 3 и 4) Где хранить аудио и транскрипты
Голоса tts-generator.py строка 13-14 Другие Edge TTS голоса (список: edge-tts --list-voices)
RATE tts-generator.py строка 16 Скорость речи (+50%, +100%, +0%)

9. Использование

В Claude Code просто пишешь:

craft podcast https://www.youtube.com/watch?v=VIDEO_ID

или

подкаст из видео https://youtu.be/VIDEO_ID

Claude сам достанет субтитры, изучит тему, напишет сценарий на русском, сгенерирует аудио и отправит в Telegram.

About

Claude Code skill: YouTube video → Russian podcast dialogue → Edge TTS → Telegram

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages