Migrating from ElevenLabs to Speech Revolutions

ElevenLabs' Scribe speech-to-text is a single synchronous multipart POST to /v1/speech-to-text. Word timestamps come back by default and diarize=true adds a speaker_id to each word. Speech Revolutions covers the same ground — transcript, per-word times, and speakers — and the SDK reduces it to one transcribe() call. This guide maps auth, upload, and the response shape (including a token quirk to watch for), and points to where Speech Revolutions measures ahead for Scribe migrators.

What changes, what doesn't

Your diarize flag ports as-is (Speech Revolutions accepts diarize as an alias for speaker_labels), and result.text maps directly. The main cleanup is dropping ElevenLabs' spacing word-array tokens — the Speech Revolutions result.words are already words only.

Authentication

ElevenLabs authenticates with an xi-api-key header. Speech Revolutions uses X-API-Key, read from the environment by the SDK.

ElevenLabsSpeech Revolutions
xi-api-key: ELEVENLABS_API_KEYX-API-Key: SPEECHREVOLUTIONS_API_KEY
ELEVENLABS_API_KEY env varSPEECHREVOLUTIONS_API_KEY

Endpoint & method mapping

ElevenLabsSpeech Revolutions RESTSpeech Revolutions SDK
POST /v1/speech-to-text (sync multipart, model_id)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

ElevenLabs takes the audio as a multipart file field with model_id in the form body. Speech Revolutions uploads through a presigned object-storage URL, so bytes stream to storage rather than through the API request — handled by the SDK when you pass a path, URL, or bytes. Speech Revolutions also reports live upload and transcribe progress (see live progress).

Response shape

ElevenLabs returns text plus a words[] array in which entries have a type of word or spacing; the spacing entries are not real words. Speakers appear as speaker_id strings (e.g. speaker_0). The Speech Revolutions result.words contains words only, with matching string speaker labels.

ElevenLabs fieldSpeech Revolutions
textresult.text
words[] where type == "word" (text, start, end, speaker_id)result.words (text, start, end, speaker) — no spacing tokens
words[] where type == "spacing"— (dropped; you no longer filter these out)
— (regroup by speaker_id yourself)result.utterances (pre-grouped speaker turns)
language_coderesult.languages

If your code skips word.type === "spacing" entries, you can delete that filter — result.words is already words only.

Diarization

ElevenLabs diarizes with diarize=true, adding a speaker_id per word. Speech Revolutions uses the same diarize flag (alias for speaker_labels, on by default) and also groups words into result.utterances, so you don't reconstruct turns from per-word ids. Diarization accuracy is a clear Speech Revolutions strength — it leads on every subset in our testing; see the benchmarks and the comparison table for the measured DER.

Timestamps

Both return per-word start/end times in seconds by default. Timestamp precision is another area Speech Revolutions measures well on for Scribe migrators — the benchmarks report the median word-boundary error side by side, so you can compare rather than take our word for it.

Language selection

ElevenLabs takes language_code. 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.

Side by side

from elevenlabs.client import ElevenLabs

client = ElevenLabs()  # ELEVENLABS_API_KEY

with open("meeting.mp3", "rb") as f:
    resp = client.speech_to_text.convert(
        model_id="scribe_v2",
        file=f,
        diarize=True,
    )

print(resp.text)
for w in resp.words:
    if w.type == "word":                       # skip spacing tokens
        print(w.speaker_id, w.text, w.start, w.end)

Common pitfalls

  • Auth header. xi-api-key X-API-Key.
  • Spacing tokens. The Speech Revolutions words array omits them — remove any type filtering.
  • Speaker grouping. Prefer result.utterances over regrouping per-word speaker_id values.
  • No keyword API on ElevenLabs. If you needed domain-term biasing and couldn't get it, Speech Revolutions adds custom_vocabulary.

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