1#![doc = include_str!("../README.md")]
2
3use crate::asr::{AutomaticSpeechRecognition, AutomaticSpeechRecognitionConfig};
4use crate::error::*;
5use crate::input::{AudioInput, AudioInputConfig};
6use crate::vad::{VoiceActivityDetection, VoiceActivityDetectionConfig};
7use serde::{Deserialize, Serialize};
8use tokio::sync::broadcast::Receiver;
9
10pub mod asr;
11pub mod error;
12pub mod input;
13pub mod utils;
14pub mod vad;
15
16#[derive(Debug, Clone, Serialize, Deserialize, Default)]
18pub struct NihilityListenerConfig {
19 pub audio_input: AudioInputConfig,
20 pub vad: VoiceActivityDetectionConfig,
21 pub asr: AutomaticSpeechRecognitionConfig,
22}
23
24pub struct NihilityListener {
26 input: AudioInput,
27 vad: VoiceActivityDetection,
28 asr: AutomaticSpeechRecognition,
29}
30
31impl NihilityListener {
32 pub fn init_from_file_config() -> Result<Self> {
34 Self::init(nihility_config::get_config::<NihilityListenerConfig>(
35 env!("CARGO_PKG_NAME"),
36 )?)
37 }
38
39 pub fn init(config: NihilityListenerConfig) -> Result<Self> {
41 let input = AudioInput::init(config.audio_input.clone())?;
42 let vad = VoiceActivityDetection::init(config.vad.clone(), input.get_sample_receiver())?;
43 let asr = AutomaticSpeechRecognition::init(config.asr.clone(), vad.get_speech_receiver())?;
44
45 Ok(Self { input, vad, asr })
46 }
47
48 pub fn get_sample_receiver(&self) -> Receiver<f32> {
49 self.input.get_sample_receiver()
50 }
51
52 pub fn get_probability_receiver(&self) -> Result<Receiver<f32>> {
53 self.vad.get_probability_receiver()
54 }
55
56 pub fn get_speech_receiver(&self) -> Receiver<Vec<f32>> {
57 self.vad.get_speech_receiver()
58 }
59
60 pub fn get_text_receiver(&self) -> Receiver<String> {
61 self.asr.get_text_receiver()
62 }
63
64 pub async fn start(&mut self) -> Result<()> {
66 tokio::try_join!(self.asr.run(), self.vad.run())?;
67 self.input.play()?;
68 Ok(())
69 }
70}