wiseguru_ReWrite-Voice-Notes/docs/DIARIZATION.md
2026-06-18 08:13:53 -07:00

13 lines
2.7 KiB
Markdown

# Speaker diarization
> Extracted from CLAUDE.md. Subject to the same maintenance rule: when you change diarization behavior, update this file in the same change, and keep the one-line summary in [CLAUDE.md](../CLAUDE.md) accurate.
Opt-in per-profile flag `TranscriptionConfig.diarize?: boolean` ([src/types.ts](../src/types.ts)). When on, the capable adapter embeds `Speaker X:` labels into the returned transcript string (the v1 shape from FEATURES.md item 4; the `transcribe(): Promise<string>` interface is unchanged, and cleanup/insert treat the labels as ordinary text). Capability is centralized in `transcriptionProviderSupportsDiarization(id)` ([src/transcription/index.ts](../src/transcription/index.ts)), true only for `assemblyai` / `deepgram` / `revai`. The settings tab ([src/settings/tab.ts](../src/settings/tab.ts)) shows an "Identify speakers" toggle in the per-profile transcription block gated on that helper; the setup card is intentionally left without it (not a "fill in the basics" field).
## Per-template override
A template can force diarization on for its own runs via `NoteTemplate.diarize?: boolean` (frontmatter `diarize: true`), independent of the profile toggle. [src/pipeline.ts](../src/pipeline.ts) `collectTranscript` merges `{ ...profile.transcriptionConfig, diarize: true }` for the transcribe call ONLY when `template.diarize` is set AND `transcriptionProviderSupportsDiarization(profile.transcriptionProvider)` is true; on a non-capable provider it leaves the config untouched (the flag is a documented no-op, not an error). The profile config is never mutated. The Meeting transcript default ships with this set. The override raises the effective setting only (a template never turns OFF a profile's diarization).
## Per-adapter behavior
[src/transcription/assemblyai.ts](../src/transcription/assemblyai.ts) sets `speaker_labels: true` and formats the returned `utterances[]` (`Speaker A: ...`, native letter labels); [src/transcription/deepgram.ts](../src/transcription/deepgram.ts) adds `diarize=true` and groups per-word `speaker` indices via `formatDiarizedWords` (0-based bumped to `Speaker 1`); [src/transcription/revai.ts](../src/transcription/revai.ts) fetches the JSON transcript (`Accept: application/vnd.rev.transcript.v1.0+json`) instead of `text/plain` and rebuilds labels from `monologues[]` via `formatMonologues` (0-based bumped to `Speaker 1`). Each adapter falls back to its flat-text path when the labeled payload is missing, so toggling off is a clean no-op. Label survival through cleanup is handled by a clause in `DEFAULT_SHARED_CORE` ([src/shared-core.ts](../src/shared-core.ts)) telling the LLM to preserve `Speaker X:` prefixes; the Podcast default template already tolerates labeled and unlabeled input.