fix: piper 二进制+依赖库+config 修正 (符号链接指向正确二进制,加 LD_LIBRARY_PATH 和 -c 参数)

This commit is contained in:
2026-07-04 16:58:41 +08:00
parent 706b1375ce
commit 4fd7e7997e
7 changed files with 62 additions and 13 deletions

View File

@@ -48,6 +48,10 @@ pub struct LocalCliBackend {
tools_dir: PathBuf,
/// whisper-cli 依赖的库路径libggml*.so 所在)
whisper_lib_dir: Option<PathBuf>,
/// piper 依赖的库路径libespeak-ng.so / libpiper_phonemize.so 所在)
piper_lib_dir: Option<PathBuf>,
/// piper 模型 config json 路径(.onnx.json
piper_config: Option<PathBuf>,
}
impl LocalCliBackend {
@@ -55,6 +59,8 @@ impl LocalCliBackend {
Self {
tools_dir,
whisper_lib_dir: None,
piper_lib_dir: None,
piper_config: None,
}
}
@@ -64,6 +70,13 @@ impl LocalCliBackend {
self
}
/// 设置 piper 依赖库路径和 config部署时由 deploy_ai.sh 标定)
pub fn with_piper_deps(mut self, lib_dir: PathBuf, config: PathBuf) -> Self {
self.piper_lib_dir = Some(lib_dir);
self.piper_config = Some(config);
self
}
fn whisper_cli(&self) -> PathBuf {
self.tools_dir.join("whisper-cli")
}
@@ -76,21 +89,26 @@ impl LocalCliBackend {
self.tools_dir.join("piper")
}
/// 给命令设置 LD_LIBRARY_PATHwhisper-cli 依赖 libggml*.so
fn with_env(&self, cmd: &mut Command) {
if let Some(lib_dir) = &self.whisper_lib_dir {
cmd.env("LD_LIBRARY_PATH", lib_dir);
}
/// 给命令设置 LD_LIBRARY_PATH合并所有库路径
fn with_lib_path(&self, cmd: &mut Command, lib_dir: &Path) {
let existing = std::env::var("LD_LIBRARY_PATH").unwrap_or_default();
let new_path = if existing.is_empty() {
lib_dir.to_string_lossy().into_owned()
} else {
format!("{}:{}", lib_dir.to_string_lossy(), existing)
};
cmd.env("LD_LIBRARY_PATH", new_path);
}
}
impl AiBackend for LocalCliBackend {
fn asr(&self, audio_path: &Path, model_path: &Path) -> Result<String> {
// whisper-cli -m <model> -f <audio> -l zh --no-timestamps -otxt -of <tmp>
// 输出到 <tmp>.txt读取后返回
let tmp_out = audio_path.with_extension("asr.txt");
let mut cmd = Command::new(self.whisper_cli());
self.with_env(&mut cmd);
if let Some(lib_dir) = &self.whisper_lib_dir {
self.with_lib_path(&mut cmd, lib_dir);
}
let output = cmd
.arg("-m")
.arg(model_path)
@@ -178,15 +196,25 @@ impl AiBackend for LocalCliBackend {
}
fn tts(&self, text: &str, model_path: &Path, output_path: &Path) -> Result<()> {
// echo <text> | piper -m <model> -f <output> --output_format wav
// echo <text> | piper -m <model> [-c <config>] -f <output> --output_format wav
// piper 依赖 libespeak-ng.so / libpiper_phonemize.so需设 LD_LIBRARY_PATH
let mut cmd = Command::new(self.piper());
if let Some(lib_dir) = &self.piper_lib_dir {
self.with_lib_path(&mut cmd, lib_dir);
}
cmd.arg("-m")
.arg(model_path)
.arg("-f")
.arg(output_path)
.arg("--output_format")
.arg("wav")
.stdin(std::process::Stdio::piped())
.arg("wav");
// piper 需要 -c 指定 .onnx.json config 文件
if let Some(config) = &self.piper_config {
cmd.arg("-c").arg(config);
}
cmd.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::piped());
@@ -199,7 +227,8 @@ impl AiBackend for LocalCliBackend {
if !output.status.success() {
bail!(
"piper 失败: {}",
"piper 失败 (exit={}): {}",
output.status,
String::from_utf8_lossy(&output.stderr)
);
}

View File

@@ -48,6 +48,8 @@ impl AiPlugin {
model_store: PathBuf,
tools_dir: PathBuf,
whisper_lib_dir: Option<PathBuf>,
piper_lib_dir: Option<PathBuf>,
piper_config: Option<PathBuf>,
tmp_dir: PathBuf,
context_window: usize,
) -> Self {
@@ -55,6 +57,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);
}
let backend = Box::new(backend_builder);
let models = model_manager::ModelManager::new(model_store);
let pipeline = ChatPipeline::new(backend, models, tmp_dir, context_window);