Amazon Transcribe and Amazon Polly sit on opposite sides of the same problem. One turns spoken audio into text. The other turns text into spoken audio. Neither service calls the other, and neither depends on the other's SDK client - but together they form the two ends of almost every voice-driven application built on AWS.
This page is the map before the detail pages: what each service actually does, how their request shapes differ, and where they fit together in a real pipeline.
Transcribe (speech-to-text): submit audio, get back text. Its primary API is an asynchronous batch job; a separate streaming API handles live audio.
Polly (text-to-speech): submit text, get back audio. Its primary API is a synchronous request-response call.
Insight: the two services are not mirror images of each other's plumbing - Transcribe's batch path is a job you poll, Polly's is a direct call that returns audio immediately.
When to Use: Transcribe for voicemail, meeting recordings, call-center audio, or live captioning; Polly for IVR prompts, accessibility narration, or any generated voice response.
Limitations/Trade-offs: Transcribe's batch job has processing latency measured in minutes, not milliseconds; Polly's neural voices cost more per character than standard voices and are not available in every AWS region.
Related Topics: batch vs streaming transcription, speaker diarization, custom vocabulary, medical and call-analytics variants, Polly voices and SSML.
Amazon Transcribe is Amazon's automatic speech recognition (ASR) service. You give it audio - a file in S3, or a live audio stream - and it gives you back text, word by word, with timestamps and confidence scores. The boto3 client is transcribe (@aws-sdk/client-transcribe in TypeScript); the streaming path uses a separate package, @aws-sdk/client-transcribe-streaming.
Amazon Polly is the mirror service for text-to-speech (TTS). You give it a string of text or SSML markup, tell it which voice and audio format you want, and it returns synthesized audio. The client is polly in boto3 and @aws-sdk/client-polly in TypeScript.
Neither service is aware of the other. There is no combined "speech-to-speech" API - if you want to transcribe a call, summarize it, and read the summary back, you call Transcribe, do your own processing on the text, then call Polly. The services are complementary by convention, not by any shared plumbing.
The clearest way to see the difference is to compare the shape of one call from each service.
Transcribe's batch job API takes a reference to audio already in S3 and returns immediately with a job that is still running:
# --- Python (boto3) ---import boto3transcribe = boto3.client("transcribe")transcribe.start_transcription_job( TranscriptionJobName="call-2026-07-24", Media={"MediaFileUri": "s3://my-bucket/calls/call.wav"}, MediaFormat="wav", LanguageCode="en-US", OutputBucketName="my-bucket",)# Returns immediately - the job runs in the background.
// --- TypeScript (AWS SDK v3) ---import { TranscribeClient, StartTranscriptionJobCommand } from "@aws-sdk/client-transcribe";const transcribe = new TranscribeClient({});await transcribe.send(new StartTranscriptionJobCommand({ TranscriptionJobName: "call-2026-07-24", Media: { MediaFileUri: "s3://my-bucket/calls/call.wav" }, MediaFormat: "wav", LanguageCode: "en-US", OutputBucketName: "my-bucket",}));// Returns immediately - the job runs in the background.
You then poll GetTranscriptionJob until TranscriptionJobStatus reaches COMPLETED, at which point the transcript is a JSON document sitting in the S3 bucket you named.
Polly's call looks entirely different in shape, because it is synchronous - the audio comes back in the response body itself:
No job, no polling, no S3 output bucket required - the audio stream is available the moment the call returns.
Transcribe has a second, entirely separate API for cases where a file in S3 is the wrong shape for the problem: live audio. StartStreamTranscriptionCommand (from @aws-sdk/client-transcribe-streaming, or the equivalent bidirectional stream in boto3) accepts a generator of audio chunks and yields transcript results back in near real time. This is a different connection model - a persistent bidirectional stream, not a request/response call - and it is covered in depth on the next page in this section.
The most common real pipeline chains both services around your own application logic in the middle:
Audio arrives (a voicemail, a call recording, a user's spoken query).
Transcribe turns it into text - via a batch job for recorded audio, or streaming for live audio.
Your application processes the text - routing, summarization, a call to an LLM, a database lookup.
Polly turns the resulting text back into audio for playback.
Neither service needs to know the other exists; your code is the glue. This also means the two halves scale and fail independently - a Polly outage does not affect your ability to transcribe, and vice versa.
Cost and latency profiles differ meaningfully between the two. Transcribe's batch jobs are billed per second of audio processed and typically complete in a fraction of the audio's own duration, but that is still minutes for a long recording - not something to use in a hard real-time loop. Polly's synchronous call is fast enough for interactive use, but a neural or long-form voice costs more per character than a standard voice, and not every voice is available with every engine in every region.
Choosing between Transcribe's batch and streaming APIs, and between Polly's standard, neural, and long-form engines, both come down to the same question: is the audio already recorded (favor batch, favor whichever engine fits the budget), or does it need to happen live (favor streaming, favor low-latency voice settings)?
"Transcribe and Polly are two operations on one API." - No, they are entirely separate services with separate clients (transcribe and polly in boto3; @aws-sdk/client-transcribe and @aws-sdk/client-polly in TypeScript) and no shared request shapes.
"StartTranscriptionJob returns the transcript." - No, it returns a job reference. The transcript is written to S3 once the job completes, and you retrieve it with GetTranscriptionJob plus a fetch of the output file.
"Streaming transcription is just polling faster." - No, it is a different API built on a persistent bidirectional stream, not the same job-based model with a shorter poll interval.
"SynthesizeSpeech needs an S3 bucket like Transcribe does." - No, Polly's core call streams audio bytes back directly in the response; no S3 output is involved unless you separately choose to save it there.
"One service can call the other automatically." - No, chaining them (transcribe, process, synthesize) is application logic you write, not a built-in AWS feature.
Do Transcribe and Polly share a client or SDK package?
No. Transcribe uses the transcribe boto3 client or @aws-sdk/client-transcribe; streaming transcription uses a further separate package, @aws-sdk/client-transcribe-streaming. Polly uses polly or @aws-sdk/client-polly. All three are independent packages.
Is StartTranscriptionJob synchronous?
No. It starts a background job and returns immediately. You poll GetTranscriptionJob and check TranscriptionJobStatus until it reaches COMPLETED or FAILED, then read the transcript from the S3 location in the response.
Is SynthesizeSpeech synchronous?
Yes. The audio stream comes back in the same response as the request - there is no job, no status to poll, and no required S3 output.
When would I use streaming transcription instead of a batch job?
When the audio is live - a phone call in progress, a live captioning feed - rather than a file that already exists. Streaming uses a different, persistent-connection API rather than the file-based job API.
Can Polly speak text it receives directly from a Transcribe transcript?
Yes, once your application reads the transcript text out of the completed job's S3 output, you can pass that text (or a summary of it) straight into SynthesizeSpeech - there is no format conversion needed, since Transcribe's transcript is plain text plus metadata.
Do both services support the same set of languages?
Not necessarily the same list. Each service publishes its own supported-language table, and coverage for a given language can differ between transcription and synthesis - check both service's documentation for the specific language you need.