Speaker diarization
Diarization answers "who spoke when." Speech Revolutions labels the speaker of each segment and of every word, so you can render a transcript as a conversation.
On the public benchmark suite, Zephyr ranks #1 on diarization error rate (DER) across every subset. Some providers don't support diarization at all, including OpenAI's gpt-4o-transcribe (as of July 2026). See the benchmarks page for the full provider-by-provider numbers and methodology, and speaker diarization measured across five APIs for interview and meeting audio side by side.
Turn it on
speaker_labels is on by default. diarize is a Deepgram-compatible alias for the same option, so code ported from Deepgram works unchanged.
# speaker_labels defaults to True; shown explicitly here.
result = client.transcribe("meeting.mp3", speaker_labels=True)
# diarize is a Deepgram-compatible alias for speaker_labels
result = client.transcribe("meeting.mp3", diarize=True)Speaker turns: .utterances
result.utterances is an AssemblyAI-style list of contiguous speaker turns. Each utterance has a speaker, text, the start/end of the turn, and the words in it.
result = client.transcribe("meeting.mp3", speaker_labels=True)
for u in result.utterances:
print(f"[{u.start:.1f}s] {u.speaker}: {u.text}")
# [0.5s] SPEAKER_1: Hi, thanks for joining.
# [3.2s] SPEAKER_2: Happy to be here.Per-word speakers: .words
Every entry in result.words also has a speaker alongside its timestamps. Utterances are runs of consecutive words with the same speaker. Use the per-word labels for finer control, such as highlighting the current speaker word by word.
for w in result.words[:4]:
print(w.speaker, w.word, w.start, w.end)
# SPEAKER_1 Hi 0.50 0.68
# SPEAKER_1 thanks 0.68 0.99Render speaker turns
To display a conversation, iterate over utterances. Each one is already a single turn, so print one block per utterance, optionally mapping labels like SPEAKER_1 to display names.
NAMES = {"SPEAKER_1": "Host", "SPEAKER_2": "Guest"}
def format_ts(seconds: float) -> str:
m, s = divmod(int(seconds), 60)
return f"{m:02d}:{s:02d}"
for u in result.utterances:
name = NAMES.get(u.speaker, u.speaker)
print(f"{format_ts(u.start)} {name}\n {u.text}\n")Speaker labels are string IDs that are stable within a job (for example, SPEAKER_1, SPEAKER_2). If you export a Deepgram-shaped response with result.to_deepgram(), those IDs become integer speaker indices to match Deepgram's schema.
Migrating from Deepgram
Besides the diarize alias, result.to_deepgram() returns Deepgram's pre-recorded response shape, including results.utterances with integer speaker indices, so your existing parsing code keeps working. See the migration playbook.
Timestamps covers the per-word start/end that diarization builds on. The cookbook has a copy-paste speaker-labels recipe.