diff --git a/crates/transcription/src/local_engine.rs b/crates/transcription/src/local_engine.rs index feef65c..66612f1 100644 --- a/crates/transcription/src/local_engine.rs +++ b/crates/transcription/src/local_engine.rs @@ -113,6 +113,42 @@ impl LocalEngine { } } +/// Thin wrapper over `ParakeetModel` that overrides `transcribe_raw` to +/// request word-granularity segments. `transcribe-rs` 0.3's trait impl for +/// `ParakeetModel::transcribe_raw` ignores `TranscribeOptions` and uses +/// `TimestampGranularity::Token` (per-subword) — which surfaces in Kon as +/// "T Est Ing . One , Two , Three" output. The concrete-type method +/// `ParakeetModel::transcribe_with` accepts `ParakeetParams` with an +/// explicit granularity; this wrapper exposes that to the trait object. +struct ParakeetWordGranularity(transcribe_rs::onnx::parakeet::ParakeetModel); + +impl transcribe_rs::SpeechModel for ParakeetWordGranularity { + fn capabilities(&self) -> transcribe_rs::ModelCapabilities { + self.0.capabilities() + } + + fn default_leading_silence_ms(&self) -> u32 { + self.0.default_leading_silence_ms() + } + + fn default_trailing_silence_ms(&self) -> u32 { + self.0.default_trailing_silence_ms() + } + + fn transcribe_raw( + &mut self, + samples: &[f32], + options: &TranscribeOptions, + ) -> std::result::Result { + use transcribe_rs::onnx::parakeet::{ParakeetParams, TimestampGranularity}; + let params = ParakeetParams { + language: options.language.clone(), + timestamp_granularity: Some(TimestampGranularity::Word), + }; + self.0.transcribe_with(samples, ¶ms) + } +} + /// Load a Parakeet model from a directory path. pub fn load_parakeet( model_dir: &Path, @@ -127,7 +163,7 @@ pub fn load_parakeet( "Failed to load Parakeet: {e}" )) })?; - Ok(Box::new(model)) + Ok(Box::new(ParakeetWordGranularity(model))) } /// Load a Whisper model from a GGML file path.