SaveMyCert
Log in
5 of 5 free questions left today·for 30 a day
Implement text analysis solutions

AI-103: Speech Solutions — Voice Agents, Custom Speech and Speech Translation

20 min readAI-103 · Implement text analysis solutionsUpdated

Implementing speech solutions for AI-103 means giving apps and agents ears and a voice: converting speech to text and text to speech with Azure Speech in Foundry Tools, running spoken agent conversations through the Voice Live API, improving recognition with phrase lists and custom speech models, letting audio-capable models reason over audio directly, and translating speech with the Speech SDK or language models. The skill is choosing the right path for each requirement — live or recorded audio, recognition or output, a trained model or a runtime fix — and configuring it correctly.

What you’ll learn
  • Choose between real-time recognition, fast transcription, batch transcription and LLM Speech by latency, volume, output form and custom-model hosting.
  • Synthesize agent replies with the Speech SDK, control pace and pauses with SSML, pick telephony output formats, and fix pronunciation with SSML elements or a custom lexicon.
  • Use the Voice Live API as an agent's speech modality, including connecting it to a Foundry Agent Service agent with Microsoft Entra ID.
  • Decide between a phrase list and a custom speech model, pick training data by error type, test with WER, and call the model from the SDK, batch jobs and Voice Live.
  • Select professional custom voice, personal voice or a prebuilt voice for an agent's output.
  • Send audio to audio-capable models for multimodal reasoning and connect to the GPT Realtime API with the right transport and credential pattern.
  • Translate speech with the Speech SDK, Live Interpreter, LLM Speech or a transcribe-then-translate pipeline.

Which speech-to-text path fits a workload?

Azure Speech in Foundry Tools offers four speech-to-text paths, and the right one follows from where the audio is and how fast the text is needed: real-time recognition with the Speech SDK for live audio, the fast transcription API for one file at a time with a synchronous answer, batch transcription for large sets of stored files, and LLM Speech (the enhanced mode of fast transcription) when a language model should shape the output.

PathHow it worksFitsWatch for
Real-time (Speech SDK SpeechRecognizer)Streams audio from a microphone, stream or file; recognize_once_async returns the first utterance (it stops at the first pause), continuous recognition keeps going until stoppedLive conversations, captions, voice commands, agentsA custom model needs a deployed custom endpoint (endpoint_id)
Fast transcription (REST)One multipart request per file, synchronous, faster than real time"Transcribe this recording now" with no streaming clientReturns display-form text only; per-file size and length limits; base models only (no custom speech model), though a phrase list is supported
Batch transcription (REST)Asynchronous job over a list of file URLs or a whole storage container; you poll and collect results laterThousands of recordings, nightly or overnight jobsNo synchronous answer; results include the lexical form; can reference a custom model without a hosted endpoint
LLM Speech (fast transcription enhanced mode)Same synchronous request, with enhancedMode settings that add a task (transcribe or translate) and a promptTranslation into a chosen language, prompted output styleCan't apply your trained custom speech model

Two output forms matter. The display form has punctuation, capitalization and formatted numbers ("$25.50"); the lexical form is the raw recognized words ("twenty five dollars fifty"). Downstream tools that need lexical text rule out fast transcription. Cost and hosting also decide: a custom speech model must be deployed to a paid custom endpoint for real-time recognition and speech translation, while batch transcription references the model directly. Fast transcription and LLM Speech have no custom-model option at all: they run on base models, optionally helped by a phrase list. Batch transcription's language identification works only with base models; to pair language detection with a custom model, use real-time recognition (see the custom speech section).

For agents, real-time is the usual path for the conversation itself, while fast or batch transcription handles recordings the agent must analyse afterwards.

How do you turn an agent's text replies into speech?

Text to speech in the Speech SDK is a SpeechSynthesizer built from a SpeechConfig: you pick the voice with speech_synthesis_voice_name (for example en-US-AvaMultilingualNeural), then call speak_text_async for plain text or speak_ssml_async for SSML markup. Each config property has one job, and the near-twins are easy to mix up:

PropertyWhat it does
speech_synthesis_voice_nameSelects a specific voice for synthesis
speech_synthesis_languageTakes a locale only and falls back to that locale's default voice
speech_recognition_languageSets the locale for speech to text, not output
endpoint_idPoints at a custom deployment (a custom speech model, or a custom voice)

SSML controls delivery. Wrap text in a prosody element with a rate (and pitch or volume) to change pace, insert a break with a time such as 500ms for a pause at an exact point, and use mstts:express-as to apply a speaking style (cheerful, calm and so on) where the voice supports it. A style changes tone, not timing. SSML only works through speak_ssml_async; sending markup to speak_text_async makes the voice read the tags as text.

Output format must match the destination. set_speech_synthesis_output_format chooses the encoding. Riff* formats are WAV files with a header; Raw* formats have no header, which streaming and telephony gateways often require. Narrowband telephony runs at 8 kHz with G.711 companding, which comes in two variants: mu-law (North America and Japan, Raw8Khz8BitMonoMULaw) and A-law (Europe and most other regions, Raw8Khz8BitMonoALaw). Lowering the sample rate changes audio quality, not speaking speed.

Voices come as standard neural voices, higher-fidelity HD voices, and multilingual voices that can speak several languages; all are prebuilt and shared by every customer, so none of them is a unique brand voice.

How do you control how an agent pronounces names and acronyms?

Pronunciation of output speech is fixed on the text-to-speech side, with SSML elements for one-off cases and a custom lexicon for rules that should apply everywhere. Recognition-side tools (phrase lists, custom speech pronunciation data) only change what the service hears, so they never fix a voice that mispronounces a word.

ToolEffectScope
<sub alias="World Wide Web Consortium">W3C</sub>Speaks the alias instead of the written textThat one place in one SSML document
<say-as interpret-as="…">Tells the voice how to read the content (date, characters, number, name)One place; still reads the written text itself
<phoneme alphabet="ipa" ph="…">Gives an exact phonetic pronunciationOne place
Custom lexicon (PLS file)Maps graphemes to a phoneme or to an aliasEvery occurrence in every reply that uses the lexicon

A lexicon is an XML Pronunciation Lexicon Specification file, not SSML. Each lexeme holds one or more grapheme entries and either a phoneme (in an alphabet such as IPA) or an alias. An alias suits acronyms: a lexeme for SLA with the alias "service level agreement" makes every SLA spoken as the phrase. Matching is case-sensitive, so a lexeme for "Contoso" doesn't cover "CONTOSO"; add a grapheme or lexeme for each casing that appears. A lexicon covers one locale, is hosted at a URL (for example Azure Blob Storage) and is cached by the service, so edits take a short while to appear.

You reference the lexicon from SSML with a lexicon element. In the Voice Live API, the voice configuration accepts custom_lexicon_url, which applies the lexicon to every reply for standard and custom voices without editing prompts or SSML.

How does the Voice Live API make speech an agent modality?

The Voice Live API is a managed speech-to-speech interface: in one WebSocket session it combines speech recognition, a generative model and text to speech, so an agent can hold a spoken conversation without you orchestrating three services. It adds the conversational audio features a hand-built chain lacks:

  • Noise suppression for busy environments and echo cancellation so the agent doesn't hear (and answer) its own voice on a speakerphone.
  • Interruption detection and advanced end-of-turn detection, so the agent doesn't cut in when a caller pauses mid-sentence.
  • Avatars for a talking visual front end, plus the choice of standard, HD, custom and personal voices.
  • Natively supported models that are fully managed (nothing to deploy), or your own model deployment.

You configure the session with a session.update event: instructions, the voice object, input_audio_transcription (the recognition model, such as azure-speech or an OpenAI transcription model like gpt-4o-transcribe or whisper-1, plus phrase_list and custom_speech), and turn-detection, noise and echo settings.

Agent mode connects Voice Live to an existing Foundry Agent Service agent instead of a bare model. The connection names the agent (agent_name) and its Foundry project (project_name), optionally a version or a conversation to resume, and the agent brings its own instructions, model and tools, so nothing is copied into the session. Agent invocation requires Microsoft Entra ID authentication; API keys aren't supported for it.

OptionWhat you buildChoose it when
Voice Live APIOne managed session: STT + model + TTS with noise, echo, turn detection, avatarsLeast engineering effort for a voice agent, including a Foundry agent
GPT Realtime APIA direct low-latency audio session with a gpt-realtime deployment you createYou want the speech-native model itself and manage the rest
Speech SDK chainYour own code linking recognition, a model and synthesisYou need full control and accept building echo and turn handling yourself

Phrase list or custom speech model?

A phrase list is the fast, no-training fix for a modest set of misrecognized words; a custom speech model is the trained fix for large vocabularies, acoustic conditions, or workloads where phrase lists don't apply.

Phrase listCustom speech model
SetupSupplied at run time: in the SDK, PhraseListGrammar.from_recognizer(recognizer) then addPhrase; in Voice Live, phrase_list under input_audio_transcriptionUpload data, train, test, then deploy (or reference from batch)
Time to valueImmediate, same dayHours to days, plus data collection
SizeBest for a small to moderate list; at a couple of thousand phrases, move to custom speechThousands of terms, whole domains
FixesVocabulary only (biases recognition toward listed words)Vocabulary, pronunciation, accents and noise (with audio data), display formatting
Where it worksReal-time, fast transcription, LLM Speech, and Voice Live with azure-speechReal-time recognition and speech translation (via custom endpoint), batch (directly), Voice Live (custom_speech)
Where it doesn'tBatch transcription; Voice Live with whisper-1 or the gpt-4o-transcribe familyFast transcription and LLM Speech (base models only); OpenAI transcription models

The "where it doesn't" row explains a common symptom: a phrase list that changes nothing. In a batch job, tuning the list can't help; the answer is a custom model trained on text that uses the terms. In Voice Live, switching input_audio_transcription to azure-speech lets the phrase list take effect. Putting names in an agent's system prompt doesn't help either, because the model sees the words only after they've already been transcribed.

How do you train, test and use a custom speech model?

A custom speech model is a base model adapted with your data; you choose the data type by the kind of error, measure it with word error rate (WER), and then make the app actually call it.

Choosing training data

Error you seeData to use
Domain words missed, audio is clean (drug names, product names)Plain text sentences that use the terms in context (or structured text for patterned utterances)
Ordinary words missed because of noise, accents or channelAudio recorded in those conditions with human-labeled transcripts
Words with unusual pronunciations recognized wronglyPronunciation data (spoken form for a written term)
Display text formatted the wrong way (a product name shown as "contoso cloud" instead of "ContosoCloud")Custom display text formatting rules

Text data is cheap to collect and targets vocabulary; audio data is the only way to improve acoustic robustness. Pronunciation data here affects recognition, not how a voice speaks.

Testing with WER

WER compares what a model recognizes from audio with a human-labeled transcript of the same audio, so an accuracy test needs audio paired with human-labeled transcripts. Audio alone supports only listening to results, and text data can't score anything. Measure the base model first; if its WER is acceptable, you may not need a custom model at all, and the same test set compares later models.

Using the model

  • Real-time recognition and speech translation (Speech SDK): deploy the model to a custom endpoint, then set endpoint_id on the SpeechConfig (or SpeechTranslationConfig) to that endpoint's ID. Without endpoint_id, the service uses the base model for the locale, however good the trained model is.
  • Fast transcription and LLM Speech: there is no custom-model or custom-endpoint option; they use base models, and a phrase list is the runtime fix for vocabulary.
  • Batch transcription: reference the model in the job; no endpoint is needed.
  • Language detection with a custom model: build AutoDetectSourceLanguageConfig from SourceLanguageConfig objects, each with a locale and optionally a custom endpoint ID. The custom model then applies only when its language is detected, and one recognizer handles the call. A global endpoint_id would force the custom model on every caller.
  • Voice Live: set custom_speech under input_audio_transcription to a dictionary keyed by locale (for example zh-CN) whose values are custom model IDs; other locales stay on the base model. It works only with the azure-speech transcription model, and the model must be available on the same Foundry resource that calls Voice Live, so a model trained on another resource has to be copied over first.

Which voice gives an agent a brand or personal voice?

A unique brand voice comes from professional custom voice; a voice that copies an individual end user comes from personal voice; everything else is a prebuilt standard or HD voice.

Professional custom voicePersonal voicePrebuilt (standard / HD)
PurposeOne unique brand or character voiceReplicate a specific user's own voiceGeneral-purpose voices shared by all customers
DataStudio-quality recordings from a voice talentA short speech sample plus the speaker's recorded consent statementNone
AccessLimited access, application requiredLimited access, approved use cases onlyOpen
Voice Live voice typeazure-custom with name and the deployment's endpoint_idazure-personal with name and a base modelazure-standard with name

Personal voice fits scenarios such as voice banking for patients who will lose their speech, or speaking translated output in each speaker's own voice. A custom speech model is not a voice at all: it improves recognition. In Voice Live, the custom voice deployment must be on the resource the session calls, and only the voice type, name and (for a custom voice) endpoint_id decide which voice speaks; other voice settings change how that voice speaks, not who it is.

How do models reason over audio directly, and how do you connect to them?

Multimodal reasoning from audio means sending the audio itself to an audio-capable model rather than a transcript, so the model can use tone, emotion and non-speech sounds (sirens, alarms, laughter) that any text conversion throws away. Sentiment on a transcript, diarization or a transcription prompt still work on words only.

Audio in chat completions

Audio-capable chat models such as gpt-4o-audio-preview and gpt-4o-mini-audio-preview accept an audio content part next to text in a user message:

{"type": "input_audio",
 "input_audio": {"data": b64_audio, "format": "wav"}}

The data is base64-encoded audio, not a file path or URL, and it is not an image_url part or base64 pasted into text. modalities=["text"] asks for a text reply; for a spoken reply as well, set modalities=["text", "audio"] and pass audio={"voice": "alloy", "format": "wav"}. This is request/response: good for analysing a recording, not for a live conversation.

The GPT Realtime API

For live, low-latency speech with a speech-native model, the GPT Realtime API streams audio both ways with a gpt-realtime deployment. The transport follows from the client:

TransportUse it for
WebRTCBrowser and mobile clients; lowest latency for audio
WebSocketsServer-to-server streaming (higher latency for client audio)
SIPTelephony

A browser must never hold a long-lived key or Entra ID token. The standard WebRTC pattern: your backend, using its own key or Entra ID credential, mints a short-lived ephemeral token from /openai/v1/realtime/client_secrets; the browser uses it to post its SDP offer to /openai/v1/realtime/calls. For stricter rules, the backend can also proxy the SDP negotiation, so no credential of any kind reaches the browser. The negotiation returns a Location header for the call, which the backend can use to open an observer WebSocket to record or control the session's events.

How do you translate speech with the Speech SDK and Live Interpreter?

Speech translation in the Speech SDK recognizes speech in one language and returns text (and optionally audio) in one or more others, using a SpeechTranslationConfig and a TranslationRecognizer.

  • The source is a language-locale string: speech_recognition_language = "ja-JP".
  • Each target is a language code: add_target_language("en"), add_target_language("es"). One recognition pass then fills result.translations, keyed by those codes.
  • Spoken output through voice_name and the synthesizing event works only for a single target language, and the voice should match that language.

To speak several languages from one recognition pass, add every target, then send each text translation to a SpeechSynthesizer with a voice in that language. Running one recognizer per language recognizes the same audio repeatedly.

Live Interpreter, part of real-time speech translation, handles conversations where nobody can choose the language in advance: it continuously identifies the spoken language with open-range detection (no candidate list; in Python an empty AutoDetectSourceLanguageConfig), follows speakers who switch language mid-session without restarting, and can speak the translation in the speaker's own personal voice (limited access). Standard translation with continuous language identification still needs candidate locales chosen up front.

How do language models translate speech?

Language models translate speech in three ways, and the choice depends on the target language and whether text must be reviewed in between.

ApproachOutputFitsLimits
LLM Speech (fast transcription with enhancedMode: task translate, a targetLanguage such as ko or de, optional prompt)Translated text from one synchronous call per fileAudio straight to a chosen language, with a prompt steering style such as brand-name renderingAudio in, text out in one step; prompts unrelated to speech output are disregarded
OpenAI transcription models (whisper's audio translations operation)English textAny supported language into EnglishTranslates only into English, whatever the prompt asks; per-file size cap
Transcribe, then translate with a GPT modelText in any language, from approved source textA review step before translation, glossaries, re-translating without reprocessing audioTwo steps; you manage prompts and glossary

The two-step pattern wins whenever the source transcript is a durable artifact: compliance can approve it, and when a glossary changes you re-run only the text translation. Direct audio-to-text translation (LLM Speech, the Speech SDK translation recognizer, whisper) reprocesses the audio every time and leaves no approved transcript in between.

Text analysis of the resulting transcript (entities, summaries, sentiment, structured output) belongs to the language-model text analysis topic of this domain.

Tip. Expect short scenarios — a contact center, a kiosk, a dictation app or a voice agent — with one deciding requirement such as least engineering effort, no training data, no hosted endpoint, one synchronous call, recognize the audio only once, no credential in the browser, or output in the speaker's own voice, followed by "what should you use or configure?". Many items hinge on whether a problem sits on the recognition side or the output side, and on which feature works on which path (phrase lists, custom models, language detection). Short Python snippets ask which SpeechConfig property, SSML element, content part or call arguments complete the code, and several items ask you to select TWO actions that must both be done.

Key takeaways
  • Live audio → real-time Speech SDK; one file, synchronous → fast transcription (display form only); many stored files → batch transcription (lexical form available, custom model without an endpoint).
  • Select a voice with speech_synthesis_voice_name; SSML (prosody rate, break time, styles) needs speak_ssml_async; Raw formats have no header, and 8 kHz mu-law is North American/Japanese telephony while A-law is European.
  • Output pronunciation is fixed on the TTS side: sub for a one-off spoken alias, a case-sensitive PLS custom lexicon (phoneme or alias) for every reply, custom_lexicon_url in Voice Live.
  • Voice Live is the managed speech-to-speech layer: noise suppression, echo cancellation, end-of-turn detection, avatars; agent mode takes agent_name + project_name and requires Entra ID.
  • Phrase lists are runtime, no-training boosts for modest lists; they don't work in batch transcription or with whisper/gpt-4o-transcribe in Voice Live — use custom speech or azure-speech instead.
  • Custom speech data follows the error: text for vocabulary, audio + human-labeled transcripts for noise and accents (and for WER testing), plus pronunciation and display formatting rules.
  • A custom speech model needs a custom endpoint and endpoint_id for real-time recognition and speech translation, batch references it directly, and fast transcription/LLM Speech take none; per-language custom models go in SourceLanguageConfig; Voice Live custom_speech maps locale to model ID, azure-speech only, same Foundry resource.
  • Professional custom voice = one brand voice from studio data (azure-custom + endpoint_id); personal voice = a user's own voice from a short sample with consent (azure-personal).
  • Audio reasoning needs the audio itself (input_audio parts to gpt-4o-audio-preview); Realtime API uses WebRTC for clients with a backend-minted ephemeral token, WebSockets server to server.
  • Speech SDK translation: locale source, language-code targets, event synthesis for one target only; Live Interpreter adds open-range detection and personal voice; whisper translates only into English.

Frequently asked questions

When should I use fast transcription instead of batch transcription?

Use fast transcription when you need the transcript of an individual file back in a single synchronous REST call within seconds, and display-form text is enough. Use batch transcription when you have large numbers of stored recordings that can be processed asynchronously as one job, when you need the lexical form of the transcript, or when you want to use a custom speech model without paying for a hosted custom endpoint.

Why doesn't my phrase list improve recognition?

Phrase lists apply only to some recognition paths. They work with real-time recognition, fast transcription, LLM Speech and the Voice Live API when the transcription model is azure-speech. They aren't available in batch transcription and have no effect in Voice Live with whisper-1 or the gpt-4o-transcribe models. For batch workloads, train a custom speech model on text that uses the terms; in Voice Live, switch input_audio_transcription to azure-speech.

How do I make a Speech SDK app use my custom speech model?

Deploy the trained model to a custom endpoint, then set endpoint_id on the SpeechConfig to that endpoint's ID. Without endpoint_id the service uses the base model for the configured locale. Batch transcription is the exception: a batch job can reference the custom model directly without a deployed endpoint. Fast transcription and LLM Speech can't use a custom speech model; they run on base models, with a phrase list as the runtime vocabulary fix.

How do I connect a Foundry Agent Service agent to the Voice Live API?

Open the Voice Live connection in agent mode with the agent's name and the name of its Foundry project, optionally a version or an existing conversation, and authenticate with a Microsoft Entra ID token credential. The agent supplies its own instructions, model and tools, so nothing needs copying into the session. Key-based authentication isn't supported for agent invocation.

What is the difference between a custom lexicon and custom speech pronunciation data?

A custom lexicon is a text-to-speech feature: a PLS file that tells a voice how to pronounce graphemes, using a phoneme or an alias, and it matches words case-sensitively. Custom speech pronunciation data is a speech-to-text feature that helps the recognizer understand terms with unusual pronunciations. If an agent mispronounces a name in its replies, fix it with a lexicon or SSML, not with recognition-side data.

Which voice option should I use for a unique brand voice?

Professional custom voice, trained on studio-quality recordings from a voice talent, creates a unique brand or character voice; it is a limited-access feature that requires an application. Personal voice instead replicates an individual user's own voice from a short sample with a recorded consent statement. Prebuilt standard and HD voices are shared by every customer, so they aren't unique.

How can a model hear tone and background sounds in a call recording?

Send the recording itself to an audio-capable model such as gpt-4o-audio-preview, as an input_audio content part with base64 data and a format, alongside the question. Converting the call to text first loses tone, emotion and non-speech sounds such as sirens, so transcript-based sentiment or diarization can't recover them.

Can whisper translate speech into languages other than English?

No. The audio translations operation of whisper translates speech from supported languages into English text only, and a prompt asking for another language doesn't change that. For another target language, use LLM Speech's translate task with a targetLanguage, Speech SDK speech translation, or transcribe the audio and translate the text with a GPT model.

Source

This lesson covers the "Implement text analysis solutions" domain of the official AI-103 exam guide. Vendors revise their guides — check the source for the current version.

Test yourself on this topic
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.

Spotted a mistake in this lesson?