wiseguru_ReWrite-Voice-Notes/docs/DIARIZATION.md
WiseGuru f3b93d5ab9 Fix secrets bootstrap + modal record UX; add ROADMAP lifecycle tracker
Secrets:
- Warm the secret-storage probe before loadSettings so a fresh install
  actually defaults to Obsidian secret storage instead of caching an
  unconfigured passphrase envelope first.
- setEncryptionMode no longer early-returns on same-mode: an unconfigured
  passphrase store now always builds its kdf/verifier, so creating a
  passphrase (incl. on Linux without a keyring) writes secrets.json.nosync
  instead of silently no-opping.

Modal:
- The Record tab closes the modal on Stop and runs the pipeline detached
  with Notice progress (per-stage setMessage) and Notice errors, mirroring
  the reprocess-audio flow. The persisted recording is the recovery path,
  so no inline Retry. Paste / From note keep the in-modal Retry flow.

Docs:
- Replace FEATURES.md with ROADMAP.md: Planned / Unreleased / Released
  lifecycle, wired into the RELEASING.md release steps.
- Update SECRETS.md, CLAUDE.md, and the Commands-and-Menus wiki page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 22:16:46 -07:00

13 lines
2.8 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 the diarization item in the [ROADMAP.md](ROADMAP.md) archive; 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.