Researchtiming

Turning emergent cross-attention into a precise aligner

29.6 ms
boundary error · read speech (TIMIT)
40.6 ms
conversational speech · best of any system on Buckeye
k = 10
supervised heads · no new parameters

A speech decoder shines a spotlight on the audio as it predicts each word. We turn that spotlight into a laser: by first making the output policy explicit, so word timing is even well-defined, then supervising the cross-attention heads that already lean toward alignment.

Alignment-like behaviour emerges naturally in a few of Whisper's cross-attention heads: while the decoder predicts the next output word, those heads tend to look at the encoder positions where that word is encoded. Nobody trained them to. The signal is faint and unreliable on its own, but it is there, and it is the seed of a precise aligner.

This is how CrisperWhisper 2.0 makes that seed dependable. It takes two steps, in order. First we make sure the timing problem is even well-posed. Then we supervise the handful of cross-attention heads that already do the right thing, and read word timings straight off them, with no additional timestamp tokens to predict like in the original OpenAI implementation, and no separate alignment model like WhisperX and others.

Output policy

Verbatim transcription is what makes timing well-defined

Timing words means establishing a mapping between the transcript and the exact time each word was spoken in the audio. If the transcript omits things that were spoken, certain sections of the audio are unaccounted for, and the mapping becomes undefined. This makes timing fundamentally ill-defined for non-verbatim transcripts.

Collapse a repetition ("I, I think") to a single "I", and it is genuinely unclear which one should be timed: the first, the second, or should that one "I" occupy the timing of both and possibly the pause between them? Drop a filler, and the stretch of audio it occupied has no token to belong to: it bleeds into the previous word, the next one, or a silence. Every choice is an arbitrary convention. A verbatim transcript avoids all of this: every sound (filler, repetition, cut-off, laugh) has its own tokens, so every span of audio maps naturally to exactly where it belongs.

That is why we treat verbatimness as a precursor to well-defined timing. CrisperWhisper 2.0 is trained on parallel verbatim/intended pairs and switches between them on demand, and we read timing in verbatim mode, where "when did this word happen?" has a natural, well-defined answer.

Cross-attention

What the decoder is doing as it predicts

With a stable, verbatim output policy, let's look at what the decoder is actually doing as it predicts the next token. Whisper sees audio as a strip of encoder frames, one every 20 ms. The decoder produces the transcript one token at a time, and to predict each token it consults the encoder through cross-attention: a distribution over those frames that answers "which slices of audio am I looking at right now?"

As each token is emitted, its cross-attention picks out the encoder frames where that word lives, and the rows stack up into a [tokens × frames] matrix. In a few heads the bright band already tracks the diagonal of time; that is the emergent alignment. Toggle to the untrained heads below and the same bands turn diffuse and, for the disfluent tokens, smear onto their neighbours.

The decoder attends to the encoder, token by tokeninteractive
Cross-attention matrix: tokens by encoder framesencoder[uh]li-likecleantranscriptsdecoderii[uh]li-likecleantranscripts0.0 sencoder frames · 20 ms each3.0 s
cross-attention masswhere the word is in the audio
The simulated utterance is "i i [uh] li- like clean transcripts". Each row is one decoded token's cross-attention over the encoder frames; the teal outlines mark where each word actually sits in the audio. Supervised heads land tightly on each word; untrained heads are diffuse and ambiguous on the repeated "i", the filler "[uh]" and the cut-off "li-".
Supervision

Supervising the heads that already align

The key decision is where to push. We don't add an alignment module or retrain the decoder wholesale. We find the ten cross-attention heads whose untrained patterns already correlate best with real word alignments, and train only those. Because those heads already encode alignment-relevant information, supervising them is a gentle correction rather than a new skill bolted on, which both minimizes catastrophic forgetting of what the model can already do and directly sharpens the timing we care about.

We generate the training targets using the Montreal Forced Aligner over English speech: for each token we know which word it belongs to and where that word sits in the audio. From that we build a ground-truth target over the encoder frames: a binary indicator vector that is one on the frames the word occupies and zero everywhere else. The objective is simply that the selected heads' averaged cross-attention concentrate on that word's frames and stay off everything else.

We enforce this with a cosine-similarity loss applied at the word level. Every token belonging to a word shares the same ground-truth vector, so we compare that one-hot-style target against the predicted attention for the word: the averaged cross-attention of the supervised heads, taken over all of the word's tokens. Maximizing the cosine similarity between the predicted word-level attention and the binary target pulls the attention mass onto the word's frames and off everything else.

Why supervise the average, not each head

This is the part that reveals what is really going on. As the decoder commits to a word (say dog), it grows more and more certain of it through the deeper decoder layers, and at each step every head emits its own query that goes looking for the matching encoder frames. Those queries specialise: one effectively asks is there a "d" sound here?, another tunes to the "o", another to the closing "g". No single query captures the whole word, but together they cover its full acoustic realisation, and in doing so they locate exactly where in the audio that word was spoken.

Supervising the average of the ten heads is what allows that division of labour: the heads only have to be right together, so each is free to specialise. Force every head to match the target on its own and you forbid the specialisation: every head is dragged toward the same blurry compromise, and the collective loses exactly the acoustic sharpness that made the alignment good. Select a token below and compare the individual heads against their average.

Individual heads vs their supervised averageinteractive
Individual heads versus their supervised average
individual heads (specialised)their averagesupervision target (word span)
Each head looks a little different (they respond to different cues within the token), but only their average (blue) is trained to match the word span (teal). That freedom is what lets the heads specialise instead of all collapsing onto one blurry shape.
Extraction

From cross-attention to word times

CrisperWhisper 2.0 never emits Whisper's timestamp tokens. It reads timing straight from the supervised heads, in a few intuitive steps.

Collect the attention. As the model decodes, every token leaves one row of cross-attention over the encoder frames. Stacked, they form the [tokens × frames] matrix from the animation above: the raw material for timing.

Group tokens into words. Sub-word pieces are stitched back into words at the spaces, and a word made of several pieces simply owns all of their rows.

Pool and sharpen. The cross-attention rows belonging to a word are first added into a single distribution over frames, which is then sharpened so its peak is decisive: one timing signal per word.

Leaving room for silence and non-speech

Words alone can't explain the gaps between them, so the Viterbi also has a virtual blank state for silence and non-speech, non-vocal sound events: pauses, background noise, ambient sounds, anything that isn't a spoken word. To score it we lean on the mel energy as a rudimentary VAD: where the mel energy is low the frame is probably not speech, so the blank should be cheap. The intuition pairs nicely with the attention: because the supervised cross-attention is always firmly focused on the word being spoken, a frame should only fall to the blank where no word is strongly attending to it. So at each frame the path weighs the word emission (from attention) against a blank emission (from the mel energy), and the blank should win only where genuine speech focus is absent.

The catch is scale. Mel energy on its own is a poor discriminator: it isn't that speech is necessarily loud and everything else quiet; plenty of non-speech sound events carry energy too (background noise, music, ambient sound), while real speech can be modest. So we have to scale the two signals against each other: the cross-attention's speech focus must reliably cross above the energy-based blank wherever a word is actually being spoken, and the blank should only rise above it in true silence and non-speech. We reshape the mel energy into a blank probability that behaves that way: raising that blank probability to a power (blank_gamma=3) collapses it toward zero except where the mel energy is very low, and a fixed log-space penalty (blank_penalty=3) holds it under the attention until the non-speech evidence is strong. This pair of knobs is what worked well for us across our tests in various conditions across speakers and recordings without per-utterance tuning. Drag the controls to watch words shrink under a raw blank and recover under a shaped one.

Shaping the mel-energy blank so it doesn't eat the wordsinteractive
Shaping the mel-energy blank0.0 sframes · 20 ms each3.0 s
mel energyblank probabilityword kept by Viterbitrue word span
Raw vs shaped blank. With a raw blank (γ=1, penalty=0) the blank state fires across the quiet interiors of words and the Viterbi clips them to their attention peaks. Shaping it (γ=3, penalty=3) makes the blank attractive only where there is real silence or non-speech evidence, so the words recover their full extent, while true pauses and non-speech between words still get absorbed.

Walking the path

Together, the word distributions and the blank give every state a per-frame cost: low where that state explains the frame well, high where it doesn't. A monotonic Viterbi search then finds the lowest-cost path through this state-by-frame grid, along the alternating sequence blank · word · blank · word · …: at each frame the path may stay in its current state or advance to the next, never going back. The minimal-cost path is the alignment: the frames a word claims become its start and end, and at 20 ms per frame that's seconds.

Because the alternating structure forces the Viterbi to assign some duration to the blank between every pair of words, we split these artefact pauses evenly between the two neighbours; empirically a 100 ms threshold works best across datasets.

The minimal-cost path through the cost matrixschematic
Minimal-cost path through the cost matrixblankiblank[uh]blanklikeblankstates0.0 sencoder frames · 20 ms each
Rows are the alternating states (a blank between each pair of words); columns are encoder frames. Each cell's shade is the cost of explaining that frame with that state: word rows are cheap where the word's pooled attention is strong, blank rows are cheap where the shaped energy says silence. The Viterbi walks the cheapest monotonic staircase from the first state to the last; where it steps off a word row are that word's start and end.
Metrics

How we measure timing

Every system is scored against ground-truth word timings on two held-out test sets, TIMIT and Buckeye, whose word boundaries were annotated by human experts. Since the transcription models produce their own words, we first align each system's words to the reference transcript by text and only score timing on the words both agree on, so timing accuracy is judged independently of transcription mistakes. On those matched words we report three numbers:

MAE: mean absolute boundary error. The average distance, in milliseconds, between a predicted word boundary and the true one, over every start and end. This is the headline number; lower is better.

mIoU: mean intersection-over-union. How much each predicted word interval overlaps the true one (shared time divided by combined time), averaged over words. A single 0–100% score for how well the spans line up; higher is better.

F1 @ collar: the share of words whose start and end both land within a tolerance of the truth, reported at 50, 100 and 200 ms collars. It reads as "what fraction of words are placed to within ±50 ms?"; higher is better.

Results

How it scores against other speech transcription systems

We compared CrisperWhisper 2.0 against other leading speech-to-text providers, open and closed source alike, scoring every system on the same datasets. CrisperWhisper posts the best boundary error on both clean read speech (TIMIT) and conversational speech (Buckeye).

29.6 ms
mean absolute boundary error on clean read speech (TIMIT): the best of any system, ahead of Grok's 37.1 ms.
TIMIT · read speech · mean absolute boundary error · lower is betterBoundary error on read speech (TIMIT)
CrisperWhisperother systems
CrisperWhisper
29.6 ms
29.6 ms
Grok
37.1 ms
37.1 ms
CTC-seg
49.3 ms
49.3 ms
Scribe v2
51.3 ms
51.3 ms
NeMo-FA
60 ms
60 ms
Deepgram
63.3 ms
63.3 ms
WhisperX
64.8 ms
64.8 ms
Cartesia
69.4 ms
69.4 ms
Canary
85.5 ms
85.5 ms
Word boundaries annotated by human experts · TIMIT ≈ 12.6k matched words.
TIMIT · read · lower MAE is better, higher mIoU / F1 is better
modeltypeMAE msmIoUF1@50F1@100F1@200
CrisperWhispertranscription · local29.679.7%69.3%90.2%98.1%
Groktranscription · API37.171.5%50.2%91.7%98.6%
CTC-segforced aligner49.369.1%38.9%82.6%96.9%
Scribe v2transcription · API51.364.3%29.1%78.2%98.3%
NeMo-FAforced aligner6055.3%19.3%66.4%98.4%
Deepgramtranscription · API63.362.3%20.1%59.7%96.6%
WhisperXtranscription · local64.856.5%13.3%59.5%96.4%
Cartesiatranscription · API69.463.5%21.4%60.6%89.6%
Canarytranscription · local85.544%12.9%41.1%86.4%
40.6 ms
mean absolute boundary error on conversational speech (Buckeye): the best of any system, ahead of Grok's 47.1 ms.
Buckeye · conversational speech · mean absolute boundary error · lower is betterBoundary error on conversational speech (Buckeye)
CrisperWhisperother systems
CrisperWhisper
40.6 ms
40.6 ms
Grok
47.1 ms
47.1 ms
Scribe v2
59.6 ms
59.6 ms
NeMo-FA
74.9 ms
74.9 ms
CTC-seg
83.9 ms
83.9 ms
Deepgram
88.4 ms
88.4 ms
WhisperX
93 ms
93 ms
Canary
117.7 ms
117.7 ms
Cartesia
125.7 ms
125.7 ms
Word boundaries annotated by human experts · Buckeye ≈ 81k matched words.
Buckeye · conversational · lower MAE is better, higher mIoU / F1 is better
modeltypeMAE msmIoUF1@50F1@100F1@200
CrisperWhispertranscription · local40.671.5%60.6%80.1%88.8%
Groktranscription · API47.162.8%46.2%80.4%89.3%
Scribe v2transcription · API59.653.9%21.5%67.1%87%
NeMo-FAforced aligner74.944.3%20.3%58.6%94.5%
CTC-segforced aligner83.963.3%48.5%74.7%85.6%
Deepgramtranscription · API88.449.5%13.7%47%82.3%
WhisperXtranscription · local9341.8%7.8%48.5%84.2%
Canarytranscription · local117.729.8%8.9%30.1%71.2%
Cartesiatranscription · API125.759.7%32.8%59.8%74.7%

Types: forced aligner (given the words); transcription · local; transcription · hosted API. Word counts: TIMIT ≈ 12.6k, Buckeye ≈ 81k.

Takeaway. By making the output policy verbatim (so word timing is well-defined) and supervising only the ten cross-attention heads that already lean toward alignment, CrisperWhisper 2.0 reads word timings straight off the decoder cross-attentions with no timestamp tokens and no separate alignment model. It posts the best boundary error of any system on both read speech (29.6 ms, TIMIT) and conversational speech (40.6 ms, Buckeye).