Azure AI Speech Free code examples in C#, Python, Java and JavaScript
Microsoft's speech stack: TTS, STT, translation and custom voices.
WHAT THIS PAGE COVERS
SSML — the control the plain-text APIs do not give you.
en-US-Ava:DragonHDLatestNeural
Microsoft.CognitiveServices.Speech
Model ids change. If a sample returns a 404 on the model, that is the first thing to check against the official docs.
Azure wants two values, not one: the key and where to send it. Newer samples use a full endpoint URI; older ones use a region string, and both are still supported.
dotnet add package Microsoft.CognitiveServices.Speech
setx SPEECH_KEY "your-key"
setx ENDPOINT "https://YOUR-REGION.api.cognitive.microsoft.com/"
SpeechSynthesisVoiceName is where the voice goes — there is no model parameter. With no AudioConfig the audio plays on the default speaker, which is the fastest way to hear whether it works.
using Microsoft.CognitiveServices.Speech;
var speechKey = Environment.GetEnvironmentVariable("SPEECH_KEY")
?? throw new InvalidOperationException("SPEECH_KEY is not set.");
var endpoint = Environment.GetEnvironmentVariable("ENDPOINT")
?? throw new InvalidOperationException("ENDPOINT is not set.");
var config = SpeechConfig.FromEndpoint(new Uri(endpoint), speechKey);
config.SpeechSynthesisVoiceName = "en-US-Ava:DragonHDLatestNeural";
using var synthesizer = new SpeechSynthesizer(config);
var result = await synthesizer.SpeakTextAsync(
"The first move is what sets everything in motion.");
Console.WriteLine($"{result.Reason}, {result.AudioData.Length} bytes");
Three things worth the extra markup: a measured pause, a phoneme override for a name the model gets wrong, and per-word emphasis. The xmlns and the xml:lang are both required; omit either and the whole document is read aloud as literal text.
var ssml = @"
<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis'
xmlns:mstts='https://www.w3.org/2001/mstts' xml:lang='en-US'>
<voice name='en-US-Ava:DragonHDLatestNeural'>
Your order ships
<break time='300ms'/>
<emphasis level='strong'>today</emphasis>.
Contact
<phoneme alphabet='ipa' ph='ˈpʌŋkədʒ'>Pankaj</phoneme>
if anything is wrong.
</voice>
</speak>";
var result = await synthesizer.SpeakSsmlAsync(ssml);
SpeakTextAsync does NOT throw on failure — it returns a result whose Reason is Canceled. Checking only for an exception is how a silent, empty audio file reaches production.
using var output = AudioConfig.FromWavFileOutput("speech.wav");
using var fileSynth = new SpeechSynthesizer(config, output);
var result = await fileSynth.SpeakTextAsync("Written straight to disk.");
if (result.Reason == ResultReason.Canceled)
{
var details = SpeechSynthesisCancellationDetails.FromResult(result);
// ErrorCode 1 (AuthenticationFailure) is a bad key or the wrong
// region for that key — the two are indistinguishable from the
// message alone, so check both.
Console.Error.WriteLine($"{details.Reason}: {details.ErrorDetails}");
}
The PyPI name does not match the namespace: you install azure-cognitiveservices-speech and import azure.cognitiveservices.speech.
pip install azure-cognitiveservices-speech
export SPEECH_KEY="your-key"
export ENDPOINT="https://YOUR-REGION.api.cognitive.microsoft.com/"
speak_text_async() returns a future; .get() waits for it. Forgetting .get() gives you a program that exits before any audio is produced and reports no error at all.
import os
import azure.cognitiveservices.speech as speechsdk
speech_config = speechsdk.SpeechConfig(
subscription=os.environ["SPEECH_KEY"],
endpoint=os.environ["ENDPOINT"],
)
speech_config.speech_synthesis_voice_name = "en-US-Ava:DragonHDLatestNeural"
synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config)
result = synthesizer.speak_text_async(
"The first move is what sets everything in motion."
).get()
print(result.reason, len(result.audio_data), "bytes")
A break in milliseconds, an IPA override for a name, and emphasis on the word that carries the meaning. This is the whole reason to pick Azure over a plain-text TTS API.
ssml = """
<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis'
xml:lang='en-US'>
<voice name='en-US-Ava:DragonHDLatestNeural'>
Your order ships
<break time='300ms'/>
<emphasis level='strong'>today</emphasis>.
Contact
<phoneme alphabet='ipa' ph='ˈpʌŋkədʒ'>Pankaj</phoneme>
if anything is wrong.
</voice>
</speak>
"""
result = synthesizer.speak_ssml_async(ssml).get()
The SDK does not raise on failure. A canceled result with an empty audio buffer is what a wrong key looks like, and it is indistinguishable from success unless you check reason.
result = synthesizer.speak_text_async("Checking this properly.").get()
if result.reason == speechsdk.ResultReason.SynthesizingAudioCompleted:
with open("speech.wav", "wb") as handle:
handle.write(result.audio_data)
elif result.reason == speechsdk.ResultReason.Canceled:
details = result.cancellation_details
print("canceled:", details.reason)
# An authentication failure here usually means the key is valid
# but the endpoint belongs to a different region.
if details.reason == speechsdk.CancellationReason.Error:
print("error:", details.error_details)
The Maven artifact is client-sdk under com.microsoft.cognitiveservices.speech. It carries native binaries, so the platform classifier matters on a build agent that is not your laptop.
# Gradle
implementation("com.microsoft.cognitiveservices.speech:client-sdk:1.46.0")
export SPEECH_KEY="your-key"
export SPEECH_REGION="your-region"
SpeechSynthesizer is AutoCloseable and holds a native handle. Leaking it leaks unmanaged memory that the JVM heap will never show you.
import com.microsoft.cognitiveservices.speech.SpeechConfig;
import com.microsoft.cognitiveservices.speech.SpeechSynthesizer;
import com.microsoft.cognitiveservices.speech.SpeechSynthesisResult;
public class Speak {
public static void main(String[] args) throws Exception {
String key = System.getenv("SPEECH_KEY");
String region = System.getenv("SPEECH_REGION");
if (key == null || region == null) {
throw new IllegalStateException("SPEECH_KEY and SPEECH_REGION must be set.");
}
SpeechConfig config = SpeechConfig.fromSubscription(key, region);
config.setSpeechSynthesisVoiceName("en-US-Ava:DragonHDLatestNeural");
try (SpeechSynthesizer synthesizer = new SpeechSynthesizer(config);
SpeechSynthesisResult result = synthesizer
.SpeakTextAsync("The first move is what sets everything in motion.")
.get()) {
System.out.println(result.getReason() + " "
+ result.getAudioData().length + " bytes");
}
}
}
SpeakSsmlAsync takes the document as a string. The xmlns is not decoration: without it Azure reads the tags aloud rather than acting on them.
String ssml = """
<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis'
xml:lang='en-US'>
<voice name='en-US-Ava:DragonHDLatestNeural'>
Your order ships
<break time='300ms'/>
<emphasis level='strong'>today</emphasis>.
</voice>
</speak>
""";
try (SpeechSynthesizer synthesizer = new SpeechSynthesizer(config);
SpeechSynthesisResult result = synthesizer.SpeakSsmlAsync(ssml).get()) {
System.out.println(result.getReason());
}
No exception is thrown for a bad key. The result comes back with reason Canceled and an empty audio buffer, so a program that only catches exceptions writes a zero-byte WAV and reports success.
import com.microsoft.cognitiveservices.speech.ResultReason;
import com.microsoft.cognitiveservices.speech.SpeechSynthesisCancellationDetails;
if (result.getReason() == ResultReason.Canceled) {
SpeechSynthesisCancellationDetails details =
SpeechSynthesisCancellationDetails.fromResult(result);
// An authentication failure is most often a valid key paired with
// the wrong region, which the message does not distinguish.
System.err.println(details.getReason() + ": " + details.getErrorDetails());
}
The npm package works in Node and in the browser, but only the Node path should ever hold a SPEECH_KEY — browser use needs a short-lived token minted server-side.
npm install microsoft-cognitiveservices-speech-sdk
export SPEECH_KEY="your-key"
export SPEECH_REGION="your-region"
The Node SDK is callback-based. Wrapping it in a Promise once, as below, is worth doing before it spreads through the codebase.
import sdk from "microsoft-cognitiveservices-speech-sdk";
const config = sdk.SpeechConfig.fromSubscription(
process.env.SPEECH_KEY,
process.env.SPEECH_REGION,
);
config.speechSynthesisVoiceName = "en-US-Ava:DragonHDLatestNeural";
function speak(text) {
const synthesizer = new sdk.SpeechSynthesizer(config);
return new Promise((resolve, reject) => {
synthesizer.speakTextAsync(
text,
(result) => { synthesizer.close(); resolve(result); },
(error) => { synthesizer.close(); reject(error); },
);
});
}
const result = await speak("The first move is what sets everything in motion.");
console.log(result.reason, result.audioData.byteLength, "bytes");
speakSsmlAsync takes the same callback shape. Note the voice moves into the markup: the voice name on the config is ignored once the SSML names one.
const ssml = `
<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis'
xml:lang='en-US'>
<voice name='en-US-Ava:DragonHDLatestNeural'>
Your order ships
<break time='300ms'/>
<emphasis level='strong'>today</emphasis>.
</voice>
</speak>`;
const synthesizer = new sdk.SpeechSynthesizer(config);
synthesizer.speakSsmlAsync(
ssml,
(result) => {
synthesizer.close();
console.log(result.reason);
},
(error) => {
synthesizer.close();
console.error(error);
},
);
SPEECH_KEY in front-end JavaScript is a published key. Mint a ten-minute token on the server and hand the browser that instead — the SDK has a constructor for exactly this.
// --- server ---------------------------------------------------------
app.get("/speech-token", async (_request, response) => {
const minted = await fetch(
`https://${process.env.SPEECH_REGION}.api.cognitive.microsoft.com` +
"/sts/v1.0/issueToken",
{
method: "POST",
headers: { "Ocp-Apim-Subscription-Key": process.env.SPEECH_KEY },
},
);
response.json({
token: await minted.text(),
region: process.env.SPEECH_REGION,
});
});
// --- browser --------------------------------------------------------
const { token, region } = await fetch("/speech-token").then((r) => r.json());
const browserConfig = sdk.SpeechConfig.fromAuthorizationToken(token, region);
browserConfig.speechSynthesisVoiceName = "en-US-Ava:DragonHDLatestNeural";
QUESTIONS
Which languages are the Azure AI 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 Azure AI Speech?
The samples use Microsoft.CognitiveServices.Speech. The install step on each language tab gives the exact command.
Which Azure AI Speech model do these examples use?
en-US-Ava:DragonHDLatestNeural, 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 Azure AI Speech documentation?
https://learn.microsoft.com/azure/ai-services/speech-service/ — 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 Azure AI 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://learn.microsoft.com/azure/ai-services/speech-service/