Switching STT APIs in under 30 minutes

Changing speech-to-text providers sounds risky. It isn't — if you do it behind an interface, compare on your own audio, and roll out gradually with a fallback. This is the provider-agnostic playbook; the per-provider guides (Deepgram, AssemblyAI, OpenAI Whisper, ElevenLabs, self-hosted Whisper) fill in the exact field mappings.

1. Why teams switch

  • Accuracy on their audio — general WER hides how a model does on your domain, accents, and multi-speaker recordings.
  • Diarization & timestamps — the difference between "a transcript" and a usable, speaker-labeled, seekable one.
  • Price at volume, output formats (SRT/VTT/DOCX), and operational simplicity (no GPUs to babysit).

2. What to evaluate

DimensionHow to judge it
AccuracyWER on a sample of your own audio, not a vendor's demo clip
DiarizationDER + does the speaker labeling actually hold up on your meetings
TimestampsWord-level start/end accuracy (matters for subtitles & search)
LanguagesThe specific languages and code-switching you serve
Formats & featuresJSON shape, SRT/VTT/DOCX, custom vocabulary, webhooks
Throughput & priceBatch latency and cost at your monthly volume

Measure on your data

Our public benchmark suite is reproducible and provider-agnostic — point it at your own audio and the providers you're comparing. The most honest benchmark is always yours.

3. Migrate behind an interface

Don't sprinkle vendor SDK calls across your codebase. Put transcription behind one function that returns your own normalized shape. Swapping providers then touches exactly one file. The Speech Revolutions result object is already transcript-first (.text, .words, .utterances) and can emit a Deepgram-shaped dict via to_deepgram() if you're mid-migration.

# transcription.py — the ONE place your app calls
from speechrevolutions import SpeechRevolutions

_client = SpeechRevolutions()  # SPEECHREVOLUTIONS_API_KEY

def transcribe(audio: str) -> dict:
    r = _client.transcribe(audio, speaker_labels=True, word_timestamps=True)
    return {
        "text": r.text,
        "speakers": [{"speaker": u.speaker, "text": u.text} for u in r.utterances],
        "words": [w.to_dict() for w in r.words],
    }

4. Compare outputs before you cut over

Run both providers over the same sample set through your interface, store both outputs, and diff them: WER against a reference if you have one, otherwise spot-check the transcripts, speaker turns, and timestamps that matter to your product. Keep the sample around as a regression set.

5. Roll out incrementally

  • Shadow — send a copy of production traffic to Speech Revolutions, compare, don't serve it yet.
  • Ramp — route 5% → 25% → 100% behind a feature flag, watching your quality and error metrics at each step.
  • Fall back — on error or timeout, have the interface fall back to the old provider until you're fully confident. One interface makes this a few lines.

Re-transcribing an existing library? Use submit() + polling or webhooks instead of blocking calls — see the batch tutorial.

6. The 30-minute quickstart

Authenticate, transcribe, read the result — that's the whole loop.

pip install speechrevolutions
export SPEECHREVOLUTIONS_API_KEY=stt_...
from speechrevolutions import SpeechRevolutions

client = SpeechRevolutions()
result = client.transcribe("meeting.mp3", speaker_labels=True)
print(result.text)

Next: pick your provider-specific guide for exact field mappings, or the Quickstart to go deeper.