use wasm_bindgen::prelude::*;
use aria_kit::audio::{Recording, RecordingReader, RecordingWriter};
use aria_kit::primitives::error_chain;
use aria_kit::transcription::{Language, Transcription, TranscriptionError, Whole};
use aria_stt::whisper_candle::WhisperCandle;
use crate::silence::SilenceGate;
#[wasm_bindgen]
pub struct Dictation {
capture: RecordingWriter,
recording: RecordingReader,
transcription: Transcription<WhisperCandle, Whole>,
gate: SilenceGate,
}
#[wasm_bindgen]
impl Dictation {
#[wasm_bindgen(constructor)]
pub fn new(
weights: &[u8],
tokenizer: &[u8],
config: &[u8],
trailing_silence_ms: u32,
) -> Result<Self, JsError> {
let gate = SilenceGate::new(trailing_silence_ms)
.map_err(|error| JsError::new(&error_chain(&error)))?;
let engine = WhisperCandle::from_bytes(weights, tokenizer, config).map_err(failed)?;
let transcription = Transcription::complete_samples(engine);
let (recording, capture) = Recording::open();
Ok(Self {
capture,
recording,
transcription,
gate,
})
}
pub fn push_audio(&mut self, samples: &[f32]) {
self.capture.push(samples);
self.gate.hear(samples);
}
pub fn speaker_stopped(&self) -> bool {
self.gate.stopped()
}
pub fn finish(mut self) -> Result<String, JsError> {
self.capture.finish();
match self
.transcription
.transcribe(&mut self.recording, &Language::Automatic)
{
Ok(transcript) => Ok(transcript.into_text()),
Err(TranscriptionError::NoSpeech) => Ok(String::new()),
Err(error) => Err(failed(error)),
}
}
}
fn failed(error: TranscriptionError) -> JsError {
JsError::new(&error_chain(&error))
}