Описание
claude-skill-yandex-tts — скилл голосового вывода для Claude Code: голос Алисы — ответы агента озвучиваются на Яндекс Станции, локальная сеть — колонка управляется без облачных сервисов, сценарий «спросил-услышал» — удобно для рутинных проверок без экрана. Для владельцев Яндекс Станции, желающих получать ответы агента голосом.
Что умеет:
— озвучивать ответы голосом Алисы;
— управлять колонкой по локальной сети;
— работать без облачных сервисов;
— выводить результаты без экрана.
Полная документация ниже — автоматически из репозитория rasperepodvipodvert/claude-skill-yandex-tts (ветка main). Оригинальные материалы проекта распространяются на условиях его лицензии.
claude-skill-yandex-tts — Claude Code Skill для озвучки через Яндекс Станцию
Скилл для Claude Code, позволяющий озвучивать ответы через Яндекс Станцию голосом Алисы. Когда пользователь просит сказать что-то через колонку или озвучить ответ, Claude Code автоматически отправляет текст на станцию.
Как это работает
┌─────────────┐ ┌──────────────┐ ┌───────────────────┐ ┌────────────────┐
│ Claude Code │────>│ /speak │────>│ Yandex Quasar │────>│ Яндекс Станция │
│ (CLI) │ │ tts.py │ │ API (Glagol) │ │ (Алиса) │
└─────────────┘ └──────────────┘ └───────────────────┘ └────────────────┘
Чистый Python 3 WebSocket (WSS) Озвучка текста
Только stdlib порт 1961 голосом Алисы
Протокол Glagol — это локальный WebSocket API Яндекс Станции. Скрипт:
- Получает
conversation_tokenчерез Yandex Quasar API (OAuth-авторизация) - Подключается к станции напрямую по локальной сети (WSS, порт 1961)
- Отправляет команду
repeat_phrase— станция произносит текст голосом Алисы - Токен кешируется на 25 минут, IP станции обнаруживается автоматически через mDNS
Требования
- Python 3.10+ (используются type hints
dict[str, str],str | None) - macOS (mDNS-обнаружение через
dns-sd; на Linux нужно указать IP вручную) - Яндекс аккаунт с привязанной Яндекс Станцией
- Компьютер и станция должны быть в одной локальной сети
Внешних зависимостей нет — скрипт использует только стандартную библиотеку Python.
Установка
1. Клонировать репозиторий
git clone git@github.com:rasperepodvipodvert/claude-skill-yandex-tts.git ~/.claude/skills/speak
2. Создать конфиг
cp ~/.claude/skills/speak/.env.example ~/.claude/skills/speak/.env
3. Получить токены (см. раздел ниже)
Заполнить MUSIC_TOKEN в файле .env.
4. Узнать Device ID
~/.claude/skills/speak/scripts/tts.py --list-devices
Вывод покажет все колонки на аккаунте:
Fetching device list...
Scanning local network via mDNS...
Станция Мини platform=yandexmini_2 id=XXXXXXXXXXXXXXX IP: 192.168.1.100
Скопировать id и platform в .env:
DEVICE_ID=XXXXXXXXXXXXXXX
DEVICE_PLATFORM=yandexmini_2
5. Проверить
~/.claude/skills/speak/scripts/tts.py "Привет, я Claude!"
Если все настроено правильно, колонка произнесет текст.
6. Сделать скрипт исполняемым (если нужно)
chmod +x ~/.claude/skills/speak/scripts/tts.py
Получение токенов
Для работы нужен MUSIC_TOKEN (он же OAuth-токен Яндекса). Процедура получения основана на методе из проекта AlexxIT/YandexStation и использует публичные client_id/client_secret приложения Яндекс.Музыка.
Шаг 1: Получить session_id через логин
Залогиниться на https://passport.yandex.ru и из cookies взять Session_id.
Или программно (требует ввода пароля, 2FA и т.д.) — рекомендуется вручную через браузер.
Шаг 2: Получить x_token
curl -s 'https://mobileproxy.passport.yandex.net/1/bundle/oauth/token_by_sessionid' \
-H 'Ya-Client-Host: passport.yandex.ru' \
-H 'Ya-Client-Cookie: Session_id=YOUR_SESSION_ID_HERE' \
-d 'client_id=c0ebe342af7d48fbbbfcf2d2eedb8f9e&client_secret=ad0a908f0aa341a182a37ecd75bc319e'
Ответ содержит x_token:
{"status": "ok", "x_token": "y0_AgAAAA..."}
Шаг 3: Получить music_token (OAuth)
curl -s 'https://oauth.yandex.ru/token' \
-d 'grant_type=x-token&client_id=23cabbbdc6cd418abb4b39c32c41195d&client_secret=53bc75238f0c4d08a118e51fe9203300&access_token=YOUR_X_TOKEN_HERE'
Ответ содержит access_token — это и есть MUSIC_TOKEN:
{"access_token": "y0_AgAAAAAF...", "token_type": "bearer", ...}
Шаг 4: Записать в .env
MUSIC_TOKEN=y0_AgAAAAAF...
Примечание:
client_idиclient_secretв командах выше — публичные ключи приложений Яндекса (из проекта YandexStation). Они не являются секретами.
Срок жизни MUSIC_TOKEN: токен действует примерно 1 год. После истечения нужно повторить процедуру получения (шаги 1–3).
Использование
Из командной строки
# Озвучить текст
~/.claude/skills/speak/scripts/tts.py "Доброе утро! Сегодня будет солнечно."
# Список всех колонок на аккаунте (с mDNS-обнаружением IP)
~/.claude/skills/speak/scripts/tts.py --list-devices
# Обнаружить IP станции через mDNS и сохранить в .env
~/.claude/skills/speak/scripts/tts.py --discover
Как скилл Claude Code
После установки в ~/.claude/skills/speak/ скилл доступен автоматически. Claude Code будет использовать его, когда:
- Пользователь просит озвучить ответ
- Пользователь просит сказать что-то через колонку
- В разговоре уместно озвучить ответ голосом
Пример:
> /speak Расскажи анекдот через колонку
Конфигурация (.env)
| Переменная | Описание | Обязательная |
|---|---|---|
MUSIC_TOKEN |
OAuth-токен Яндекса | Да |
DEVICE_ID |
ID устройства (из --list-devices) |
Да |
DEVICE_PLATFORM |
Платформа (например yandexmini_2) |
Да |
STATION_IP |
IP-адрес станции (автообнаружение через mDNS) | Нет* |
CONVERSATION_TOKEN |
Кешированный токен сессии (auto-managed) | Нет |
CONVERSATION_TOKEN_EXPIRES |
Время истечения токена (auto-managed) | Нет |
* Если STATION_IP не указан или станция не отвечает, скрипт попытается найти её через mDNS автоматически.
Особенности
- Нулевые зависимости — чистый Python 3, только stdlib. WebSocket-клиент реализован вручную по RFC 6455.
- Автообнаружение IP — станция ищется через mDNS (сервис
_yandexio._tcp). На macOS используетdns-sd. - Кеширование токенов —
conversation_tokenсохраняется в.envи обновляется каждые 25 минут. - Очистка текста — Markdown-разметка, блоки кода, спецсимволы автоматически удаляются перед озвучкой.
- Лимит 500 символов — длинные тексты обрезаются.
Совместимость колонок
Скрипт работает с любыми колонками Яндекса, поддерживающими протокол Glagol:
| Модель | Platform ID |
|---|---|
| Яндекс Станция (большая) | yandexstation |
| Яндекс Станция 2 | yandexstation_2 |
| Яндекс Станция Макс | yandexstation_2 |
| Яндекс Станция Мини | yandexmini |
| Яндекс Станция Мини 2 | yandexmini_2 |
| Яндекс Станция Лайт | yandexmicro |
| Яндекс Модуль | yandexmodule |
| Яндекс Модуль 2 | yandexmodule_2 |
| JBL Link Portable | linkplay_a98 |
| JBL Link Music | jbl_link_music |
| Elari SmartBeat | elari_a98 |
| DEXP Smartbox | dexp_smartbox |
Platform ID может отличаться у разных ревизий. Используйте
--list-devicesдля получения точного значения.
Troubleshooting
| Проблема | Решение |
|---|---|
connection refused на порт 1961 |
Станция офлайн или компьютер не в той же сети. Проверь, что станция включена и оба устройства в одной LAN. |
| mDNS не находит станцию | Убедись, что компьютер и станция в одной сети. На Linux mDNS может не работать — укажи IP вручную в STATION_IP в .env. |
conversation_token протух (ошибки авторизации при отправке) |
Удали CONVERSATION_TOKEN и CONVERSATION_TOKEN_EXPIRES из .env — скрипт получит новый токен автоматически. |
token expired / ошибки с MUSIC_TOKEN |
Токен истёк (срок жизни ~1 год). Повтори процедуру получения MUSIC_TOKEN (шаги 1–3 из раздела «Получение токенов»). |
Лицензия
MIT