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

2.8 KiB

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 accurate.

Opt-in per-profile flag TranscriptionConfig.diarize?: boolean (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 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), true only for assemblyai / deepgram / revai. The settings tab (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 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 sets speaker_labels: true and formats the returned utterances[] (Speaker A: ..., native letter labels); 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 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) telling the LLM to preserve Speaker X: prefixes; the Podcast default template already tolerates labeled and unlabeled input.