원클릭으로
gen-tts
Synthesize speech audio via Gemini 3.1 Flash TTS — single clip, batch parallel, voice + style presets
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Synthesize speech audio via Gemini 3.1 Flash TTS — single clip, batch parallel, voice + style presets
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Surface open PRs that have genuinely unaddressed review feedback, filtering out CodeRabbit auto-summaries and CI-bot noise. Use before ending a session, when asked "which of my PRs need attention", or to gate a session close on unresolved review threads.
Sync git repository with upstream. Use at the start of a session, when asked to sync, get up to date, check git status, or when working on a stale branch.
Analyze content and generate illustrations via Gemini image API
Brainstorm multiple visual directions for a blog image, generate them in parallel, build a comparison page, and optionally publish as a shareable link (Surge.sh or gist).
Bulk-parallel CLIs — turn N sequential gh/bd/git/file tool calls into a single fan-out JSON call. Use when the session is about to fire ≥3 similar sequential calls (gh pr view, bd show, Read of small files, up-to-date diagnose across repos).
Extract durable lessons from a completed Claude session and codify them in the right CLAUDE.md files or skills. Use at the end of a long session, after a bug hunt that surfaced a non-obvious constraint, or when the user asks "what can we learn from this session". Discovers CLAUDE.md files dynamically, routes lessons by generic scope (project / shared conventions / environment / machine-local), enforces neutral voice, and asks for approval before editing.
| name | gen-tts |
| description | Synthesize speech audio via Gemini 3.1 Flash TTS — single clip, batch parallel, voice + style presets |
| argument-hint | single --text <text> --output path.wav | batch file.json [--voice NAME] [--style-preset NAME] |
| allowed-tools | Bash, Read, Write, Glob, Grep, AskUserQuestion |
Turn text into natural-sounding speech via Google's Gemini 3.1 Flash TTS
preview. Supports single-clip generation, parallel batch mode, prosody
tags ([whisper], [short pause], [excited], …), and voice preset
files.
Parse the user's input for:
--text-file)--voice NAME: Voice preset name. Resolves in this order:
voices/<NAME>.txt in this skill dir — first non-comment line is the literal Gemini voiceName (for single-line voice-ID presets)Kore, Puck, Charon) passed straight throughtts-voice.txt (Charon ships as the default)--style-prompt TEXT: Director's-notes prefix prepended to the text (e.g. "Speak slowly, with a warm Newcastle accent."). Gemini honors these notes separately from the voice ID.--style-preset NAME: Load a multi-line style directive from voices/<NAME>.txt (e.g. freud, soprano). Comment lines stripped, body collapsed to one paragraph, prepended as a director's note. Mutually exclusive with --style-prompt / --style-file.--style-file PATH: Like --style-preset but takes an explicit file path (for styles kept outside the skill dir).--output path.wav: Where to save the WAV file--speed FLOAT: Post-process tempo multiplier applied via ffmpeg atempo after the Gemini call. 1.0 (default) = no change, 1.8 pairs well with the freud preset (the preset is deliberately slow; speeding to 1.8× tightens the phrasing without losing the character). Quality is best in [0.5, 2.0]; values outside that band chain atempo filters automatically. Gemini 3.1 Flash TTS has no server-side speed parameter, so post-processing is the deterministic path. Requires ffmpeg on PATH.batch file.json: Parallel batch mode subcommand (see shape below)--api-url URL: Override the Gemini endpoint (rarely needed; useful for testing against a proxy)--voice (Gemini voice ID) and --style-* (director's notes prepended to
the text) are independent and compose — e.g. --voice Charon --style-preset freud pairs the Charon baritone with Freud's Viennese pacing.
GOOGLE_API_KEY — auto-loaded from ~/.env by generate-tts.py (same var as gen-image). Passed as an x-goog-api-key header so the key never leaks into URL access logs, shell traces, or proxy logs.tts-voice.txt in this skill's directorygenerate-tts.py — handles the HTTP call, WAV assembly, env loading, voice resolution, and parallel batch execution. Stdlib core with Typer for CLI (no requests / httpx / jq / curl deps); the PEP-723 shebang (#!/usr/bin/env -S uv run --script) means it runs without a local venv. Two subcommands: single (one clip) and batch (parallel from JSON manifest).gemini-3.1-flash-tts-previewPOST https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-tts-preview:generateContentcandidates[0].content.parts[*].inlineData.data. generate-tts.py
wraps it in a canonical WAV header (via struct.pack) so the .wav
output is directly playable by any audio tool. Sample rate is parsed
from the response MIME type (audio/L16;codec=pcm;rate=24000) with
24000 as the fallback.Embed these inline in the text to steer delivery (Gemini interprets them rather than speaking them verbatim):
[whisper], [shouting], [sigh], [gasp],
[laughs], [crying][short pause], [long pause][excited], [tired], [sarcastic], [amazed],
[angry], [confused], [nervous], [calm], [warm]The model also accepts narrative "director's notes" prefixed to the
text — e.g. "Speak slowly, with a warm Newcastle accent: <text>" — per
Simon Willison's 2026-04-15 write-up. Use either approach; they compose.
30 prebuilt voices ship with the model. Ones we've found useful:
| Voice | Vibe | Use for |
|---|---|---|
Charon (default) | Deeper storyteller baritone | Larry-style grounding, long-form narration |
Kore | Firm, observer-coach (reads feminine) | Review reads when that vibe fits |
Puck | Upbeat, playful | Kickoff messages, celebratory clips |
Aoede | Warm, soft | Empathic/comfort lines |
Full catalog in tts-voice.txt. To lock in a named preset separately
from the default, drop voices/<name>.txt next to this file with the
literal voiceName on its first non-comment line.
voices/<name>.txt — two shapesFiles in voices/ serve two distinct purposes:
Kore, Charon, Puck, etc.). Used via
--voice <name>. The rest of the file is commentary on when to pick it.--style-preset <name>. Comment lines are stripped; the body is
prepended to the text as a director's note. These do NOT pick a
Gemini voice — pair them with --voice Charon (or whichever voice
ID suits the character) for best results.Shipped style presets: freud, soprano.
The script is executable and uses a uv-powered PEP-723 shebang — invoke it directly, no python3 prefix needed:
GEN_TTS="$(git -C ~/gits/chop-conventions rev-parse --show-toplevel)/skills/gen-tts/generate-tts.py"
"$GEN_TTS" single --text "Hello from Larry. [short pause] This is a voice pipeline test." --output /tmp/larry.wav
"$GEN_TTS" single --text-file /tmp/script.txt --output /tmp/read.wav --voice Charon
echo "piped text" | "$GEN_TTS" single --output /tmp/piped.wav
# Freud's Viennese analyst voice, baritone
"$GEN_TTS" single --text "Tell me about your mother." --voice Charon \
--style-preset freud --output /tmp/freud.wav
# Freud at 1.8× — same deliberate phrasing, tighter tempo
"$GEN_TTS" single --text "Tell me about your mother." --voice Charon \
--style-preset freud --speed 1.8 --output /tmp/freud-fast.wav
# Inline director's notes (no preset)
"$GEN_TTS" single --text "Welcome aboard." --voice Puck \
--style-prompt "Speak with the warmth of a flight attendant greeting family." \
--output /tmp/welcome.wav
Write a JSON file:
[
{
"text": "Good morning. [short pause] Ready to start?",
"output": "/tmp/morning.wav",
"voice": "Kore"
},
{
"text": "[excited] You nailed that workout!",
"output": "/tmp/celebrate.wav",
"voice": "Puck"
},
{ "text": "[whisper] Time to wind down.", "output": "/tmp/bedtime.wav" },
{
"text": "Tell me about your father.",
"output": "/tmp/freud.wav",
"voice": "Charon",
"style_preset": "freud"
}
]
Each job object accepts text, output, voice, plus any one of
style_prompt / style_preset / style_file, plus an optional speed
float. A --style-* or --speed flag on the CLI provides a default that
per-job entries can override.
Then:
"$GEN_TTS" batch /tmp/lines.json --max-workers 4
_duration_s is written back into each job object for debug visibility. The batch file is rewritten atomically (tempfile + os.replace) so a crash mid-write never corrupts the input.
~/.env. If still unset, set GOOGLE_API_KEY in env or ~/.env.error.message (malformed request, quota exhausted, billing not enabled, TTS preview not enabled) is surfaced verbatim with an API Error: prefix.promptFeedback.blockReason surfaces as Gemini TTS refused the prompt (blockReason=...) with the specific reason (e.g. PROHIBITED_CONTENT) plus any safetyRatings for diagnosis.candidates[0].finishReason of SAFETY / PROHIBITED_CONTENT / RECITATION / OTHER (anything other than STOP / MAX_TOKENS) surfaces as refused to generate audio (finishReason=...). Most common trigger: certain prosody tags ([excited], [whisper]) combined with flavorful content trip the filter. Retry without the tag or rephrase.HTTP request failed after retry: ....urllib.request, base64, struct, json). No jq / curl / requests / httpx required — just a Python 3.11+ interpreter managed by uv (the PEP-723 shebang bootstraps it)./tmp/ or the consumer repo's assets dir.