feat(A.2 #13): replace SpeechBackend enum with Transcriber trait
New crates/transcription/src/transcriber.rs defines a Transcriber trait (Send supertrait for spawn_blocking travel) with TranscriberCapabilities (sample_rate, channels, supports_initial_prompt). TranscriberCapabilities.sample_rate is load-bearing for the upcoming progressive WAV writer (#19). Concrete impls: - SpeechModelAdapter wraps Box<dyn transcribe_rs::SpeechModel + Send> for Parakeet (and any future transcribe-rs-backed engine). - WhisperRsBackend moves its transcribe_sync body into the impl, widening the signature from &self to &mut self so per-call WhisperState can be created cleanly through the trait object. LocalEngine now holds Box<dyn Transcriber + Send>; dispatch in transcribe_sync collapses from a match to a direct call. Adds LocalEngine::capabilities() for the WAV-writer. Cargo feature flag "whisper" (default on) makes whisper-rs, num_cpus, and the whole whisper_rs_backend module optional. cargo check --no-default-features -p kon-transcription now builds without pulling whisper-rs-sys — the escape hatch brief item #6 / #13 called for on Windows / non-AVX2 / cloud-only builds. load_whisper is cfg-gated behind the same feature. src-tauri/src/commands/models.rs load_model_from_disk returns Box<dyn Transcriber + Send> instead of SpeechBackend; caller chain (ensure_model_loaded, prewarm_default_model) is unchanged. transcriber_trait_is_object_safe test lands alongside the trait as a compile-time witness against future Self-returning / generic-method additions.
This commit is contained in:
61
crates/transcription/src/transcriber.rs
Normal file
61
crates/transcription/src/transcriber.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
//! Engine-abstraction trait for speech-to-text backends.
|
||||
//!
|
||||
//! Replaces the previous `SpeechBackend` enum so new backends
|
||||
//! (Moonshine, whisper-rs forks, cloud ASR shims, Windows non-AVX2
|
||||
//! fallbacks) can drop in without adding a match arm in `LocalEngine`.
|
||||
//!
|
||||
//! Concrete implementers today: `SpeechModelAdapter` (wraps any
|
||||
//! `transcribe-rs` model, currently used for Parakeet) and — behind the
|
||||
//! `whisper` feature — `WhisperRsBackend` (direct whisper-rs, the only
|
||||
//! path that pipes `initial_prompt`).
|
||||
|
||||
use kon_core::error::Result;
|
||||
use kon_core::types::{Segment, TranscriptionOptions};
|
||||
|
||||
/// Static capabilities a `Transcriber` advertises to callers.
|
||||
///
|
||||
/// `sample_rate` is load-bearing for the progressive WAV writer (#19)
|
||||
/// which writes live capture samples to disk at the transcriber's
|
||||
/// native rate. `supports_initial_prompt` lets the Settings surface
|
||||
/// hide the initial-prompt field for backends that ignore it (Parakeet
|
||||
/// today).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct TranscriberCapabilities {
|
||||
pub sample_rate: u32,
|
||||
pub channels: u16,
|
||||
pub supports_initial_prompt: bool,
|
||||
}
|
||||
|
||||
/// Unified interface for speech-to-text backends.
|
||||
///
|
||||
/// `Send` is a supertrait so `Box<dyn Transcriber + Send>` travels
|
||||
/// across `spawn_blocking` boundaries without a per-site bound. All
|
||||
/// inference is synchronous — async callers wrap a `tokio::spawn_blocking`
|
||||
/// around `transcribe_sync`.
|
||||
pub trait Transcriber: Send {
|
||||
fn capabilities(&self) -> TranscriberCapabilities;
|
||||
|
||||
/// Synchronously transcribe 16 kHz mono f32 PCM (or whatever the
|
||||
/// backend's `capabilities().sample_rate` declares). `&mut self` so
|
||||
/// backends that keep per-call scratch state (whisper-rs's
|
||||
/// `WhisperState`, Parakeet's decoder buffers) can mutate them
|
||||
/// without interior-mutability gymnastics.
|
||||
fn transcribe_sync(
|
||||
&mut self,
|
||||
samples: &[f32],
|
||||
options: &TranscriptionOptions,
|
||||
) -> Result<Vec<Segment>>;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn transcriber_trait_is_object_safe() {
|
||||
// Compile-time witness: if the trait stops being object-safe
|
||||
// (e.g. someone adds a generic method or a Self-returning
|
||||
// method) this declaration fails to build. No runtime work.
|
||||
let _: Option<Box<dyn Transcriber + Send>> = None;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user