Speech-to-text sounds like one of those features that should be extremely simple.
You have an audio file. You want text.
Done.
Except, of course, real audio is a little gremlin.
People mumble. Microphones hiss. Someone records a meeting from the other side of the room. Two people talk over each other. A podcast has music in the intro. A customer call has background noise. A video file hides the audio inside a format your script does not like. Someone says “LLMAPI,” and the model confidently writes “Elon API.” Lovely.
So yes, converting speech to text with Python is very doable.
But the best method depends on what you need:
- A quick local transcription.
- A production API.
- Real-time streaming.
- Speaker labels.
- Timestamps.
- Multilingual transcription.
- Offline/private transcription.
- Post-processing with an LLM.
In this guide, we’ll build a practical speech-to-text workflow with Python, starting from a simple local script and moving toward production-ready transcription.
What is speech-to-text?
Speech-to-text, also called automatic speech recognition or ASR, converts spoken audio into written text.
Input:
meeting_recording.mp3
Output:
Today we discussed the product roadmap, customer onboarding issues, and the next API release.
A good speech-to-text system can also return extra data:
| Feature | What it means |
| Timestamps | When each word or segment was spoken |
| Speaker labels | Who said what |
| Confidence scores | How sure the model is |
| Language detection | What language is spoken |
| Punctuation | Cleaner readable transcript |
| Paragraphs | More human-friendly formatting |
| Word-level timing | Useful for subtitles and clips |
| Streaming | Live transcription while audio is still happening |
| Custom vocabulary | Better recognition of product names and technical terms |
For a tiny script, you may only need plain text.
For a real product, you usually need timestamps, metadata, storage, retry logic, cleanup, and review.
Why we can write this guide
We’ve spent around 6 years working with AI APIs, speech-to-text tools, NLP pipelines, LLM workflows, automation, and developer tutorials. We also checked current docs for OpenAI, AssemblyAI, Deepgram, Google Cloud Speech-to-Text, and Azure Speech.
The practical lesson is simple: transcription quality depends on the audio and the workflow.
A clean studio recording is easy. A noisy real-world call with accents, interruptions, and technical terms is much harder. A 2025 paper on using custom language models with the open-source Vosk toolkit found that custom models reduced word error rates in domain-specific scenarios with technical terminology, varied accents, and background noise. That is a useful reminder: if your audio has niche terms, do not judge speech-to-text quality from one clean demo file.
Which Python speech-to-text method should you use?
Here is the quick version.
| Need | Best starting point |
| Quick local transcription | Whisper / faster-whisper |
| Offline/private transcription | Whisper, faster-whisper, Vosk |
| Production file transcription | OpenAI, AssemblyAI, Deepgram, Google, Azure |
| Real-time transcription | Deepgram, AssemblyAI, Azure, Google, OpenAI Realtime |
| Speaker diarization | AssemblyAI, Deepgram, Google, Azure |
| Long meetings/podcasts | API with async jobs or chunked local pipeline |
| Subtitles | API or local model with timestamps |
| Technical/domain terms | Custom vocabulary/model features |
| Post-transcription summaries | Speech-to-text API + LLMAPI |
If you are experimenting, start with a local model.
If you are building a production app, test at least two hosted APIs.
Option 1: Convert speech to text locally with Whisper
Whisper-style transcription is a good first option because it can run locally.
That means:
- No API call.
- No per-minute API cost.
- More privacy control.
- Easy experiments.
- Good enough quality for many use cases.
Install:
pip install openai-whisper
You also need FFmpeg installed because audio/video files often need conversion before transcription.
On macOS:
brew install ffmpeg
On Ubuntu:
sudo apt update
sudo apt install ffmpeg
On Windows, install FFmpeg and add it to your PATH.
Now create transcribe_local.py:
import whisper
model = whisper.load_model("base")
result = model.transcribe("audio.mp3")
print(result["text"])
Run:
python transcribe_local.py
That is the simplest version.
Which Whisper model size should you use?
Whisper models usually follow a speed/quality tradeoff.
| Model size | Good for |
| tiny | Very fast tests, rough drafts |
| base | Simple local transcription |
| small | Better quality, still manageable |
| medium | Better accuracy, slower |
| large | Best quality, needs more compute |
Use a smaller model if you need speed.
Use a larger model if accuracy matters and your machine can handle it.
Save the transcript to a file
Let’s make the script useful.
import whisper
from pathlib import Path
audio_path = Path("audio.mp3")
output_path = Path("transcript.txt")
model = whisper.load_model("base")
result = model.transcribe(str(audio_path))
output_path.write_text(result["text"], encoding="utf-8")
print(f"Transcript saved to {output_path}")
Now your transcript is saved instead of only printed.
Option 2: Use faster-whisper for better local performance
If local Whisper is too slow, try faster-whisper.
It uses CTranslate2 under the hood and is often faster/more efficient for local transcription.
Install:
pip install faster-whisper
Basic script:
from faster_whisper import WhisperModel
model = WhisperModel("base", device="cpu", compute_type="int8")
segments, info = model.transcribe("audio.mp3")
print("Detected language:", info.language)
for segment in segments:
print(f"[{segment.start:.2f}s -> {segment.end:.2f}s] {segment.text}")
This gives you timestamped segments.
Example output:
Detected language: en
[0.00s -> 4.20s] Today we are testing speech to text with Python.
[4.20s -> 8.90s] The transcript includes timestamps for each segment.
That is useful for subtitles, video clips, podcast search, and meeting review.
Option 3: Use OpenAI speech-to-text from Python
If you want an API instead of local transcription, OpenAI is one option.
OpenAI’s Audio API FAQ says there are different approaches depending on whether you are transcribing completed recordings or handling ongoing streams, and points developers to the speech-to-text documentation. OpenAI also introduced newer real-time voice models in 2026, including GPT-Realtime-Whisper for live speech-to-text, according to Reuters reporting on OpenAI’s voice model launch.
For a simple prerecorded audio file, the Python flow looks like this:
pip install openai
Then:
from openai import OpenAI
client = OpenAI()
with open("audio.mp3", "rb") as audio_file:
transcript = client.audio.transcriptions.create(
model="gpt-4o-mini-transcribe",
file=audio_file
)
print(transcript.text)
Store your API key as an environment variable:
export OPENAI_API_KEY="your_api_key_here"
On Windows PowerShell:
setx OPENAI_API_KEY "your_api_key_here"
When OpenAI is a good fit
Use OpenAI speech-to-text when:
- You already use OpenAI in your app.
- You want a simple API.
- You want transcription plus LLM post-processing.
- You need clean developer experience.
- You may later connect transcription to summaries, extraction, or agents.
For production, check the current OpenAI audio docs before choosing a model name, because audio models and recommended endpoints can change.
Option 4: Use AssemblyAI for transcription and audio intelligence
AssemblyAI is a strong option when you want transcription plus features like speaker labels, summaries, chapters, topics, or other audio intelligence tools.
AssemblyAI’s docs describe Speech-to-Text models for converting audio files, video files, and live speech into text, plus streaming transcription and audio intelligence features.
Install:
pip install assemblyai
Basic transcription:
import assemblyai as aai
aai.settings.api_key = "your_api_key_here"
transcriber = aai.Transcriber()
transcript = transcriber.transcribe("audio.mp3")
if transcript.status == aai.TranscriptStatus.error:
print(transcript.error)
else:
print(transcript.text)
Use an environment variable instead of hardcoding the key:
import os
import assemblyai as aai
aai.settings.api_key = os.environ["ASSEMBLYAI_API_KEY"]
Add speaker labels
Speaker labels are useful for meetings, interviews, and calls.
/cod4import assemblyai as aai aai.settings.api_key = “your_api_key_here” config = aai.TranscriptionConfig( speaker_labels=True ) transcriber = aai.Transcriber(config=config) transcript = transcriber.transcribe(“meeting.mp3″) for utterance in transcript.utterances: print(f”Speaker {utterance.speaker}: {utterance.text}”)
Example output:
Speaker A: Can we review the onboarding flow?
Speaker B: Yes, the main issue is the payment step.
When AssemblyAI is a good fit
Use AssemblyAI when you need:
- File transcription.
- Streaming transcription.
- Speaker diarization.
- Meeting/interview transcripts.
- Audio summaries.
- Chapters or topics.
- Audio intelligence features.
- Developer-friendly speech workflows.
Option 5: Use Deepgram for fast speech-to-text
Deepgram is another strong speech-to-text API, especially for real-time and low-latency workflows.
Deepgram’s docs include pre-recorded audio transcription, live streaming audio, Python SDK examples, and audio intelligence features. The official Deepgram Python SDK supports automated speech recognition, text-to-speech, and language understanding APIs.
Install:
pip install deepgram-sdk
A simple prerecorded transcription pattern looks like this:
import os
from deepgram import DeepgramClient, PrerecordedOptions
deepgram = DeepgramClient(os.environ["DEEPGRAM_API_KEY"])
with open("audio.mp3", "rb") as audio:
buffer_data = audio.read()
payload = {
"buffer": buffer_data
}
options = PrerecordedOptions(
model="nova-3",
smart_format=True
)
response = deepgram.listen.rest.v("1").transcribe_file(
payload,
options
)
print(response["results"]["channels"][0]["alternatives"][0]["transcript"])
When Deepgram is a good fit
Use Deepgram when you need:
- Fast transcription.
- Real-time streaming.
- Voice agents.
- Call center workflows.
- Smart formatting.
- Language/audio intelligence features.
- Low-latency speech apps.
Deepgram is especially worth testing if your app needs live captions, real-time call transcription, or voice-agent input.
Option 6: Use Google Cloud Speech-to-Text
Google Cloud Speech-to-Text is a strong enterprise/cloud option.
Google’s Speech-to-Text documentation says the API lets developers send audio and receive text transcription from Google speech recognition technology. Google also provides a Python client library for Cloud Speech-to-Text.
Install:
pip install google-cloud-speech
Set up Google credentials first:
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
Basic local file example:
from google.cloud import speech
client = speech.SpeechClient()
with open("audio.wav", "rb") as audio_file:
content = audio_file.read()
audio = speech.RecognitionAudio(content=content)
config = speech.RecognitionConfig(
encoding=speech.RecognitionConfig.AudioEncoding.LINEAR16,
sample_rate_hertz=16000,
language_code="en-US"
)
response = client.recognize(
config=config,
audio=audio
)
for result in response.results:
print(result.alternatives[0].transcript)
Google’s API is powerful, but it is strict about audio config. If your file is MP3, FLAC, stereo, or a different sample rate, configure it correctly or convert it first.
When Google Cloud is a good fit
Use Google Cloud Speech-to-Text when:
- Your app already uses Google Cloud.
- You need enterprise cloud infrastructure.
- You process lots of audio.
- You need language/model configuration.
- You want integration with GCS, Pub/Sub, Dataflow, or BigQuery.
- You need speech transcription as part of a larger Google Cloud workflow.
Option 7: Use Azure AI Speech
Azure AI Speech is the Microsoft route for speech-to-text.
Microsoft’s quickstart says the Speech SDK for Python is available as a PyPI module, and Azure Speech supports real-time speech-to-text through Microsoft Foundry and Azure AI Speech resources.
Install:
pip install azure-cognitiveservices-speech
Basic file transcription:
import os
import azure.cognitiveservices.speech as speechsdk
speech_key = os.environ["AZURE_SPEECH_KEY"]
speech_region = os.environ["AZURE_SPEECH_REGION"]
speech_config = speechsdk.SpeechConfig(
subscription=speech_key,
region=speech_region
)
audio_config = speechsdk.audio.AudioConfig(
filename="audio.wav"
)
speech_recognizer = speechsdk.SpeechRecognizer(
speech_config=speech_config,
audio_config=audio_config
)
result = speech_recognizer.recognize_once()
if result.reason == speechsdk.ResultReason.RecognizedSpeech:
print(result.text)
else:
print("Speech could not be recognized:", result.reason)
When Azure is a good fit
Use Azure AI Speech when:
- Your company uses Microsoft/Azure.
- You need real-time speech recognition.
- You need enterprise controls.
- You are building call center or internal business workflows.
- You want to connect speech with Azure AI Language, Foundry, Functions, or Power Platform.
- You need custom speech features in the Microsoft ecosystem.
How to transcribe long audio files
Long files need extra care.
Many APIs have file size, duration, or timeout limits. Local models may work, but they can be slow or memory-heavy.
A practical approach:
- Convert audio to a clean format.
- Split it into chunks.
- Transcribe each chunk.
- Preserve timestamps.
- Merge the transcript.
- Run cleanup after merging.
Install audio tools:
pip install pydub
You also need FFmpeg.
Split audio into chunks:
from pydub import AudioSegment
from pathlib import Path
def split_audio(input_path, output_dir, chunk_length_ms=10 * 60 * 1000):
output_dir = Path(output_dir)
output_dir.mkdir(exist_ok=True)
audio = AudioSegment.from_file(input_path)
chunks = []
for index, start in enumerate(range(0, len(audio), chunk_length_ms)):
chunk = audio[start:start + chunk_length_ms]
chunk_path = output_dir / f"chunk_{index:03d}.wav"
chunk.export(chunk_path, format="wav")
chunks.append(chunk_path)
return chunks
chunks = split_audio("long_meeting.mp3", "chunks")
print(chunks)
Then transcribe each chunk:
import whisper
model = whisper.load_model("base")
full_transcript = []
for chunk_path in chunks:
result = model.transcribe(str(chunk_path))
full_transcript.append(result["text"])
final_text = "\n\n".join(full_transcript)
Path("long_meeting_transcript.txt").write_text(final_text, encoding="utf-8")
This is not perfect, because chunk boundaries can split sentences. For better results, use overlapping chunks or an API that handles long files well.
How to convert video to text
Speech-to-text often starts with video.
You can extract audio with FFmpeg:
ffmpeg -i input_video.mp4 -vn -acodec mp3 audio.mp3
Then transcribe audio.mp3.
Python wrapper:
import subprocess
from pathlib import Path
def extract_audio(video_path, audio_path):
command = [
"ffmpeg",
"-y",
"-i", str(video_path),
"-vn",
"-acodec", "mp3",
str(audio_path)
]
subprocess.run(command, check=True)
extract_audio("video.mp4", "video_audio.mp3")
Then pass video_audio.mp3 to Whisper, OpenAI, AssemblyAI, Deepgram, Google, or Azure.
This is useful for:
- YouTube-style videos.
- Webinars.
- Product demos.
- Recorded calls.
- Training videos.
- Interview recordings.
- Podcast clips.
How to make transcripts more readable
Raw transcripts can be rough.
They may need:
- Punctuation cleanup.
- Paragraph breaks.
- Speaker labels.
- Filler word removal.
- Summary.
- Action items.
- Topic headings.
- Translation.
- Entity extraction.
- Formatting for subtitles or notes.
Example cleanup prompt for an LLM:
Clean this transcript.
Keep the meaning unchanged.
Fix punctuation and paragraph breaks.
Do not remove important details.
Return only the cleaned transcript.
For meeting notes:
Turn this transcript into:
1. Short summary
2. Key decisions
3. Action items with owners
4. Open questions
This is where speech-to-text becomes more than transcription. It becomes workflow automation.
How to create subtitles from speech-to-text
Subtitles need timestamps.
If you use faster-whisper, you already get segment timestamps.
Generate a simple .srt file:
from faster_whisper import WhisperModel
def format_timestamp(seconds):
milliseconds = int((seconds % 1) * 1000)
total_seconds = int(seconds)
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
secs = total_seconds % 60
return f"{hours:02}:{minutes:02}:{secs:02},{milliseconds:03}"
model = WhisperModel("base", device="cpu", compute_type="int8")
segments, info = model.transcribe("video_audio.mp3")
with open("subtitles.srt", "w", encoding="utf-8") as file:
for index, segment in enumerate(segments, start=1):
file.write(f"{index}\n")
file.write(f"{format_timestamp(segment.start)} --> {format_timestamp(segment.end)}\n")
file.write(f"{segment.text.strip()}\n\n")
Now you have subtitles.
Attach them to video with:
ffmpeg -i video.mp4 -i subtitles.srt -c copy -c:s mov_text output_with_subtitles.mp4
Or burn them into the video:
ffmpeg -i video.mp4 -vf subtitles=subtitles.srt output_burned.mp4
How to handle noisy audio
Noisy audio hurts transcription quality.
Before blaming the speech model, check the file.
Common problems:
| Problem | What happens |
| Background noise | Words get misheard |
| Low volume | Speech is missed |
| Echo | Transcript becomes messy |
| Multiple speakers | Speaker turns get confused |
| Music | Lyrics/noise may appear in transcript |
| Bad microphone | Words blur together |
| Compression | Audio artifacts reduce accuracy |
| Long silence | Wastes processing time |
| Domain terms | Product names get miswritten |
Useful fixes:
- Use a better microphone.
- Record closer to the speaker.
- Convert to mono.
- Normalize volume.
- Remove long silence.
- Use custom vocabulary if available.
- Use a provider with speaker labels.
- Keep the original audio for review.
Convert to mono 16k WAV:
ffmpeg -i input.mp3 -ac 1 -ar 16000 output.wav
This format works well for many speech models and APIs.
How to choose the best speech-to-text API
Here is the practical comparison.
| Tool/API | Best for |
| Whisper / faster-whisper | Local/offline transcription |
| Vosk | Offline transcription with custom/local setup |
| OpenAI | Simple API + LLM workflow integration |
| AssemblyAI | File transcription, speaker labels, audio intelligence |
| Deepgram | Fast real-time and prerecorded transcription |
| Google Cloud Speech-to-Text | Google Cloud enterprise pipelines |
| Azure AI Speech | Microsoft enterprise and real-time speech |
| AWS Transcribe | AWS-native speech workflows |
| LLMAPI | Post-transcription summarization, routing, extraction |
If you are building a serious product, test with your real audio.
Not one clean clip.
Use:
- Clear speech.
- Noisy speech.
- Accents.
- Multiple speakers.
- Phone audio.
- Long recordings.
- Domain terms.
- Fast speech.
- Background music.
- Silence and interruptions.
Track:
| Metric | Why it matters |
| Word error rate | Overall transcription accuracy |
| Proper noun accuracy | Product names, people, companies |
| Timestamp quality | Needed for subtitles/search |
| Speaker label quality | Needed for meetings/calls |
| Latency | Needed for real-time apps |
| Cost per hour | Needed for scale |
| File limits | Needed for long recordings |
| Language support | Needed for multilingual apps |
| Formatting quality | Readability |
| Post-processing effort | Hidden cost |
The best API is the one that works on your audio, not the one with the nicest demo.
Where LLMAPI fits
LLMAPI fits after speech-to-text when your app needs to do something useful with the transcript.
Speech-to-text gives you raw text.
LLMAPI can help turn that text into:
| Task | Example |
| Summary | “Summarize this meeting in 5 bullets.” |
| Action items | “Extract tasks, owners, and deadlines.” |
| CRM notes | “Turn this sales call into CRM-ready notes.” |
| Support ticket | “Create a support ticket from this call.” |
| Compliance review | “Flag risky statements.” |
| Content repurposing | “Turn this webinar into a blog outline.” |
| Translation | “Translate the transcript into Spanish.” |
| Entity extraction | “Extract people, companies, dates, and prices.” |
| Routing | “Send billing calls to finance support.” |
A practical workflow looks like this:
audio/video → speech-to-text API → transcript → LLMAPI → summary/extraction/action
That is especially useful for voice agents, meeting tools, podcasts, sales calls, support calls, webinars, training videos, and internal automation.
Common mistakes when converting speech to text with Python
These are the classics.
| Mistake | Better approach |
| Testing only clean audio | Test real-world audio |
| Ignoring audio format | Convert to mono 16k WAV if needed |
| No timestamps | Use segment/word timestamps when useful |
| No speaker labels | Add diarization for meetings/calls |
| Hardcoding API keys | Use environment variables |
| No retry logic | Add retries for API failures |
| No chunking | Split long files or use async transcription |
| No review path | Review high-stakes transcripts |
| No domain vocabulary | Use custom vocabulary if available |
| Deleting original audio too soon | Keep audio when verification matters |
That last one matters more than people think.
Speech-to-text models can hallucinate or mishear words, especially in bad audio. Reporting from AP in 2024 described concerns that Whisper-based transcription tools used in hospitals sometimes invented text that was not spoken, and experts warned against deleting original audio before verification. Even outside healthcare, the lesson is useful: keep the original recording if the transcript may affect important decisions.
A simple production-ready workflow
Here is the version we would build first.
- Upload audio or video.
- Extract/normalize audio if needed.
- Store the original file.
- Send audio to the selected speech-to-text engine.
- Save raw transcript.
- Save timestamps and speaker labels if available.
- Run cleanup/formatting.
- Run LLMAPI for summary, action items, or extraction.
- Flag low-confidence sections for review.
- Store transcript and metadata.
- Show transcript with audio playback.
- Let users correct errors.
That gives you a product workflow, not just a transcription script.
The practical takeaway
You can convert speech to text with Python in several ways.
Use Whisper or faster-whisper if you want a local/offline setup. Use OpenAI if you want a simple speech-to-text API that connects nicely with LLM workflows. Use AssemblyAI if you need speaker labels and audio intelligence. Use Deepgram if speed and real-time streaming matter. Use Google Cloud Speech-to-Text if your app runs on Google Cloud. Use Azure AI Speech if your team works inside Microsoft. Use Vosk if offline transcription and custom local models matter.
The basic workflow looks like this:
audio/video → clean or convert → transcribe → timestamp → clean transcript → summarize/extract/action
That is how speech-to-text becomes useful.
Not just “audio into words,” but “spoken information into something your app can search, summarize, route, and act on.”