timestamps: true and you also get every word located in time — plus the transcript grouped into runs of speech, ready for subtitles.
Timestamps are free. The alignment is a by-product of the same decode pass, and you are billed on
audio_seconds whether you ask for it or not.turning it on
what comes back
Everything from a normal transcription, plus two arrays:Word[]
Every word in the transcript, in order.
Segment[]
The transcript grouped into runs of speech, split at the pauses used to chunk long audio.
words or segments?
subtitles
toSubtitles() formats a transcription as SubRip (.srt) or WebVTT (.vtt). It is a pure function — no client, no API key, no request.
response_format=verbose_json also returns segments and words, so Whisper code that already reads them keeps working.
how the alignment works
Seta is a CTC model. It reads the audio as a sequence of frames and emits a token — or a blank — for each one, so the frame index at which a token is emitted is its position in time. Grouping those tokens into words and multiplying by the frame duration gives the boundaries. Nothing is estimated after the fact and no second pass runs, which is why the feature is free. Audio longer than about 20 seconds is split at pauses before decoding. Each piece is timed independently and then shifted back into the timeline of the whole file, sostart and end are always measured from the beginning of your audio, whatever its length.
Precision is bounded by the frame rate, so treat boundaries as accurate to a few tens of milliseconds — right for subtitles, search and seeking. It is not phoneme-level forced alignment.
- Boundaries sit on speech, not silence. A segment starts at its first word and ends at its last, so the pause between segments is real silence.
- A word’s
endand the next word’sstartdiffer. The gap is the actual pause between them, not padding.
limits
Drop-in for Whisper
verbose_json, srt and vtt all work on the OpenAI-compatible route.Accuracy
8.71% WER on KSC2, including code-switched speech.