Speech recognition used to mean a stack of specialist components — a voice activity detector, an acoustic model, a pronunciation lexicon, a language model, each with its own failure modes — and Whisper’s central idea is that a single sequence-to-sequence Transformer can replace all of it. Trained on a large and diverse corpus of audio, the model performs multilingual speech recognition, speech translation, and language identification, all expressed as ordinary token prediction: special tokens tell the decoder which task to do, which language to expect, and where each segment begins and ends in time. The codebase is famously compact — a single Python package you can read in an afternoon, MIT-licensed, installable with pip install -U openai-whisper, needing only ffmpeg beside it. The usage story is one line each: whisper audio.mp3 --model turbo on the command line, or whisper.load_model("turbo") followed by model.transcribe("audio.mp3") in Python, and the README’s table spans six sizes from the 39-million-parameter tiny to the 1.55-billion large, with the 809-million turbo delivering large-v3-class accuracy at roughly eight times its speed.

The source is organized the way a good lecture is. One module holds the network — the audio encoder with its convolutional stem and attention blocks, the text decoder with cross-attention back to the spectrogram, all parameterized by a single dimensions dataclass. One module holds the entire decoding strategy: greedy and beam search, hypothesis ranking, and a family of logit filters that keep timestamped output well-formed. Around them sit the audio front end that turns any file ffmpeg can read into log-Mel spectrograms, the tokenizer built on tiktoken vocabularies, a timing module that converts attention maps into word-level timestamps through dynamic time warping, and utility code that verifies downloads by hash and writes subtitles in five formats. Nothing is hidden behind a framework; what you call is what you read. As always in this series, what follows is an educational tour of published source code.

Whisper overview architecture diagram

Whisper at a glance: the CLI drives the 30-second-window transcribe loop, which feeds ffmpeg-decoded log-Mel windows into the encoder-decoder network through the decoding engine, guided by tiktoken-backed tokens; dynamic time warping over cross-attention adds word timestamps, and the utils module verifies checkpoints and writes subtitles.

Reading the overview from left to right:

Why You Need This

The first reason is that this is the cleanest full reference implementation of a modern speech model you can study. The network file defines ModelDimensions, a dataclass listing every hyperparameter — Mel bins, audio context, audio and text state sizes, head counts, layer counts, vocabulary size — from which the Whisper class builds everything. The AudioEncoder runs two Conv1d stem layers over the spectrogram, adds fixed sinusoidal positions, and stacks residual attention blocks; the TextDecoder does causal self-attention plus cross-attention to the encoder output. Even the attention implementation is instructive, using PyTorch’s scaled_dot_product_attention when available with a manual fallback and a disable_sdpa escape hatch. The beauty is that the same weights serve three tasks: change the task token and the model transcribes, translates, or identifies a language — the multitask design from the paper made physical in the tokenizer.

The second reason is the decoding layer, which is where the real engineering lives. The decoding module defines DecodingOptions and DecodingResult, an Inference interface with a PyTorch implementation that just calls the network, and a DecodingTask that composes everything for one pass. Search strategy is pluggable: a GreedyDecoder with temperature-based fallback tries progressively hotter decodes when output looks like repetition, a BeamSearchDecoder keeps multiple hypotheses alive, and the MaximumLikelihoodRanker scores across candidates with length normalization. The logit filter family is the hidden gem — SuppressBlank and SuppressTokens block degenerate outputs, while ApplyTimestampRules forces the model to emit a timestamp token before segment boundaries, which is how a pure language model produces correctly-sliced subtitles. Language detection falls out for free: one forward pass with a language-agnostic prompt, then a softmax over language tokens.

The third reason is the honest treatment of audio reality. The audio module accepts anything ffmpeg reads, resamples to sixteen kilohertz mono, pads or trims to exactly thirty seconds, and multiplies by a precomputed Mel filterbank — eighty bins for older models, one hundred twenty-eight for large-v3 and turbo. The transcription loop slides that window across long files with thirty-second stride, stitching segments and managing temperature fallback per window. For word-level timing, the timing module takes the cross-attention matrices between each token and the audio frames, median-filters them, and runs dynamic time warping — implemented for CPU, CUDA, and Triton kernels — to produce WordTiming objects with start, end, and probability. Output goes through the utils writers to txt, srt, vtt, tsv, and json, and the normalizers ship the exact text normalization used for fair benchmark comparison.

Whisper detail architecture diagram

The detail view: entry points at the top with the transcription loop and checkpoint loading, the audio front end with ffmpeg and the bundled filterbank, the network with dimensions, encoder, decoder, attention blocks, the decoding machinery with task composition, search, ranking, and filters, the timing stack with DTW and Triton kernels, and output with tokenizer, writers, and normalizers.

Walking the detail diagram, the flow from file to subtitle is fully traceable. The transcription function starts by asking load_model for weights, which checks a local cache keyed by sha256 and otherwise downloads from OpenAI’s storage — the utils download helper shows progress and verifies the hash. Audio enters through load_audio, pad_or_trim enforces the thirty-second window, and log_mel_spectrogram produces the input tensor. Inside the network, ModelDimensions sizes every layer, ResidualAttentionBlock repeats identically in encoder and decoder — the decoder’s blocks simply turn on cross-attention — and MultiHeadAttention serves both. On the decoding side, DecodingTask wires PyTorchInference to the network while the filter family and ApplyTimestampRules shape each step. The tokenizer wraps the tiktoken encodings and contributes the special-token grammar; find_alignment closes the loop by producing word timestamps from attention.

From Install to Your First Transcript

The path is three steps and no configuration. Install with pip install -U openai-whisper plus ffmpeg from your package manager — chocolatey on Windows, brew on macOS, apt on Debian. Transcribe a file with whisper audio.mp3 --model turbo; add --language Japanese to hint the language or --task translate on a multilingual model to get English text out, and --output_format srt when you want subtitles rather than plain text. In Python, whisper.load_model("turbo") returns the network, model.transcribe("audio.mp3") returns a dict of text and segments, and for finer control you load audio yourself, call pad_or_trim, build the spectrogram, and drive decode with custom DecodingOptions — the same primitives the CLI composes. Model choice is the only real decision: tiny and base run on any laptop CPU, small and medium trade speed for accuracy, turbo is the default for a reason, and large-v3 is there when accuracy is worth ten gigabytes of VRAM.

Honest limits: whisper is a research artifact from OpenAI, and its simplicity is also its ceiling. There is no streaming — audio must arrive as whole files or windows, so real-time transcription requires the many third-party ports built on this codebase rather than the original. There is no speaker diarization: the model cannot tell two voices apart, so interviews need a separate diarization pass. The codebase has no plugin system, no server mode, and no batched inference; its attention is unbatched per window, which is exactly why faster-whisper and the many Rust and C++ reimplementations exist. Hallucinations on silence or music remain a known failure mode, mitigated by the logit filters but not solved. And the model itself, while remarkable, has documented performance gaps across languages — check the language breakdown in the README before betting a production workload on an uncommon language. For what it does aim at — accurate, timestamped, multilingual transcription of recorded audio with code you can fully understand — it remains the reference.

Watch PyShine on YouTube

Contents