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.

OpenAISpeech Revolutions
Authorization: Bearer OPENAI_API_KEYX-API-Key: SPEECHREVOLUTIONS_API_KEY
OPENAI_API_KEY env varSPEECHREVOLUTIONS_API_KEY

Endpoint & method mapping

OpenAISpeech Revolutions RESTSpeech Revolutions SDK
POST /v1/audio/transcriptions (sync multipart)POST /api/v1/upload → PUT to presigned URL → POST /api/v1/upload/completetranscribe() (blocks until done)
— (response is inline)GET /api/v1/jobs/{id} / /streamget_transcript() / on_progress
POST/api/v1/upload

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 fieldSpeech Revolutions
textresult.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-transcribe

Common pitfalls

  • Auth prefix. Drop Bearer; Speech Revolutions uses the X-API-Key header.
  • Expecting text only. Speech Revolutions returns words and utterances by 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 prompt term list with custom_vocabulary.

See the migration playbook for cutover, and the benchmarks for accuracy, diarization, and timestamp comparisons.