Lesson 3 of 5

Speech to text

Whisper reads a log-mel spectrogram with a transformer encoder and writes the words with a decoder. Run it in your browser and find where it fails.

Advanced18 min

Builds on How computers hear, Attention, step by step (Transformers and LLMs), and Tokens (Language as vectors)

In this lesson you will

  • Trace Whisper from audio to log-mel spectrogram to encoder to decoder tokens
  • Explain how special tokens set the task, how timestamps are made, and why audio is read 30 seconds at a time
  • Measure word error rate and recognize Whisper's typical failures with noise, accents, and silence

Video captions, transcribed voice messages, and meeting notes all start with the same step: Speech recognitionTurning recorded speech into text. Modern systems such as Whisper are neural networks that read a spectrogram of the audio and write the transcript one token at a time.Open in glossary, turning sound into text. In September 2022 OpenAI released Whisper, a family of open models trained on 680,000 hours of audio paired with transcripts collected from the internet. Its smaller versions are light enough to run in a browser. This lesson runs one on your device and then goes looking for its mistakes.

From a spectrogram to words

Whisper is an Encoder-decoderA model in two parts. The encoder reads the whole input (a sentence, or a spectrogram) into a set of vectors; the decoder writes the output one token at a time, looking back at those vectors through cross-attention.Open in glossary transformer, the same design as the original transformer for translation. Its input is not the waveform but the log-mel spectrogram from How computers hear: 80 mel bands, one frame every 10 ms, for a 30-second window.

  1. Audio30 s at 16,000 samples a secondshorter audio is padded with silence
  2. Log-mel spectrogram80 bands x 3,000 frames25 ms windows every 10 ms
  3. Two convolutions1,500 positions x 512one position per 20 ms
  4. Encoder6 transformer blocksself-attention over the whole window
  5. Decoder6 transformer blockswrites tokens, attending to the encoder

<|startoftranscript|><|0.00|>Printing, in the only sense...<|9.60|><|endoftranscript|>

Whisper base.en (74 million parameters). The encoder turns 30 seconds of sound into 1,500 vectors; the decoder writes text tokens one at a time, and through cross-attention every token can look at any of those 1,500 vectors. Time tokens such as <|0.00|> appear only when timestamps are requested.

The encoder starts with two small convolutions; the second takes every other step, so 3,000 frames become 1,500 positions, one per 20 ms. Position encodings are added, and then transformer blocks let every moment of the audio attend to every other moment. Out comes one vector per 20 ms of sound.

The decoder is a language model. It writes the transcript one TokenThe unit of text a language model reads and writes. A token can be a whole word, part of a word, a single character, or punctuation, often including a leading space.Taught in TokensOpen in glossary at a time, using the same tokenizer as GPT-2 for the English-only models, and each new token depends on the tokens before it, as in the transformers track. What makes it a recognizer is cross-attention: in every decoder block, the token being written can look at all 1,500 encoder vectors and pull in whatever part of the sound it needs. The model in this lab, Whisper base.en, has 74 million parameters, with 6 blocks in the encoder and 6 in the decoder.

Tokens that set the task

The decoder’s first tokens are instructions rather than words. Every transcript starts with <|startoftranscript|>. The multilingual models then predict a language token (one per language, 99 in all) and a task, <|transcribe|> or <|translate|> (into English); English-only models such as base.en skip those two. A <|notimestamps|> token asks for plain text. Without it, the decoder writes time tokens between pieces of text: a start time before each segment and an end time after it, rounded to 20 ms, which is the timing you see with Segments in the lab.

Word-level timings, the default in the lab, are not something Whisper was trained to write. They are worked out afterwards: a few cross-attention heads tend to look at the part of the audio being transcribed, so smoothing their attention weights and aligning them with the tokens (dynamic time warping) gives an estimated start and end for each word. Both OpenAI’s code and the Transformers.js library used here do this. The times are estimates, as you will see.

Whisper was trained on 30-second windows and cannot read more at once. Shorter audio is padded with silence; choose Whisper’s 30 seconds in the lab to see the padding. For longer recordings, OpenAI’s own code moves the window forward according to the timestamps it predicted. The library used here instead cuts long audio into 30-second windows that start every 20 seconds, so neighbors overlap by 10 seconds, and stitches the text together where they overlap. Record more than 30 seconds of your own voice to see the windows.

Speech to text with Whisper

Whisper reads a log-mel spectrogram of 30 seconds of audio and writes the words it hears, with times.

Linda Johnson, US English

Recorded from Whisper base.en

Loading the model's recorded outputs for the reading, the five speakers at every noise level, and the audio with no speech, with each kind of timestamps.

About the download

Transcribe the clips, noise, silence, or your own voice with Whisper, and see when it heard each word. This uses Whisper base.en, a 74-million-parameter English speech recognition model from OpenAI (2022), which turns speech into text.

The first time, your browser downloads about 80 MB of model files from Hugging Face, plus a 14 MB runtime from this site. Both are cached for later visits. Everything runs on your device; nothing you record is sent anywhere.

Manage downloads

Loading the recorded results

Audio
Added noise (speech louder than noise by)
Timestamps
Show
Audionone yet
Whisper reads3,000 frames x 80 bands
Word error raten/a
Time to transcriben/a

Challenges

0 of 3 complete

  1. Add background noise to a recording until Whisper gets at least one word in four wrong. (not yet)
  2. Give Whisper audio with no speech in it and catch it writing words anyway. (not yet)
  3. Among the five speakers, find one whose sentence Whisper gets wrong. (not yet)

Try this

  • Start with Reading and press a word in the transcript. It plays that stretch of audio and lights up its box on the spectrogram. How close are the boxes to the words you hear?
  • Step Added noise down from None to -10 dB, watching the spectrogram. At what point does the speech stop standing out, and when do the words start to go wrong?
  • Choose Five speakers and go through all five. They read the same sentence.
  • Choose No speech with Silence, then switch the view to Whisper’s 30 seconds. Where did it put the word it wrote?
  • Choose Your voice and record a sentence. Type what you said to score it. Try a whisper, a fast sentence, or a word Whisper is unlikely to know.
Word error rate and noise in NumPyPython with NumPy
import re
import numpy as np

def words(text):
    return re.findall(r"[a-z0-9']+", text.lower())

def word_error_rate(reference, heard):
    r, h = words(reference), words(heard)
    d = np.zeros((len(r) + 1, len(h) + 1), dtype=int)
    d[:, 0] = np.arange(len(r) + 1)          # drop every reference word
    d[0, :] = np.arange(len(h) + 1)          # insert every heard word
    for i in range(1, len(r) + 1):
        for j in range(1, len(h) + 1):
            swap = d[i - 1, j - 1] + (r[i - 1] != h[j - 1])   # match or substitute
            d[i, j] = min(swap, d[i - 1, j] + 1, d[i, j - 1] + 1)
    return d[-1, -1] / len(r)                # fewest edits per reference word

said = "He was a head shorter than his companion, of almost delicate physique."
print(f"{word_error_rate(said, 'He was head shorter than his companion of almost delicate physics.'):.3f}")
print(f"{word_error_rate(said, 'Here is a headshot of Dennis from Banyo, a far more delicate figure.'):.3f}")

# Background noise at a chosen signal-to-noise ratio (SNR), as the lab adds it.
rng = np.random.default_rng(0)
speech = 0.3 * np.sin(2 * np.pi * 200 * np.arange(16000) / 16000)   # stand-in for a voice
noise = rng.standard_normal(16000)
rms = lambda x: np.sqrt(np.mean(x ** 2))
for snr_db in (20, 0, -10):
    scaled = noise * rms(speech) / rms(noise) / 10 ** (snr_db / 20)
    print(f"SNR {snr_db:3d} dB: noise RMS {rms(scaled):.4f}, speech RMS {rms(speech):.4f}")
0.167
0.917
SNR  20 dB: noise RMS 0.0212, speech RMS 0.2121
SNR   0 dB: noise RMS 0.2121, speech RMS 0.2121
SNR -10 dB: noise RMS 0.6708, speech RMS 0.2121

Scoring a transcript

The standard score is the Word error rateThe standard score for speech recognition. Count the fewest word substitutions, deletions, and insertions that turn the transcript into the correct text, and divide by the number of correct words. Lower is better.Open in glossary. Line the transcript up with the correct text using the fewest edits, count substitutions SS, deletions DD, and insertions II, and divide by the number of reference words NN:

WER=S+D+IN\text{WER} = \frac{S + D + I}{N}

It can pass 100% when the model invents many words. The score depends on how text is normalized first: is “20th” the same as “twentieth”? The lab ignores case and punctuation and expands contractions such as “I’m”, but does not match numbers. Whisper’s paper uses a far more thorough normalizer, so the lab’s numbers cannot be compared with published ones. In the paper, with greedy decoding on the LibriSpeech test-clean benchmark, base.en scored 4.2% and the larger medium.en 3.1%.

Where it fails

Noise. On the clean reading the lab’s model makes no errors. With white noise added, it got at most one word wrong down to 5 dB (speech about three times more powerful than the noise), about one word in five at 0 dB, where the noise is as loud as the speech, and at -5 and -10 dB it wrote fluent sentences that were never said, one beginning “This is the only chance to”. Whisper was unusually robust for its time: in its paper’s noise test, all 14 comparison models, trained largely on the LibriSpeech dataset, did worse than Whisper once the signal-to-noise ratio of added pub noise (background chatter) fell below 10 dB. But every model, Whisper included, degraded as the noise grew.

Silence. Given 6 seconds of exact zeros, the model wrote “you”; given a faint hiss, “and”. Whisper’s authors list “complete hallucination where the model will output a transcript entirely unrelated to the actual audio” among its failure modes, and its model card suggests why: the model combines “trying to predict the next word in audio with trying to transcribe the audio itself”. The word is a HallucinationWhen a language model states something false or invented, such as a fake quote or citation, in the same fluent, confident style as true statements.Taught in What AI gets wrongOpen in glossary in the same sense as a chatbot’s. A 2024 study of OpenAI’s Whisper service by Allison Koenecke and colleagues found that roughly 1% of transcriptions contained whole invented phrases or sentences, more often for speakers with long pauses. OpenAI’s own transcription code checks the probability of a no-speech token together with the average confidence of the text to skip silent windows; the plain pipeline in this lab has no such check.

Accents. On the lab’s sentence, the US, Canadian, and Scottish speakers were transcribed perfectly and the Indian English speaker’s had two errors. One sentence is an anecdote, so we ran 20 sentences from each speaker through the same model: about 2 to 4 errors per 100 words for the two US speakers and the Canadian, 5 for the Scottish speaker, and 15 for the Indian English speaker. Each accent here is a single person reading in a quiet room, so speaker and accent cannot be separated. Larger studies point the same way: Whisper’s model card warns of “disparate performance on different accents and dialects”, and a 2020 study of five commercial recognizers found an average word error rate of 35% for Black speakers against 19% for white speakers in recorded interviews.

Why the lab's model is 8-bit, and what that costsOptional

The lab runs Whisper base.en with its weights stored as 8-bit integers (77 MB) instead of 32-bit floats (291 MB), a trade-off from the quantization lesson. We measured it on 140 clips (1,676 words) with this site’s code: the full-precision model made 90 word errors (5.4%), the 8-bit one 105 (6.3%), and 27 of the 140 transcripts changed. Quantizing only the encoder changed almost nothing (89 errors); the decoder is where precision matters. The smaller tiny.en model at full precision made 113 errors (6.7%) and is a larger download (151 MB), so the 8-bit base model is both smaller and more accurate on these clips.

Key ideas

  • Whisper is an encoder-decoder transformer: the encoder reads a 30-second log-mel spectrogram, and the decoder writes tokens while attending to it through cross-attention.
  • Special tokens set the task and turn timestamps on or off. Segment times are tokens the model writes; word times are estimated afterwards from cross-attention.
  • Word error rate counts substitutions, deletions, and insertions per reference word, and depends on how text is normalized.
  • Whisper degrades in heavy noise, varies across accents and speakers, and can write fluent text for audio with no speech in it.

Check yourself

Pick an answer to see why it is right or wrong. Nothing is graded. Your first answer is saved in this browser so the question can come back for review.

1What does Whisper's encoder actually read?
2Given 6 seconds of silence, Whisper base.en wrote "you". What best explains it?
3The reference has 12 words. The transcript leaves out one word and gets another wrong. What is the word error rate?
4Which statement about the word timestamps in the lab is accurate?

Progress is saved in this browser only.

Up nextText to speech
Next
Models that hear and speak
  1. 1How computers hear
  2. 2What sound is this?
  3. 3Speech to text
  4. 4Text to speech
  5. 5A voice assistant taken apart

Try "embedding", "softmax", "overfitting", or "backpropagation".