nihility-listener 0.1.0

nihility project asr module
Documentation
#![doc = include_str!("../README.md")]

use crate::asr::{AutomaticSpeechRecognition, AutomaticSpeechRecognitionConfig};
use crate::error::*;
use crate::input::{AudioInput, AudioInputConfig};
use crate::vad::{VoiceActivityDetection, VoiceActivityDetectionConfig};
use serde::{Deserialize, Serialize};
use tokio::sync::mpsc;

pub mod asr;
pub mod error;
pub mod input;
pub mod utils;
pub mod vad;

/// 助手项目中实时语音输入项目配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NihilityListenerConfig {
    pub sample_channel_size: usize,
    pub speech_channel_size: usize,
    pub audio_input: AudioInputConfig,
    pub vad: VoiceActivityDetectionConfig,
    pub asr: AutomaticSpeechRecognitionConfig,
}

/// 助手项目中实时语音输入
pub struct NihilityListener {
    input: AudioInput,
    vad: VoiceActivityDetection,
    asr: AutomaticSpeechRecognition,
}

impl NihilityListener {
    /// 读取文件配置初始化语音输入实例
    pub fn init_from_file_config() -> Result<(Self, mpsc::UnboundedReceiver<String>)> {
        Self::init(nihility_config::get_config::<NihilityListenerConfig>(
            env!("CARGO_PKG_NAME"),
        )?)
    }

    /// 根据配置初始化语音输入实例
    pub fn init(config: NihilityListenerConfig) -> Result<(Self, mpsc::UnboundedReceiver<String>)> {
        let (sample_sender, sample_receiver) = mpsc::channel::<f32>(config.sample_channel_size);
        let (speech_sender, speech_receiver) =
            mpsc::channel::<Vec<f32>>(config.speech_channel_size);
        let (text_sender, text_receiver) = mpsc::unbounded_channel::<String>();

        let input = AudioInput::init(config.audio_input.clone(), sample_sender)?;
        let vad = VoiceActivityDetection::init(config.vad.clone(), sample_receiver, speech_sender)?;
        let asr =
            AutomaticSpeechRecognition::init(config.asr.clone(), speech_receiver, text_sender)?;

        Ok((Self { input, vad, asr }, text_receiver))
    }

    /// 开始实时语音识别
    pub async fn start(&mut self) -> Result<()> {
        tokio::try_join!(self.asr.run(), self.vad.run())?;
        self.input.play()?;
        Ok(())
    }
}

impl Default for NihilityListenerConfig {
    fn default() -> Self {
        Self {
            sample_channel_size: 16000 * 10,
            speech_channel_size: 5,
            audio_input: AudioInputConfig::default(),
            vad: VoiceActivityDetectionConfig::default(),
            asr: AutomaticSpeechRecognitionConfig::default(),
        }
    }
}