Add all scaffolding, design, and decision documentation AKA first commit

This commit is contained in:
iamdoubz committed 2026-06-30 16:12:55 -05:00
1 parent b19e01c171
commit aae22a0e23
63 files changed
+4690

No files matched your search

+40
View File
@@ -0,0 +1,40 @@
//! Speaker diarization (Phase 4, FR-SPK-*). sherpa-onnx: segmentation +
//! embedding + clustering, fully offline (ADR-0005).
//!
//! Runs as a post-stop pass over the recorded WAV (audio = source of truth),
//! then aligns speaker spans to transcript segments by timestamp overlap.
//! Speaker IDs are internal ("S1"…); names are applied at render time and never
//! destructively rewritten onto segments (FR-SPK-5).
use crate::models::{SpeakerSpan, TranscriptSegment};
use std::path::Path;
#[derive(Debug, thiserror::Error)]
pub enum DiarError {
#[error("model load failed: {0}")]
Load(String),
#[error("diarization failed: {0}")]
Run(String),
}
pub trait Diarizer: Send + Sync {
/// Partition audio into speaker spans.
fn diarize(&self, wav: &Path) -> Result<Vec<SpeakerSpan>, DiarError>;
/// Assign speaker labels to transcript segments by overlap with spans.
fn assign(&self, segments: &mut [TranscriptSegment], spans: &[SpeakerSpan]);
}
#[cfg(feature = "diarization")]
pub struct SherpaDiarizer;
#[cfg(feature = "diarization")]
impl Diarizer for SherpaDiarizer {
fn diarize(&self, _wav: &Path) -> Result<Vec<SpeakerSpan>, DiarError> {
// T4.1: sherpa-onnx segmentation + embedding + clustering via FFI.
todo!("Phase 4 — diarize")
}
fn assign(&self, _segments: &mut [TranscriptSegment], _spans: &[SpeakerSpan]) {
// T4.2: timestamp-overlap alignment.
todo!("Phase 4 — assign speakers to segments")
}
}