Generate Russian Speech from Text
Claude Code skill that speaks its answers out loud through a Yandex Station smart speaker in Alice's voice, over the local Glagol protocol.
Why it matters
Leverage Yandex SpeechKit TTS to generate high-quality audio from Russian text. This asset is ideal for applications requiring natural-sounding voiceovers or spoken content in Russian.
Outcomes
What it gets done
Convert Russian text into spoken audio
Utilize Yandex SpeechKit for TTS generation
Provide audio output for various applications
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/yandex-tts | bash Overview
Yandex Text-to-Speech
Lets Claude Code speak its answers out loud through a Yandex Station smart speaker, using Alice's voice. It connects to the station over the local Glagol WebSocket protocol and sends the text via a repeat_phrase command. Use it when a response should be read aloud through a Yandex smart speaker instead of just displayed as text. Requires a Yandex account with a linked station on the same local network as the machine running Claude Code.
What it does
The Yandex Text-to-Speech skill lets Claude Code speak its responses out loud through a Yandex Station smart speaker, in Alice's voice. When a user asks Claude to say something through the speaker, Claude Code sends the text to a small Python script (tts.py), which talks to the Yandex Quasar API to obtain a conversation_token, then connects directly to the station over the local network via the Glagol protocol - a local WebSocket API on port 1961 - and issues a repeat_phrase command that makes the station speak the text.
When to use - and when NOT to
Use it whenever a user asks for a spoken answer through the speaker, or whenever it's contextually useful to have the response read aloud by Alice. It is not a general text-to-speech engine for arbitrary output devices - it only works with Yandex speakers that support the Glagol protocol, and only when the computer running Claude Code and the station are on the same local network. Long responses are not fully spoken either: text is capped at 500 characters, and anything past that limit is truncated, so it is best suited to short confirmations or summaries rather than long-form narration.
Inputs and outputs
Setup is a one-time process: clone the skill into ~/.claude/skills/speak, copy .env.example to .env, and fill in a MUSIC_TOKEN (a Yandex OAuth token obtained via a documented session-id -> x_token -> music_token exchange, based on the method from the AlexxIT/YandexStation project). Running tts.py --list-devices discovers every speaker on the account via mDNS and prints its id and platform, which are copied into DEVICE_ID and DEVICE_PLATFORM in .env:
~/.claude/skills/speak/scripts/tts.py --list-devices
Once configured, tts.py "some text" sends that text to the station to be spoken; --discover finds and saves the station's IP via mDNS. The CONVERSATION_TOKEN and its expiry are cached automatically and refreshed roughly every 25 minutes; before speaking, the script strips Markdown formatting, code blocks, and special characters from the input text.
Integrations
There are no external runtime dependencies - the skill is pure Python 3.10+ standard library, including its own WebSocket client implemented per RFC 6455. It requires macOS for automatic IP discovery (via the dns-sd command over mDNS's _yandexio._tcp service); on Linux the station's IP must be set manually via STATION_IP. It works with any Yandex speaker that speaks Glagol, including the Yandex Station, Station 2, Station Max, Station Mini, Station Mini 2, Station Lite, Yandex Module/Module 2, and several third-party Glagol-compatible speakers (JBL Link Portable, JBL Link Music, Elari SmartBeat, DEXP Smartbox). Common failure modes documented include a refused connection on port 1961 (station offline or on a different network), a stale MUSIC_TOKEN after roughly a year (requiring the token procedure again), and an expired CONVERSATION_TOKEN, which self-heals by simply deleting the cached token fields from .env.
Who it's for
Users running Claude Code at home or in a home-office setup who already own a Yandex Station (or another Glagol-compatible speaker) and want Claude's answers read aloud through it, rather than only displayed as text.
Source README
claude-skill-yandex-tts -- Claude Code Skill for text-to-speech via Yandex Station
A skill for Claude Code that enables voice output through Yandex Station using Alice's voice. When a user asks to speak something through the speaker or have an answer read aloud, Claude Code automatically sends the text to the station.
How it works
┌─────────────┐ ┌──────────────┐ ┌───────────────────┐ ┌────────────────┐
│ Claude Code │────>│ /speak │────>│ Yandex Quasar │────>│ Yandex Station │
│ (CLI) │ │ tts.py │ │ API (Glagol) │ │ (Alice) │
└─────────────┘ └──────────────┘ └───────────────────┘ └────────────────┘
Pure Python 3 WebSocket (WSS) Text-to-speech
Stdlib only port 1961 with Alice voice
Glagol protocol is the local WebSocket API for Yandex Station. The script:
- Obtains
conversation_tokenvia Yandex Quasar API (OAuth authorization) - Connects directly to the station over local network (WSS, port 1961)
- Sends
repeat_phrasecommand -- the station speaks the text in Alice's voice - Token is cached for 25 minutes, station IP is auto-discovered via mDNS
Requirements
- Python 3.10+ (uses type hints
dict[str, str],str | None) - macOS (mDNS discovery via
dns-sd; on Linux you need to specify IP manually) - Yandex account with a linked Yandex Station
- Computer and station must be on the same local network
No external dependencies -- the script uses only Python's standard library.
Installation
1. Clone the repository
git clone git@github.com:rasperepodvipodvert/claude-skill-yandex-tts.git ~/.claude/skills/speak
2. Create config
cp ~/.claude/skills/speak/.env.example ~/.claude/skills/speak/.env
3. Get tokens (see section below)
Fill in MUSIC_TOKEN in the .env file.
4. Find Device ID
~/.claude/skills/speak/scripts/tts.py --list-devices
Output will show all speakers on your account:
Fetching device list...
Scanning local network via mDNS...
Station Mini platform=yandexmini_2 id=XXXXXXXXXXXXXXX IP: 192.168.1.100
Copy the id and platform to .env:
DEVICE_ID=XXXXXXXXXXXXXXX
DEVICE_PLATFORM=yandexmini_2
5. Test
~/.claude/skills/speak/scripts/tts.py "Hello, I'm Claude!"
If everything is configured correctly, the speaker will say the text.
6. Make script executable (if needed)
chmod +x ~/.claude/skills/speak/scripts/tts.py
Getting tokens
You need a MUSIC_TOKEN (Yandex OAuth token). The token retrieval procedure is based on the method from the AlexxIT/YandexStation project and uses public client_id/client_secret from the Yandex Music app.
Step 1: Get session_id via login
Log in to https://passport.yandex.ru and extract Session_id from cookies.
Or programmatically (requires password, 2FA, etc.) -- manual retrieval via browser is recommended.
Step 2: Get 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'
Response contains x_token:
{"status": "ok", "x_token": "y0_AgAAAA..."}
Step 3: Get 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'
Response contains access_token -- this is your MUSIC_TOKEN:
{"access_token": "y0_AgAAAAAF...", "token_type": "bearer", ...}
Step 4: Write to .env
MUSIC_TOKEN=y0_AgAAAAAF...
Note: The
client_idandclient_secretin the commands above are public keys from Yandex apps (from the YandexStation project). They are not secrets.
MUSIC_TOKEN lifetime: The token is valid for approximately 1 year. After expiration, repeat the retrieval procedure (steps 1--3).
Usage
From command line
# Speak text
~/.claude/skills/speak/scripts/tts.py "Good morning! It will be sunny today."
# List all speakers on account (with mDNS IP discovery)
~/.claude/skills/speak/scripts/tts.py --list-devices
# Discover station IP via mDNS and save to .env
~/.claude/skills/speak/scripts/tts.py --discover
As a Claude Code skill
After installation in ~/.claude/skills/speak/, the skill is available automatically. Claude Code will use it when:
- User asks to read the answer aloud
- User asks to say something through the speaker
- It makes sense in the conversation to speak the answer
Example:
> /speak Tell me a joke through the speaker
Configuration (.env)
| Variable | Description | Required |
|---|---|---|
MUSIC_TOKEN |
Yandex OAuth token | Yes |
DEVICE_ID |
Device ID (from --list-devices) |
Yes |
DEVICE_PLATFORM |
Platform (e.g. yandexmini_2) |
Yes |
STATION_IP |
Station IP address (auto-discovered via mDNS) | No* |
CONVERSATION_TOKEN |
Cached session token (auto-managed) | No |
CONVERSATION_TOKEN_EXPIRES |
Token expiration time (auto-managed) | No |
* If STATION_IP is not specified or the station doesn't respond, the script will attempt to find it via mDNS automatically.
Features
- Zero dependencies -- pure Python 3, stdlib only. WebSocket client implemented manually per RFC 6455.
- Auto IP discovery -- station is found via mDNS (
_yandexio._tcpservice). On macOS usesdns-sd. - Token caching --
conversation_tokenis saved to.envand refreshed every 25 minutes. - Text cleanup -- Markdown formatting, code blocks, special characters are automatically removed before playback.
- 500 character limit -- longer texts are truncated.
Speaker compatibility
The script works with any Yandex speaker that supports the Glagol protocol:
| Model | Platform ID |
|---|---|
| Yandex Station (large) | yandexstation |
| Yandex Station 2 | yandexstation_2 |
| Yandex Station Max | yandexstation_2 |
| Yandex Station Mini | yandexmini |
| Yandex Station Mini 2 | yandexmini_2 |
| Yandex Station Lite | yandexmicro |
| Yandex Module | yandexmodule |
| Yandex Module 2 | yandexmodule_2 |
| JBL Link Portable | linkplay_a98 |
| JBL Link Music | jbl_link_music |
| Elari SmartBeat | elari_a98 |
| DEXP Smartbox | dexp_smartbox |
Platform ID may differ across revisions. Use
--list-devicesto get the exact value.
Troubleshooting
| Issue | Solution |
|---|---|
connection refused on port 1961 |
Station is offline or computer is not on the same network. Check that the station is on and both devices are on the same LAN. |
| mDNS can't find station | Make sure computer and station are on the same network. On Linux mDNS may not work -- specify IP manually in STATION_IP in .env. |
conversation_token expired (auth errors when sending) |
Delete CONVERSATION_TOKEN and CONVERSATION_TOKEN_EXPIRES from .env -- the script will get a new token automatically. |
token expired / errors with MUSIC_TOKEN |
Token has expired (lifetime ~1 year). Repeat the MUSIC_TOKEN retrieval procedure (steps 1--3 from "Getting tokens" section). |
FAQ
Common questions
Discussion
Questions & comments · 0
Sign In Sign in to leave a comment.