
Speech Use
- 56 installs
- 124 repo stars
- Updated February 6, 2026
- cnemri/google-genai-skills
Generates speech, transcribes audio, and clones voices via portable Python scripts using Google GenAI and Cloud Speech (Gemini-TTS, Chirp 3, Instant Custom Voice).
About
Runs TTS, STT, and voice cloning through ready-made scripts over Google's speech SDKs. A developer uses it to synthesize speech, transcribe audio, or create a custom voice from the CLI.
- generate_speech, transcribe_audio, and create_custom_voice scripts
- Prebuilt and cloned voices with consent-audio requirement
Speech Use by the numbers
- 56 all-time installs (skills.sh)
- Ranked #872 of 1,335 Generative Media skills by installs in the Skillselion catalog
- Data as of Jul 29, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cnemri/google-genai-skills --skill speech-useAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 56 |
|---|---|
| repo stars | ★ 124 |
| Last updated | February 6, 2026 |
| Repository | cnemri/google-genai-skills ↗ |
What it does
Generates speech, transcribes audio, and clones voices via portable Python scripts using Google GenAI and Cloud Speech (Gemini-TTS, Chirp 3, Instant Custom Voice).
Files
Speech Use
Use this skill to perform Text-to-Speech (TTS), Speech-to-Text (STT), and Voice Cloning operations.
This skill uses portable Python scripts managed by uv.
Prerequisites
1. Environment Variables:
-
GOOGLE_API_KEY(for TTS via Gemini) -
GOOGLE_CLOUD_PROJECT(Required for STT and Voice Cloning) -
GOOGLE_APPLICATION_CREDENTIALS(Recommended for STT/Voice Cloning)
2. APIs Enabled:
- Text-to-Speech API (
texttospeech.googleapis.com) - Speech-to-Text API (
speech.googleapis.com)
Usage
1. Generate Speech (TTS)
Generate audio from text using Gemini-TTS.
Standard Voice:
uv run skills/speech-use/scripts/generate_speech.py "Hello world, this is a test." --voice Puck --output hello.wavCustom Voice (Cloned):
uv run skills/speech-use/scripts/generate_speech.py "This is my custom voice speaking." --voice-cloning-key "YOUR_KEY_HERE" --output custom.wav2. Create Custom Voice (Voice Cloning)
Generate a voiceCloningKey from a reference audio file and a consent file.
Requirements:
-
reference.wav: 10-30s of clear speech (the voice to clone). -
consent.wav: The speaker saying: "I am the owner of this voice and I consent to Google using this voice to create a synthetic voice model."
uv run skills/speech-use/scripts/create_custom_voice.py --reference-audio reference.wav --consent-audio consent.wavSave the output key to use with `generate_speech.py`.
3. Transcribe Audio (STT)
Transcribe audio files using Chirp 3.
uv run skills/speech-use/scripts/transcribe_audio.py audio.wav --language en-US --output transcript.txtOptions
generate_speech.py
-
--voice: Prebuilt voice (e.g.,Kore,Puck,Fenrir,Aoede). -
--voice-cloning-key: Key fromcreate_custom_voice.py. -
--model: Defaultgemini-2.5-flash-preview-tts.
transcribe_audio.py
-
--model: Defaultchirp_3. -
--language: Defaultauto. -
--location: Cloud region (defaultus).
References
Before running scripts, review the reference guides for available voices and options.
- Voices Guide - 30+ voice options with styles (Puck, Kore, Fenrir, Aoede, etc.)
Voices & Locales
Gemini-TTS Voices
30 options available. Use these names in voice_name.
| Voice Name | Style | Voice Name | Style |
|---|---|---|---|
| Zephyr | Bright | Puck | Upbeat |
| Kore | Firm | Fenrir | Excitable |
| Orus | Firm | Leda | Youthful |
| Aoede | Breezy | Callirrhoe | Easy-going |
| Charon | Informative | Enceladus | Breathy |
| Iapetus | Clear | Umbriel | Easy-going |
| Algieba | Smooth | Despina | Smooth |
| Erinome | Clear | Algenib | Gravelly |
| Rasalgethi | Informative | Laomedeia | Upbeat |
| Achernar | Soft | Alnilam | Firm |
| Schedar | Even | Gacrux | Mature |
| Pulcherrima | Forward | Achird | Friendly |
| Zubenelgenubi | Casual | Vindemiatrix | Gentle |
| Sadachbia | Lively | Sadaltager | Knowledgeable |
| Sulafat | Warm | Autonoe | Bright |
Chirp 3 HD Voices
Currently 8 distinct voices (4 male, 4 female) available in 31 languages. Common examples: Aoede, Puck, Charon, Kore, Fenrir, Leda, Orus, Zephyr.
Locales (Gemini-TTS)
Supports 24 languages including:
en-US,en-GB,en-INes-US,es-ESfr-FR,de-DEja-JP,ko-KRpt-BRhi-IN- And more.
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "requests",
# "python-dotenv",
# "google-auth",
# ]
# ///
import argparse
import base64
import json
import os
from dotenv import load_dotenv
import sys
import requests
import google.auth
import google.auth.transport.requests
load_dotenv()
def get_credentials():
credentials, _ = google.auth.default()
request = google.auth.transport.requests.Request()
credentials.refresh(request)
return credentials
def wav_to_base64(file_path):
try:
with open(file_path, "rb") as wav_file:
encoded_string = base64.b64encode(wav_file.read()).decode("utf-8")
return encoded_string
except FileNotFoundError:
print(f"Error: File not found at {file_path}")
sys.exit(1)
except Exception as e:
print(f"Error reading file: {e}")
sys.exit(1)
def create_instant_custom_voice_key(reference_audio_path, consent_audio_path, project_id, location="us"):
api_endpoint = "texttospeech.googleapis.com"
if location != "global" and location != "us":
# Regional endpoints might differ, but instant custom voice is often US/Global.
# The notebook uses global or us-texttospeech.
# Let's default to texttospeech.googleapis.com as per notebook example for global/us.
pass
url = f"https://{api_endpoint}/v1beta1/voices:generateVoiceCloningKey"
reference_audio_b64 = wav_to_base64(reference_audio_path)
consent_audio_b64 = wav_to_base64(consent_audio_path)
request_body = {
"reference_audio": {
"audio_config": {"audio_encoding": "LINEAR16", "sample_rate_hertz": 24000},
"content": reference_audio_b64,
},
"voice_talent_consent": {
"audio_config": {"audio_encoding": "LINEAR16", "sample_rate_hertz": 24000},
"content": consent_audio_b64,
},
"consent_script": "I am the owner of this voice and I consent to Google using this voice to create a synthetic voice model.",
"language_code": "en-US",
}
credentials = get_credentials()
headers = {
"Authorization": f"Bearer {credentials.token}",
"x-goog-user-project": project_id,
"Content-Type": "application/json; charset=utf-8",
}
try:
response = requests.post(url, headers=headers, json=request_body)
response.raise_for_status()
response_json = response.json()
return response_json.get("voiceCloningKey")
except requests.exceptions.RequestException as e:
print(f"Error making API request: {e}")
if response is not None:
print("Response text:", response.text)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description="Create an Instant Custom Voice key.")
parser.add_argument("--reference-audio", required=True, help="Path to reference audio file (WAV).")
parser.add_argument("--consent-audio", required=True, help="Path to consent audio file (WAV).")
parser.add_argument("--project-id", help="Google Cloud Project ID.")
args = parser.parse_args()
project_id = args.project_id or os.environ.get("GOOGLE_CLOUD_PROJECT")
if not project_id:
print("=" * 60)
print("ERROR: Missing required Google Cloud Project ID!")
print("=" * 60)
print()
print("Please create a .env file in your project root or add the")
print("following environment variable to your existing .env file:")
print()
print(" GOOGLE_CLOUD_PROJECT=your-project-id")
print()
print("Alternatively, pass --project-id as a command line argument.")
print()
print("Note: For custom voice creation, ensure you have Application")
print("Default Credentials configured:")
print(" gcloud auth application-default login")
print("=" * 60)
sys.exit(1)
print("Generating Voice Cloning Key...")
key = create_instant_custom_voice_key(args.reference_audio, args.consent_audio, project_id)
if key:
print("SUCCESS! Voice Cloning Key:")
print(key)
print("\nSave this key to use with generate_speech.py --voice-cloning-key")
else:
print("Failed to generate key.")
if __name__ == "__main__":
main()
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "google-genai",
# "python-dotenv",
# "pillow",
# ]
# ///
import os
from dotenv import load_dotenv
import argparse
import sys
import wave
from google import genai
from google.genai import types
load_dotenv()
def save_wav(filename, pcm_data, channels=1, rate=24000, sample_width=2):
with wave.open(filename, "wb") as wf:
wf.setnchannels(channels)
wf.setsampwidth(sample_width)
wf.setframerate(rate)
wf.writeframes(pcm_data)
def get_client():
api_key = os.environ.get("GOOGLE_API_KEY") or os.environ.get("GEMINI_API_KEY")
if api_key:
return genai.Client(api_key=api_key)
project = os.environ.get("GOOGLE_CLOUD_PROJECT")
location = os.environ.get("GOOGLE_CLOUD_LOCATION")
use_vertex = os.environ.get("GOOGLE_GENAI_USE_VERTEXAI", "").lower()
if project and location and use_vertex in ("1", "true"):
return genai.Client(vertexai=True, project=project, location=location)
print("=" * 60)
print("ERROR: Missing required environment variables!")
print("=" * 60)
print()
print("Please create a .env file in your project root or add the")
print("following environment variables to your existing .env file:")
print()
print("Option 1 - Using Gemini API Key:")
print(" GOOGLE_API_KEY=your-api-key-here")
print()
print("Option 2 - Using Vertex AI:")
print(" GOOGLE_CLOUD_PROJECT=your-project-id")
print(" GOOGLE_CLOUD_LOCATION=us-central1")
print(" GOOGLE_GENAI_USE_VERTEXAI=1")
print()
print("Note: For Speech APIs, location must be 'us-central1'.")
print("=" * 60)
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description="Generate speech using Gemini-TTS.")
parser.add_argument("text", help="Text to speak")
parser.add_argument("--voice", default="Puck", help="Prebuilt voice name (e.g. Kore, Puck). Ignored if --voice-cloning-key is set.")
parser.add_argument("--voice-cloning-key", help="Instant Custom Voice Cloning Key")
parser.add_argument("--model", default="gemini-2.5-flash-preview-tts", help="TTS Model")
parser.add_argument("--output", default="output.wav", help="Output filename")
args = parser.parse_args()
client = get_client()
try:
if args.voice_cloning_key:
print(f"Using Custom Voice Key: {args.voice_cloning_key[:8]}...")
voice_config = types.VoiceConfig(
voice_clone=types.VoiceClone(voice_cloning_key=args.voice_cloning_key)
)
else:
print(f"Using Prebuilt Voice: {args.voice}")
voice_config = types.VoiceConfig(
prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=args.voice)
)
config = types.GenerateContentConfig(
response_modalities=["AUDIO"],
speech_config=types.SpeechConfig(
voice_config=voice_config
)
)
print(f"Generating speech with model {args.model}...")
response = client.models.generate_content(
model=args.model,
contents=args.text,
config=config
)
if response.candidates and response.candidates[0].content.parts:
part = response.candidates[0].content.parts[0]
if part.inline_data:
save_wav(args.output, part.inline_data.data)
print(f"Audio saved to {args.output}")
else:
print("No inline audio data found.")
else:
print("No candidates returned.")
except Exception as e:
print(f"Error generating speech: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "google-cloud-speech",
# "python-dotenv",
# ]
# ///
import argparse
import os
from dotenv import load_dotenv
import sys
from google.cloud.speech_v2 import SpeechClient
from google.cloud.speech_v2.types import cloud_speech
from google.api_core.client_options import ClientOptions
load_dotenv()
def get_client(location="us"):
api_endpoint = f"{location}-speech.googleapis.com" if location != "global" else "speech.googleapis.com"
client_options = ClientOptions(api_endpoint=api_endpoint)
return SpeechClient(client_options=client_options)
def main():
parser = argparse.ArgumentParser(description="Transcribe audio using Chirp 3.")
parser.add_argument("audio_file", help="Path to input audio file")
parser.add_argument("--model", default="chirp_3", help="Model ID (default: chirp_3)")
parser.add_argument("--language", default="auto", help="Language code (default: auto)")
parser.add_argument("--project-id", help="Google Cloud Project ID")
parser.add_argument("--location", default="us", help="Location (e.g. us, eu, global)")
parser.add_argument("--output", default="transcript.txt", help="Output text filename")
args = parser.parse_args()
project_id = args.project_id or os.environ.get("GOOGLE_CLOUD_PROJECT")
if not project_id:
print("=" * 60)
print("ERROR: Missing required Google Cloud Project ID!")
print("=" * 60)
print()
print("Please create a .env file in your project root or add the")
print("following environment variable to your existing .env file:")
print()
print(" GOOGLE_CLOUD_PROJECT=your-project-id")
print()
print("Alternatively, pass --project-id as a command line argument.")
print()
print("Note: For transcription, ensure you have Application Default")
print("Credentials configured (run: gcloud auth application-default login)")
print("=" * 60)
sys.exit(1)
client = get_client(args.location)
try:
with open(args.audio_file, "rb") as f:
content = f.read()
config = cloud_speech.RecognitionConfig(
auto_decoding_config=cloud_speech.AutoDetectDecodingConfig(),
model=args.model,
language_codes=[args.language],
features=cloud_speech.RecognitionFeatures(
# enable_word_time_offsets=True,
),
)
request = cloud_speech.RecognizeRequest(
recognizer=f"projects/{project_id}/locations/{args.location}/recognizers/_",
config=config,
content=content,
)
print(f"Transcribing {args.audio_file}...")
response = client.recognize(request=request)
full_transcript = ""
for result in response.results:
transcript = result.alternatives[0].transcript
full_transcript += transcript + "\n"
print("Transcript:")
print(full_transcript)
with open(args.output, "w") as f:
f.write(full_transcript)
print(f"Transcript saved to {args.output}")
except Exception as e:
print(f"Error transcribing audio: {e}")
sys.exit(1)
if __name__ == "__main__":
main()