> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runanywhere.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Diarization

> Attribute spans of audio to speakers

`RunAnywhere.diarization.diarize` returns who spoke when. It gives time ranges, not text, so pair it
with [transcription](/flutter/stt/transcribe) when you need both.

```dart theme={null}
final result = await RunAnywhere.diarization.diarize(AudioInput.pcm16(pcm));

print('${result.speakerCount} speakers');
for (final segment in result.segments) {
  print('${segment.speakerId}: ${segment.startMs}-${segment.endMs}ms');
}
```

```dart theme={null}
Future<DiarizationResult> diarize(
  AudioInput audio, {
  DiarizationOptions? options,
});
```

It throws `SDKException` when the SDK is not initialized or no diarization model is loaded. Unlike the
generation verbs, `diarize` does not auto-load: load the model yourself first with
`RunAnywhere.models.load(id)`.

## DiarizationResult

`segments` is a `List<SpeakerSegment>` in chronological order, and `speakerCount` is the number of
distinct speakers found. `SpeakerSegment` carries `speakerId`, `startMs`, and `endMs`. Speaker labels
are stable only within one call.

## DiarizationOptions

```dart theme={null}
final result = await RunAnywhere.diarization.diarize(
  audio,
  options: DiarizationOptions(
    threshold: 0.6,
    minimumDurationMs: 250,
    mergeGapMs: 500,
  ),
);
```

| Field               | Type      | Default       | Notes                                            |
| ------------------- | --------- | ------------- | ------------------------------------------------ |
| `threshold`         | `double?` | model default | Speaker-change sensitivity                       |
| `minimumDurationMs` | `int?`    | model default | Segments shorter than this are dropped           |
| `mergeGapMs`        | `int?`    | model default | Adjacent same-speaker segments closer are merged |

The sample rate, channel count, and encoding come from the `AudioInput` you pass, so raw PCM and
Float32 both work without extra configuration.

## Labelling a transcript

For per-word speaker labels, ask STT for them instead. `SttOptions(diarization: true)` puts a
`speakerId` on every `Word`. See [STT options](/flutter/stt/options).

Use `diarize` when you want the speaker turns on their own, for instance to split a long recording
before transcribing each speaker separately.

```dart theme={null}
final turns = await RunAnywhere.diarization.diarize(AudioInput.pcm16(pcm));

for (final turn in turns.segments) {
  final slice = sliceMs(pcm, turn.startMs, turn.endMs);
  final text = await RunAnywhere.stt.transcribe(AudioInput.pcm16(slice));
  print('${turn.speakerId}: ${text.text}');
}
```

## Models

Diarization models register under `MODEL_CATEGORY_SPEAKER_DIARIZATION`. Register a backend that serves
the diarization primitive, then load the model.

```dart theme={null}
await RunAnywhere.models.register(
  ModelRegistration.archive(
    id: 'sherpa-onnx-speaker-diarization',
    name: 'Speaker Diarization',
    url: 'https://example.com/speaker-diarization.tar.bz2',
    archiveType: ArchiveType.ARCHIVE_TYPE_TAR_BZ2,
    structure: ArchiveStructure.ARCHIVE_STRUCTURE_NESTED_DIRECTORY,
    framework: InferenceFramework.INFERENCE_FRAMEWORK_SHERPA,
    category: ModelCategory.MODEL_CATEGORY_SPEAKER_DIARIZATION,
    memoryRequirementBytes: 90000000,
  ),
);

await RunAnywhere.models.load('sherpa-onnx-speaker-diarization');
```

## See also

<CardGroup cols={2}>
  <Card title="STT options" icon="sliders" href="/flutter/stt/options">
    Per-word speaker labels
  </Card>

  <Card title="Models" icon="box" href="/flutter/models">
    Registration and loading
  </Card>
</CardGroup>
