Google Cloud Speech Free code examples in C#, Python, Java and JavaScript
Google's text-to-speech and speech-to-text, with many Indian languages.
WHAT THIS PAGE COVERS
Hindi and other Indic voices, and how the language codes actually work.
hi-IN-Chirp3-HD-Charon
google-cloud-texttospeech
Model ids change. If a sample returns a 404 on the model, that is the first thing to check against the official docs.
Google ships a first-party .NET client for this one — unlike Gemini, where the .NET path is the REST API. Auth is still Application Default Credentials.
dotnet add package Google.Cloud.TextToSpeech.V1
setx GOOGLE_APPLICATION_CREDENTIALS "C:\path\to\service-account.json"
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
Create() picks up Application Default Credentials. AudioContent is a ByteString, so WriteTo on a file stream avoids copying the whole clip into a byte array first.
using Google.Cloud.TextToSpeech.V1;
var client = await TextToSpeechClient.CreateAsync();
var response = await client.SynthesizeSpeechAsync(
new SynthesisInput { Text = "नमस्ते, यह हिंदी में एक परीक्षण है।" },
new VoiceSelectionParams
{
LanguageCode = "hi-IN",
Name = "hi-IN-Chirp3-HD-Charon",
},
new AudioConfig { AudioEncoding = AudioEncoding.Mp3 });
await using var output = File.Create("hindi.mp3");
response.AudioContent.WriteTo(output);
Availability differs by language and changes without notice. One ListVoices call beats a constant that was true when someone wrote it.
var voices = await client.ListVoicesAsync(new ListVoicesRequest
{
LanguageCode = "hi-IN",
});
foreach (var voice in voices.Voices)
{
if (!voice.Name.Contains("Chirp3-HD", StringComparison.Ordinal))
{
continue;
}
Console.WriteLine($"{voice.Name} {voice.SsmlGender} {voice.NaturalSampleRateHertz}Hz");
}
The voice name is a locale prefix plus a character. Keeping the character fixed and changing only the prefix is how a multilingual product keeps one identity.
var greetings = new Dictionary<string, string>
{
["hi-IN"] = "नमस्ते, आपका स्वागत है।",
["en-IN"] = "Hello, and welcome.",
["bn-IN"] = "নমস্কার, স্বাগতম।",
["ta-IN"] = "வணக்கம், வரவேற்கிறோம்.",
};
foreach (var (locale, text) in greetings)
{
var spoken = await client.SynthesizeSpeechAsync(
new SynthesisInput { Text = text },
new VoiceSelectionParams
{
LanguageCode = locale,
Name = $"{locale}-Chirp3-HD-Charon",
},
new AudioConfig { AudioEncoding = AudioEncoding.Mp3 });
await using var file = File.Create($"greeting-{locale}.mp3");
spoken.AudioContent.WriteTo(file);
}
No API key. Google Cloud uses Application Default Credentials — either a service-account file, or `gcloud auth application-default login` on a laptop.
pip install google-cloud-texttospeech
# A service account, for a server:
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
# Or, on a developer machine:
gcloud auth application-default login
The locale goes in TWO places and they must agree: language_code on the voice, and the locale prefix of the name. A mismatch is accepted and produces an accent nobody asked for.
from google.cloud import texttospeech
client = texttospeech.TextToSpeechClient()
response = client.synthesize_speech(
input=texttospeech.SynthesisInput(
text="नमस्ते, यह हिंदी में एक परीक्षण है।"
),
voice=texttospeech.VoiceSelectionParams(
language_code="hi-IN",
name="hi-IN-Chirp3-HD-Charon",
),
audio_config=texttospeech.AudioConfig(
audio_encoding=texttospeech.AudioEncoding.MP3
),
)
with open("hindi.mp3", "wb") as handle:
handle.write(response.audio_content)
DO NOT HARDCODE A VOICE LIST. Availability changes per language and per region, and list_voices is the only answer that is true on the day you run it — the same reasoning as the Bedrock recipe's model discovery step.
voices = client.list_voices(language_code="hi-IN")
for voice in voices.voices:
# Chirp 3 HD voices are the ones with Chirp3-HD in the name; the
# rest are Standard, WaveNet, Neural2 or Studio, which have
# different capabilities and different pricing.
if "Chirp3-HD" in voice.name:
print(voice.name, voice.ssml_gender.name, voice.natural_sample_rate_hertz)
Charon is Charon in every locale that has it. Swapping the prefix moves language without changing how the voice sounds, which is what keeps a multilingual product from sounding like four different products.
GREETINGS = {
"hi-IN": "नमस्ते, आपका स्वागत है।",
"en-IN": "Hello, and welcome.",
"bn-IN": "নমস্কার, স্বাগতম।",
"ta-IN": "வணக்கம், வரவேற்கிறோம்.",
}
for locale, text in GREETINGS.items():
response = client.synthesize_speech(
input=texttospeech.SynthesisInput(text=text),
voice=texttospeech.VoiceSelectionParams(
language_code=locale,
name=f"{locale}-Chirp3-HD-Charon",
),
audio_config=texttospeech.AudioConfig(
audio_encoding=texttospeech.AudioEncoding.MP3
),
)
with open(f"greeting-{locale}.mp3", "wb") as handle:
handle.write(response.audio_content)
The BOM keeps the client and its gRPC transitive dependencies on versions that agree with each other — skipping it is the usual cause of a NoSuchMethodError at startup.
# Gradle
implementation(platform("com.google.cloud:libraries-bom:26.66.0"))
implementation("com.google.cloud:google-cloud-texttospeech")
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
The client is AutoCloseable and expensive to build — one per process, not one per request. ByteString gives you the bytes without another copy.
import com.google.cloud.texttospeech.v1.*;
import com.google.protobuf.ByteString;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class SpeakHindi {
public static void main(String[] args) throws Exception {
try (TextToSpeechClient client = TextToSpeechClient.create()) {
SynthesisInput input = SynthesisInput.newBuilder()
.setText("नमस्ते, यह हिंदी में एक परीक्षण है।")
.build();
VoiceSelectionParams voice = VoiceSelectionParams.newBuilder()
.setLanguageCode("hi-IN")
.setName("hi-IN-Chirp3-HD-Charon")
.build();
AudioConfig audio = AudioConfig.newBuilder()
.setAudioEncoding(AudioEncoding.MP3)
.build();
SynthesizeSpeechResponse response =
client.synthesizeSpeech(input, voice, audio);
ByteString content = response.getAudioContent();
try (OutputStream out = new FileOutputStream("hindi.mp3")) {
content.writeTo(out);
}
}
}
}
Which Chirp 3 HD voices exist for a given Indic locale changes. Ask, rather than shipping a constant that was accurate once.
try (TextToSpeechClient client = TextToSpeechClient.create()) {
ListVoicesResponse voices = client.listVoices("hi-IN");
for (Voice voice : voices.getVoicesList()) {
if (!voice.getName().contains("Chirp3-HD")) {
continue;
}
System.out.printf("%s %s %dHz%n",
voice.getName(),
voice.getSsmlGender(),
voice.getNaturalSampleRateHertz());
}
}
Same character, four languages. This is the whole trick to sounding like one product in a country with twenty-two official languages.
import java.util.Map;
Map<String, String> greetings = Map.of(
"hi-IN", "नमस्ते, आपका स्वागत है।",
"en-IN", "Hello, and welcome.",
"bn-IN", "নমস্কার, স্বাগতম।",
"ta-IN", "வணக்கம், வரவேற்கிறோம்.");
try (TextToSpeechClient client = TextToSpeechClient.create()) {
for (Map.Entry<String, String> entry : greetings.entrySet()) {
String locale = entry.getKey();
SynthesizeSpeechResponse response = client.synthesizeSpeech(
SynthesisInput.newBuilder().setText(entry.getValue()).build(),
VoiceSelectionParams.newBuilder()
.setLanguageCode(locale)
.setName(locale + "-Chirp3-HD-Charon")
.build(),
AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build());
try (OutputStream out = new FileOutputStream("greeting-" + locale + ".mp3")) {
response.getAudioContent().writeTo(out);
}
}
}
The npm package is scoped. Credentials come from the environment, so nothing about the key lives in code.
npm install @google-cloud/text-to-speech
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
synthesizeSpeech returns an array — the response is the first element. Destructuring it, as below, is the idiom in every Google Cloud client and it catches people out once.
import { writeFile } from "node:fs/promises";
import textToSpeech from "@google-cloud/text-to-speech";
const client = new textToSpeech.TextToSpeechClient();
const [response] = await client.synthesizeSpeech({
input: { text: "नमस्ते, यह हिंदी में एक परीक्षण है।" },
voice: {
languageCode: "hi-IN",
name: "hi-IN-Chirp3-HD-Charon",
},
audioConfig: { audioEncoding: "MP3" },
});
await writeFile("hindi.mp3", response.audioContent, "binary");
A hardcoded voice list goes stale the first time Google adds a language. listVoices is one call and it is correct by construction.
const [available] = await client.listVoices({ languageCode: "hi-IN" });
for (const voice of available.voices) {
if (!voice.name.includes("Chirp3-HD")) continue;
console.log(voice.name, voice.ssmlGender, voice.naturalSampleRateHertz);
}
speakingRate, pitch and SSML input are accepted and have NO EFFECT on a Chirp 3 HD voice. No error is raised. If you need them, that is a reason to pick a Neural2 or Studio voice instead.
// This runs, returns audio, and ignores both knobs.
const [ignored] = await client.synthesizeSpeech({
input: { text: "This is read at the default rate and pitch." },
voice: { languageCode: "hi-IN", name: "hi-IN-Chirp3-HD-Charon" },
audioConfig: {
audioEncoding: "MP3",
speakingRate: 1.4, // ignored by Chirp 3 HD
pitch: -4.0, // ignored by Chirp 3 HD
},
});
// A Neural2 voice honours both, at the cost of a less natural read.
const [controlled] = await client.synthesizeSpeech({
input: { text: "This one is genuinely faster." },
voice: { languageCode: "hi-IN", name: "hi-IN-Neural2-A" },
audioConfig: { audioEncoding: "MP3", speakingRate: 1.4 },
});
QUESTIONS
Which languages are the Google Cloud Speech examples in?
C#, Python, Java and JavaScript. Every sample runs as pasted and reads its credentials from an environment variable — no key is ever written into the code.
Which package do I install for Google Cloud Speech?
The samples use google-cloud-texttospeech. The install step on each language tab gives the exact command.
Which Google Cloud Speech model do these examples use?
hi-IN-Chirp3-HD-Charon, checked against the official documentation on 26 September 2026. Model ids change often; if a call returns a model-not-found error, check the current list in the official docs.
Where is the official Google Cloud Speech documentation?
https://cloud.google.com/text-to-speech/docs — it is linked at the bottom of this page, and it is the authority whenever it disagrees with a sample here.
ALSO IN SPEECH & AUDIO
The authority
Official Google Cloud Speech documentation
Model names, pricing and rate limits change faster than any page here can. When this page and the official docs disagree, the official docs are right.
https://cloud.google.com/text-to-speech/docs