diff --git a/configs/cat_state_machine.json b/configs/cat_state_machine.json index 636a3c7..d797604 100644 --- a/configs/cat_state_machine.json +++ b/configs/cat_state_machine.json @@ -1169,6 +1169,7 @@ "backend": "local", "whisper_lib_dir": "/home/showen/ai_spike/whisper.cpp/build/bin", "piper_lib_dir": "/home/showen/ai_spike/piper/piper", - "piper_config": "/home/showen/ai_spike/piper/zh_CN-huayan-medium.onnx.json" + "piper_config": "/home/showen/ai_spike/piper/zh_CN-huayan-medium.onnx.json", + "espeak_data_dir": "/home/showen/ai_spike/piper/piper/espeak-ng-data" } } \ No newline at end of file diff --git a/configs/dog_state_machine.json b/configs/dog_state_machine.json index e266eea..7c150b1 100644 --- a/configs/dog_state_machine.json +++ b/configs/dog_state_machine.json @@ -1181,6 +1181,7 @@ "backend": "local", "whisper_lib_dir": "/home/showen/ai_spike/whisper.cpp/build/bin", "piper_lib_dir": "/home/showen/ai_spike/piper/piper", - "piper_config": "/home/showen/ai_spike/piper/zh_CN-huayan-medium.onnx.json" + "piper_config": "/home/showen/ai_spike/piper/zh_CN-huayan-medium.onnx.json", + "espeak_data_dir": "/home/showen/ai_spike/piper/piper/espeak-ng-data" } } \ No newline at end of file diff --git a/src/core/config.rs b/src/core/config.rs index ef46e37..7fb2a77 100644 --- a/src/core/config.rs +++ b/src/core/config.rs @@ -390,6 +390,9 @@ pub struct AiConfig { /// piper 模型 config json 路径 (.onnx.json) #[serde(default)] pub piper_config: Option, + /// piper espeak-ng-data 目录路径 + #[serde(default)] + pub espeak_data_dir: Option, /// 临时文件目录 #[serde(default = "default_tmp_dir")] pub tmp_dir: PathBuf, diff --git a/src/main.rs b/src/main.rs index cbb14b5..5244af5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,6 +52,7 @@ fn main() -> Result<()> { let ai_whisper_lib_dir = config.ai.whisper_lib_dir.clone(); let ai_piper_lib_dir = config.ai.piper_lib_dir.clone(); let ai_piper_config = config.ai.piper_config.clone(); + let ai_espeak_data_dir = config.ai.espeak_data_dir.clone(); let ai_tmp_dir = config.ai.tmp_dir.clone(); let ai_context_window = config.ai.context_window; @@ -85,6 +86,7 @@ fn main() -> Result<()> { ai_whisper_lib_dir, ai_piper_lib_dir, ai_piper_config, + ai_espeak_data_dir, ai_tmp_dir, ai_context_window, ); diff --git a/src/plugins/ai/backend.rs b/src/plugins/ai/backend.rs index c5ae1cb..e7feffd 100644 --- a/src/plugins/ai/backend.rs +++ b/src/plugins/ai/backend.rs @@ -52,6 +52,8 @@ pub struct LocalCliBackend { piper_lib_dir: Option, /// piper 模型 config json 路径(.onnx.json) piper_config: Option, + /// piper espeak-ng-data 目录路径 + espeak_data_dir: Option, } impl LocalCliBackend { @@ -61,6 +63,7 @@ impl LocalCliBackend { whisper_lib_dir: None, piper_lib_dir: None, piper_config: None, + espeak_data_dir: None, } } @@ -70,10 +73,11 @@ impl LocalCliBackend { self } - /// 设置 piper 依赖库路径和 config(部署时由 deploy_ai.sh 标定) - pub fn with_piper_deps(mut self, lib_dir: PathBuf, config: PathBuf) -> Self { + /// 设置 piper 依赖(库路径、config、espeak-ng-data 目录) + pub fn with_piper_deps(mut self, lib_dir: PathBuf, config: PathBuf, espeak_data: PathBuf) -> Self { self.piper_lib_dir = Some(lib_dir); self.piper_config = Some(config); + self.espeak_data_dir = Some(espeak_data); self } @@ -198,10 +202,14 @@ impl AiBackend for LocalCliBackend { fn tts(&self, text: &str, model_path: &Path, output_path: &Path) -> Result<()> { // echo | piper -m [-c ] -f --output_format wav // piper 依赖 libespeak-ng.so / libpiper_phonemize.so,需设 LD_LIBRARY_PATH + // piper 需要 ESPEAK_DATA_PATH 指向 espeak-ng-data 目录 let mut cmd = Command::new(self.piper()); if let Some(lib_dir) = &self.piper_lib_dir { self.with_lib_path(&mut cmd, lib_dir); } + if let Some(espeak_data) = &self.espeak_data_dir { + cmd.env("ESPEAK_DATA_PATH", espeak_data); + } cmd.arg("-m") .arg(model_path) .arg("-f") diff --git a/src/plugins/ai/mod.rs b/src/plugins/ai/mod.rs index a2e5095..c2fff39 100644 --- a/src/plugins/ai/mod.rs +++ b/src/plugins/ai/mod.rs @@ -50,6 +50,7 @@ impl AiPlugin { whisper_lib_dir: Option, piper_lib_dir: Option, piper_config: Option, + espeak_data_dir: Option, tmp_dir: PathBuf, context_window: usize, ) -> Self { @@ -57,8 +58,9 @@ impl AiPlugin { if let Some(lib_dir) = whisper_lib_dir { backend_builder = backend_builder.with_whisper_lib_dir(lib_dir); } - if let (Some(lib_dir), Some(config)) = (piper_lib_dir, piper_config) { - backend_builder = backend_builder.with_piper_deps(lib_dir, config); + // piper 三个依赖必须同时设置 + if let (Some(lib_dir), Some(config), Some(espeak_data)) = (piper_lib_dir, piper_config, espeak_data_dir) { + backend_builder = backend_builder.with_piper_deps(lib_dir, config, espeak_data); } let backend = Box::new(backend_builder); let models = model_manager::ModelManager::new(model_store);