Migrating from the OpenAI Whisper API to Speech Revolutions
OpenAI's transcription API is a single synchronous multipart POST to /v1/audio/transcriptions. It's simple, but three constraints tend to push teams to migrate: a hard 25 MB file limit, and — on the current gpt-4o-transcribe model — no word-level timestamps and no speaker diarization. Speech Revolutions returns transcript, word timestamps, and diarized speaker turns from a single call, with no file-size ceiling in the request body.
The capability gap this closes
On OpenAI, word timestamps require the older whisper-1 model (via response_format=verbose_json + timestamp_granularities), and speaker labels require a separate gpt-4o-transcribe-diarize model — gpt-4o-transcribe returns text only. Speech Revolutions gives you result.text, result.words (with times), and result.utterances (speakers) together, every time.
Authentication
OpenAI uses Authorization: Bearer <key>. Speech Revolutions uses X-API-Key, read from the environment by the SDK.
| OpenAI | Speech Revolutions |
|---|---|
Authorization: Bearer OPENAI_API_KEY | X-API-Key: SPEECHREVOLUTIONS_API_KEY |
OPENAI_API_KEY env var | SPEECHREVOLUTIONS_API_KEY |
Endpoint & method mapping
| OpenAI | Speech Revolutions REST | Speech Revolutions SDK |
|---|---|---|
POST /v1/audio/transcriptions (sync multipart) | POST /api/v1/upload → PUT to presigned URL → POST /api/v1/upload/complete | transcribe() (blocks until done) |
| — (response is inline) | GET /api/v1/jobs/{id} / /stream | get_transcript() / on_progress |
Upload differences & the 25 MB limit
OpenAI expects the audio as a multipart file field in the request body, which is why the API rejects anything over 25 MB — you have to pre-split or compress long recordings yourself. Speech Revolutions uploads through a presigned object-storage URL, so the bytes never pass through the API request body and there is no 25 MB request ceiling to work around. The SDK does the presign → PUT → complete handshake; you just pass a path, URL, or bytes.
No more chunking long files
If you built a splitter to keep files under 25 MB for OpenAI, you can retire it. Send the whole recording to transcribe().
Response shape
With response_format=json, OpenAI's gpt-4o-transcribe returns essentially { text } — no words, no segments, no speakers. Speech Revolutions returns those too:
| OpenAI field | Speech Revolutions |
|---|---|
text | result.text |
— (not returned by gpt-4o-transcribe) | result.words (word + start/end/speaker, seconds) |
| — (not returned) | result.utterances (speaker turns) |
language (with verbose_json) | result.languages |
Diarization
gpt-4o-transcribe cannot diarize — you would switch to the separate gpt-4o-transcribe-diarize model (true as of the models available on 2026-07-23; check OpenAI's current docs before relying on this). Speech Revolutions diarizes in the same call: set speaker_labels (on by default) and read result.utterances. Diarization is one of Zephyr's headline strengths; the benchmarks and comparison table have the measured numbers.
Timestamps
On OpenAI, word timestamps mean dropping back to whisper-1 with response_format=verbose_json and timestamp_granularities: ["word"]. On Speech Revolutions, word_timestamps is on by default and the times live on result.words in seconds — no model swap.
Language selection
OpenAI takes an ISO-639-1 language hint. Speech Revolutions always auto-detects, including code-switching mid-file — there's no language parameter to set. result.languages is a list of {start, end, language} segments covering the whole file, and every word in result.words also carries a language.
Custom vocabulary
OpenAI's only biasing lever is the free-text prompt (capped at roughly 224 tokens). Speech Revolutions takes an explicit custom_vocabulary list of domain terms.
Side by side
from openai import OpenAI
client = OpenAI() # OPENAI_API_KEY
with open("meeting.mp3", "rb") as f: # must be <= 25 MB
resp = client.audio.transcriptions.create(
model="gpt-4o-transcribe",
file=f,
response_format="json",
)
print(resp.text)
# no word timestamps, no speakers from gpt-4o-transcribeCommon pitfalls
- Auth prefix. Drop
Bearer; Speech Revolutions uses theX-API-Keyheader. - Expecting text only. Speech Revolutions returns
wordsandutterancesby default — you no longer need a second model for timestamps or speakers. - Left-over 25 MB workarounds. Chunking / compression steps built for OpenAI are unnecessary.
- Prompt-based biasing. Replace the
promptterm list withcustom_vocabulary.
Next steps
See the migration playbook for cutover, and the benchmarks for accuracy, diarization, and timestamp comparisons.