Community Скиллы Российские сервисы

Озвучка через Яндекс Станцию

Установка
git clone (см. README)

Описание

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 Яндекс Станции. Скрипт:

  1. Получает conversation_token через Yandex Quasar API (OAuth-авторизация)
  2. Подключается к станции напрямую по локальной сети (WSS, порт 1961)
  3. Отправляет команду repeat_phrase — станция произносит текст голосом Алисы
  4. Токен кешируется на 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