Skip to content

Speaker Diarization

OpenASR can label transcript segments with per-speaker identities. Diarization is a model-agnostic stage that wraps around any ASR executor — it composes with every native model family additively, using neural VAD plus speaker segmentation, embedding, and clustering.

All processing is local. No network calls are made beyond a one-time, consented capability-pack install. Only L2-normalized embeddings are stored — raw enrollment audio is never written to the voiceprint store. Voice matching is a diarization convenience, not authentication.

Pass --diarize to transcribe or live:

bash
openasr transcribe --diarize recording.wav
openasr live --diarize

Segments are labeled with anonymous speakers in zero-padded format: SPEAKER_00, SPEAKER_01, and so on.

If the required WeSpeaker speaker-embedder capability pack is not already installed, passing --diarize triggers an automatic install — the flag itself is the consent. The install reuses the same progress UI as openasr pull. If --diarize is passed on a backend or pack that does not support diarization, the CLI fails closed with an error rather than silently skipping it.

For offline transcription you can force an exact cluster count:

bash
openasr transcribe --diarize --speakers 3 recording.wav

--speakers accepts a positive integer and requires --diarize. It is available on transcribe only — live does not support a forced speaker count.

Enroll a voice-match profile so diarized output uses a display name instead of an anonymous label:

bash
openasr speaker enroll enroll.wav --name "Alice" --match-similarity 0.6
OptionDescriptionDefault
<input>16 kHz mono PCM16 WAV with at least five seconds of speech.(required)
--nameDisplay name used when this voice matches.SPEAKER_ME
--match-similarityCosine similarity threshold (0–1) required for a match.0.5

If your audio is not in the right format, convert it with ffmpeg:

bash
ffmpeg -i input.mp3 -ac 1 -ar 16000 -c:a pcm_s16le enroll.wav

On success the CLI prints the profile name, ID, input path, and storage location. The profile takes effect on the next diarized session.

Remove all local voice-match profiles:

bash
openasr speaker clear

This deletes the on-disk voiceprint store entirely.

Profiles are stored at OPENASR_HOME/diarize/voiceprints.json by default. Override the path with the OPENASR_SPEAKER_PROFILES environment variable.

The server exposes a REST surface for managing voice-match profiles. All /v1/speakers routes are operator-only — they require the pairing admin token when pairing auth is enabled.

bash
curl -s http://127.0.0.1:8080/v1/speakers

Each profile in the response includes:

FieldTypeDescription
idstringProfile identifier.
namestringDisplay name.
created_atstringCreation timestamp.
sample_secondsnumberDuration of the enrollment audio.
compatibleboolWhether the stored embedding matches the currently active speaker-embedder.
bash
curl -s http://127.0.0.1:8080/v1/speakers \
-F name=Alice \
bash
curl -s -X PATCH http://127.0.0.1:8080/v1/speakers/{id} \
-H "Content-Type: application/json" \
-d '{"name": "Bob"}'

Replace a profile’s stored embedding from a new recording without changing its ID:

bash
curl -s -X POST http://127.0.0.1:8080/v1/speakers/{id}/reenroll \
-F wav=@new_sample.wav
bash
curl -s -X DELETE http://127.0.0.1:8080/v1/speakers/{id}

Returns { "id": "...", "deleted": true }.

  • Embeddings only — raw enrollment audio is never persisted. The voiceprint store contains L2-normalized embeddings and the active speaker-embedder identity.
  • Local processing — diarization runs entirely on-device. The only network activity is the one-time capability-pack download, which only happens when you pass --diarize and the pack is missing.
  • Not authentication — voice matching assigns display names during diarization. It is not an identity-verification mechanism.
  • No telemetry.

See the CLI reference for the full flag list and Server API for the complete endpoint table.