rs_voice_toolkit_tts/lib.rs
1//! # TTS (Text-to-Speech) Module - 文本转语音模块
2//!
3//! 这个模块提供了高质量的文本转语音功能,支持多种 TTS 引擎和灵活的配置选项。
4//!
5//! ## 主要功能
6//!
7//! ### 核心特性
8//! - **多引擎支持**: 支持 Index-TTS、Piper、Coqui 等多种 TTS 引擎
9//! - **灵活配置**: 支持语言、说话人、采样率、速度、音调等参数配置
10//! - **多种输出**: 支持内存输出和文件输出两种方式
11//! - **高质量语音**: 基于 Index-TTS 引擎提供自然流畅的语音合成
12//! - **异步处理**: 完全异步的 API 设计,适合高并发场景
13//! - **可扩展架构**: 易于添加新的 TTS 引擎支持
14//!
15//! ### 支持的语言和说话人
16//! - **中文**: 支持标准中文语音合成
17//! - **英文**: 支持标准英文语音合成
18//! - **自动检测**: 根据文本内容自动选择语言
19//! - **多说话人**: 支持不同说话人声音(取决于引擎支持)
20//!
21//! ### 音频输出格式
22//! - **WAV**: 标准 WAV 格式输出
23//! - **采样率**: 支持 8kHz - 48kHz 采样率
24//! - **位深度**: 16-bit PCM
25//! - **声道**: 单声道/立体声(取决于引擎支持)
26//!
27//! ## 快速开始
28//!
29//! ### 基本语音合成
30//!
31//! ```rust
32//! use rs_voice_toolkit_tts::{TtsService, TtsConfig};
33//!
34//! #[tokio::main]
35//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
36//! // 创建默认配置
37//! let config = TtsConfig::default();
38//! let service = TtsService::new(config);
39//!
40//! // 检查引擎可用性
41//! if !service.is_available().await {
42//! println!("TTS 引擎不可用,请检查安装");
43//! return Ok(());
44//! }
45//!
46//! // 文本转语音(输出到文件)
47//! let text = "你好,世界!欢迎使用语音工具库。";
48//! let output_path = "output/hello.wav";
49//!
50//! service.text_to_file(text, output_path).await?;
51//! println!("语音合成完成: {}", output_path);
52//!
53//! Ok(())
54//! }
55//! ```
56//!
57//! ### 自定义配置语音合成
58//!
59//! ```rust
60//! use rs_voice_toolkit_tts::{TtsService, TtsConfig, TtsEngineType};
61//!
62//! #[tokio::main]
63//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
64//! // 自定义配置
65//! let config = TtsConfig {
66//! language: Some("zh".to_string()), // 中文
67//! speaker: Some("female".to_string()), // 女声
68//! sample_rate: 22050, // 采样率
69//! speed: 1.2, // 语速稍快
70//! pitch: 0.0, // 正常音调
71//! executable_path: None, // 使用系统 PATH
72//! };
73//!
74//! let service = TtsService::new(config);
75//!
76//! // 文本转语音(输出到内存)
77//! let text = "这是一段使用自定义配置生成的语音。";
78//! let audio_data = service.text_to_speech(text).await?;
79//!
80//! println!("生成音频数据大小: {} 字节", audio_data.len());
81//!
82//! // 保存到文件
83//! std::fs::write("output/custom.wav", audio_data)?;
84//!
85//! Ok(())
86//! }
87//! ```
88//!
89//! ### 批量语音合成
90//!
91//! ```rust
92//! use rs_voice_toolkit_tts::{TtsService, TtsConfig};
93//!
94//! #[tokio::main]
95//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
96//! let service = TtsService::new(TtsConfig::default());
97//!
98//! // 批量合成多个文本
99//! let texts = vec![
100//! "这是第一段文本。",
101//! "这是第二段文本。",
102//! "这是第三段文本。",
103//! ];
104//!
105//! for (i, text) in texts.iter().enumerate() {
106//! let output_path = format!("output/speech_{}.wav", i + 1);
107//!
108//! match service.text_to_file(text, &output_path).await {
109//! Ok(_) => println!("✓ {}: {}", i + 1, output_path),
110//! Err(e) => println!("✗ {}: {} - {}", i + 1, text, e),
111//! }
112//! }
113//!
114//! Ok(())
115//! }
116//! ```
117//!
118//! ## 引擎选择指南
119//!
120//! ### Index-TTS 引擎(默认)
121//! - **特点**: 高质量、多语言支持、配置灵活
122//! - **适用场景**: 通用语音合成、多语言应用
123//! - **安装**: 需要安装 index-tts 可执行文件
124//!
125//! ### Piper 引擎(计划中)
126//! - **特点**: 轻量级、离线运行、多说话人支持
127//! - **适用场景**: 嵌入式设备、离线应用
128//! - **状态**: 计划中功能
129//!
130//! ### Coqui 引擎(计划中)
131//! - **特点**: 高质量、可训练、多语言
132//! - **适用场景**: 专业语音合成、定制化需求
133//! - **状态**: 计划中功能
134//!
135//! ## 配置参数说明
136//!
137//! ### 基本配置
138//! - **language**: 语言设置("zh", "en", "auto")
139//! - **speaker**: 说话人选择(引擎相关)
140//! - **sample_rate**: 采样率(8000-48000 Hz)
141//!
142//! ### 语音效果调整
143//! - **speed**: 语速控制(0.5-2.0,1.0为正常)
144//! - **pitch**: 音调调整(-20.0到20.0,0.0为正常)
145//!
146//! ### 引擎配置
147//! - **executable_path**: 引擎可执行文件路径
148//!
149//! ## 性能优化
150//!
151//! ### 引擎优化
152//! - **保持服务实例**: 避免重复创建 TtsService 实例
153//! - **批量处理**: 使用批量合成减少初始化开销
154//! - **异步并发**: 利用异步特性进行并发处理
155//!
156//! ### 系统资源优化
157//! - **内存管理**: 及时释放大型音频数据
158//! - **磁盘空间**: 合理管理生成的音频文件
159//! - **CPU 使用**: 监控合成过程中的 CPU 使用率
160//!
161//! ### 音频质量优化
162//! - **采样率选择**: 根据应用场景选择合适的采样率
163//! - **语速调整**: 避免过快的语速影响可懂度
164//! - **音调调整**: 适度调整音调避免不自然
165//!
166//! ## 错误处理
167//!
168//! 模块提供了详细的错误类型,帮助快速定位问题:
169//!
170//! ```rust
171//! use rs_voice_toolkit_tts::{TtsService, TtsConfig, TtsError};
172//!
173//! let service = TtsService::new(TtsConfig::default());
174//!
175//! match service.text_to_speech("测试文本").await {
176//! Ok(audio_data) => println!("合成成功,音频大小: {} 字节", audio_data.len()),
177//! Err(TtsError::NotImplemented) => println!("功能尚未实现"),
178//! Err(TtsError::ConfigError(msg)) => println!("配置错误: {}", msg),
179//! Err(TtsError::AudioGenerationError(msg)) => println!("音频生成错误: {}", msg),
180//! Err(TtsError::EngineExecutionError(msg)) => println!("引擎执行错误: {}", msg),
181//! Err(e) => println!("其他错误: {}", e),
182//! }
183//! ```
184//!
185//! ## 系统要求
186//!
187//! ### Index-TTS 引擎要求
188//! - **内存**: ~100MB 运行内存
189//! - **CPU**: 支持多线程处理
190//! - **磁盘**: 引擎安装空间 ~50MB
191//! - **依赖**: index-tts 可执行文件
192//!
193//! ### 系统兼容性
194//! - **Linux**: 完全支持
195//! - **macOS**: 完全支持
196//! - **Windows**: 基本支持(取决于引擎)
197//!
198//! ## 注意事项
199//!
200//! - 首次使用前需要安装相应的 TTS 引擎
201//! - 建议在使用前验证引擎可用性
202//! - 长文本建议分段处理以避免内存问题
203//! - 实时应用建议使用较小的采样率以减少延迟
204//! - 生成的音频文件需要注意版权问题
205
206use async_trait::async_trait;
207use std::path::{Path, PathBuf};
208use thiserror::Error;
209use tokio::process::Command;
210
211/// TTS模块的错误类型
212///
213/// 这个枚举定义了TTS模块中可能出现的所有错误情况,提供了详细的错误信息
214/// 以帮助开发者快速定位和解决问题。
215///
216/// # 错误类型说明
217///
218/// - `NotImplemented`: 某些功能尚未实现,主要是一些计划中的引擎
219/// - `ConfigError`: 配置参数错误,如无效的采样率、缺失的可执行文件等
220/// - `AudioGenerationError`: 音频生成过程中的错误,如内存不足、格式不支持等
221/// - `EngineExecutionError`: TTS引擎执行过程中的错误,如进程启动失败、异常退出等
222///
223/// # 使用示例
224///
225/// ```rust
226/// use rs_voice_toolkit_tts::TtsError;
227///
228/// match some_tts_operation() {
229/// Ok(result) => println!("操作成功: {:?}", result),
230/// Err(TtsError::NotImplemented) => println!("该功能尚未实现"),
231/// Err(TtsError::ConfigError(msg)) => println!("配置错误: {}", msg),
232/// Err(TtsError::AudioGenerationError(msg)) => println!("音频生成失败: {}", msg),
233/// Err(TtsError::EngineExecutionError(msg)) => println!("引擎执行失败: {}", msg),
234/// }
235/// ```
236#[derive(Error, Debug)]
237pub enum TtsError {
238 /// TTS功能尚未实现
239 ///
240 /// 这个错误通常在尝试使用尚未实现的功能时出现,比如计划中的 Piper 或 Coqui 引擎。
241 #[error("TTS功能尚未实现")]
242 NotImplemented,
243
244 /// 配置错误
245 ///
246 /// 这个错误表示TTS配置存在问题,常见原因包括:
247 /// - 找不到指定的可执行文件
248 /// - 无效的采样率设置
249 /// - 不支持的语言或说话人设置
250 /// - 其他配置参数错误
251 ///
252 /// # 示例
253 ///
254 /// ```rust
255 /// # use rs_voice_toolkit_tts::TtsError;
256 /// let error = TtsError::ConfigError("找不到 index-tts 可执行文件".to_string());
257 /// println!("配置错误: {}", error);
258 /// ```
259 #[error("配置错误: {0}")]
260 ConfigError(String),
261
262 /// 音频生成错误
263 ///
264 /// 这个错误在音频数据生成过程中出现,可能原因包括:
265 /// - 内存不足导致无法生成音频
266 /// - 音频格式不支持
267 /// - 文本内容为空或无效
268 /// - 音频编码过程失败
269 ///
270 /// # 示例
271 ///
272 /// ```rust
273 /// # use rs_voice_toolkit_tts::TtsError;
274 /// let error = TtsError::AudioGenerationError("内存不足,无法生成音频数据".to_string());
275 /// println!("音频生成错误: {}", error);
276 /// ```
277 #[error("音频生成错误: {0}")]
278 AudioGenerationError(String),
279
280 /// 引擎执行错误
281 ///
282 /// 这个错误在TTS引擎执行过程中出现,可能原因包括:
283 /// - 引擎进程启动失败
284 /// - 引擎进程异常退出
285 /// - 引擎输出格式错误
286 /// - 引擎内部错误
287 ///
288 /// # 示例
289 ///
290 /// ```rust
291 /// # use rs_voice_toolkit_tts::TtsError;
292 /// let error = TtsError::EngineExecutionError("index-tts 进程异常退出".to_string());
293 /// println!("引擎执行错误: {}", error);
294 /// ```
295 #[error("引擎执行错误: {0}")]
296 EngineExecutionError(String),
297}
298
299/// TTS配置
300///
301/// 这个结构体定义了TTS引擎的所有配置参数,提供了灵活的语音合成选项。
302/// 通过调整这些参数,可以获得不同语言、说话人、音色和语速的语音输出。
303///
304/// # 配置参数说明
305///
306/// - `executable_path`: TTS引擎可执行文件路径,如果为None则从系统PATH中查找
307/// - `language`: 目标语言代码,如"zh"(中文)、"en"(英文)、"auto"(自动检测)
308/// - `speaker`: 说话人标识,具体支持的值取决于TTS引擎
309/// - `sample_rate`: 输出音频的采样率,范围通常在8000-48000Hz之间
310/// - `speed`: 语音播放速度,1.0为正常速度,范围0.5-2.0
311/// - `pitch`: 音调调整,0.0为正常音调,范围-20.0到20.0
312///
313/// # 使用示例
314///
315/// ## 基本配置
316///
317/// ```rust
318/// use rs_voice_toolkit_tts::TtsConfig;
319///
320/// // 使用默认配置
321/// let config = TtsConfig::default();
322///
323/// // 自定义配置
324/// let config = TtsConfig {
325/// executable_path: Some("/usr/local/bin/index-tts".into()),
326/// language: Some("zh".to_string()),
327/// speaker: Some("female".to_string()),
328/// sample_rate: 22050,
329/// speed: 1.0,
330/// pitch: 0.0,
331/// };
332/// ```
333///
334/// ## 链式配置
335///
336/// ```rust
337/// use rs_voice_toolkit_tts::TtsConfig;
338///
339/// let config = TtsConfig {
340/// language: Some("zh".to_string()),
341/// speaker: Some("male".to_string()),
342/// ..TtsConfig::default()
343/// };
344/// ```
345///
346/// # 参数建议
347///
348/// ## 采样率选择
349/// - `8000`: 电话质量,文件小,适合网络传输
350/// - `16000`: 标准语音识别质量,清晰度较好
351/// - `22050`: 多媒体应用标准,音质良好
352/// - `44100`: CD质量,音质最佳但文件较大
353///
354/// ## 语速调整
355/// - `0.5`: 慢速,适合学习或重要信息
356/// - `1.0`: 正常速度,适合大多数场景
357/// - `1.5`: 快速,适合信息密度高的内容
358/// - `2.0`: 极快,适合快速浏览
359///
360/// ## 音调调整
361/// - `-20.0`: 极低音,特殊效果
362/// - `-10.0`: 低音,男性化效果
363/// - `0.0`: 正常音调
364/// - `10.0`: 高音,女性化效果
365/// - `20.0`: 极高音,特殊效果
366///
367/// # 注意事项
368///
369/// - 并非所有TTS引擎都支持所有配置参数
370/// - 某些参数的有效范围可能因引擎而异
371/// - 建议在使用前测试不同参数组合的效果
372/// - 过于极端的参数值可能导致合成质量下降
373#[derive(Debug, Clone)]
374pub struct TtsConfig {
375 /// Index-TTS 可执行文件路径
376 ///
377 /// 指定TTS引擎可执行文件的完整路径。如果设置为None,
378 /// 系统会在PATH环境变量中查找引擎。
379 ///
380 /// # 示例
381 ///
382 /// ```rust
383 /// # use rs_voice_toolkit_tts::TtsConfig;
384 /// // 使用系统PATH中的引擎
385 /// let config1 = TtsConfig { executable_path: None, ..Default::default() };
386 ///
387 /// // 指定特定路径的引擎
388 /// let config2 = TtsConfig {
389 /// executable_path: Some("/usr/local/bin/index-tts".into()),
390 /// ..Default::default()
391 /// };
392 /// ```
393 pub executable_path: Option<PathBuf>,
394
395 /// 语言设置
396 ///
397 /// 指定语音合成的目标语言。支持的语言取决于TTS引擎。
398 ///
399 /// # 支持的语言代码
400 /// - `"zh"`: 中文
401 /// - `"en"`: 英文
402 /// - `"auto"`: 自动检测(如果引擎支持)
403 ///
404 /// # 示例
405 ///
406 /// ```rust
407 /// # use rs_voice_toolkit_tts::TtsConfig;
408 /// let config = TtsConfig {
409 /// language: Some("zh".to_string()),
410 /// ..Default::default()
411 /// };
412 /// ```
413 pub language: Option<String>,
414
415 /// 说话人设置
416 ///
417 /// 指定语音合成的说话人。支持的说话人取决于TTS引擎。
418 ///
419 /// # 常见说话人选项
420 /// - `"male"`: 男性声音
421 /// - `"female"`: 女性声音
422 /// - `"child"`: 儿童声音
423 /// - 其他引擎特定的说话人标识
424 ///
425 /// # 示例
426 ///
427 /// ```rust
428 /// # use rs_voice_toolkit_tts::TtsConfig;
429 /// let config = TtsConfig {
430 /// speaker: Some("female".to_string()),
431 /// ..Default::default()
432 /// };
433 /// ```
434 pub speaker: Option<String>,
435
436 /// 采样率
437 ///
438 /// 指定输出音频的采样率,单位为Hz。采样率越高,
439 /// 音质越好,但文件也越大。常见的采样率有:
440 ///
441 /// - `8000`: 电话质量
442 /// - `16000`: 标准语音质量
443 /// - `22050`: 多媒体质量
444 /// - `44100`: CD质量
445 /// - `48000`: 专业音频质量
446 ///
447 /// # 示例
448 ///
449 /// ```rust
450 /// # use rs_voice_toolkit_tts::TtsConfig;
451 /// let config = TtsConfig {
452 /// sample_rate: 22050,
453 /// ..Default::default()
454 /// };
455 /// ```
456 pub sample_rate: u32,
457
458 /// 语音速度
459 ///
460 /// 控制语音播放的速度。1.0为正常速度,值越大播放越快,
461 /// 值越小播放越慢。建议范围:0.5 - 2.0。
462 ///
463 /// # 速度对照
464 /// - `0.5`: 正常速度的一半
465 /// - `0.8`: 稍慢
466 /// - `1.0`: 正常速度
467 /// - `1.2`: 稍快
468 /// - `1.5`: 正常速度的1.5倍
469 /// - `2.0`: 正常速度的2倍
470 ///
471 /// # 示例
472 ///
473 /// ```rust
474 /// # use rs_voice_toolkit_tts::TtsConfig;
475 /// let config = TtsConfig {
476 /// speed: 1.2,
477 /// ..Default::default()
478 /// };
479 /// ```
480 pub speed: f32,
481
482 /// 音调调整
483 ///
484 /// 调整语音的音调。0.0为正常音调,正值提高音调,
485 /// 负值降低音调。建议范围:-20.0 - 20.0。
486 ///
487 /// # 音调效果
488 /// - `-20.0`: 极低音
489 /// - `-10.0`: 低音
490 /// - `0.0`: 正常音调
491 /// - `10.0`: 高音
492 /// - `20.0`: 极高音
493 ///
494 /// # 示例
495 ///
496 /// ```rust
497 /// # use rs_voice_toolkit_tts::TtsConfig;
498 /// let config = TtsConfig {
499 /// pitch: 5.0,
500 /// ..Default::default()
501 /// };
502 /// ```
503 pub pitch: f32,
504}
505
506impl Default for TtsConfig {
507 fn default() -> Self {
508 Self {
509 executable_path: None,
510 language: Some("auto".to_string()),
511 speaker: None,
512 sample_rate: 22050,
513 speed: 1.0,
514 pitch: 0.0,
515 }
516 }
517}
518
519/// TTS引擎类型
520///
521/// 这个枚举定义了支持的TTS引擎类型。目前只有Index-TTS引擎是完整实现的,
522/// 其他引擎作为未来扩展的预留选项。
523///
524/// # 引擎对比
525///
526/// ## Index-TTS(当前默认)
527/// - **特点**: 高质量、多语言、配置灵活
528/// - **支持**: 中文、英文等多种语言
529/// - **输出**: WAV格式音频
530/// - **安装**: 需要index-tts可执行文件
531///
532/// ## Piper(计划中)
533/// - **特点**: 轻量级、离线运行、多说话人
534/// - **支持**: 多种语言和声音
535/// - **输出**: WAV格式音频
536/// - **安装**: 单文件可执行程序
537///
538/// ## Coqui(计划中)
539/// - **特点**: 高质量、可训练、专业级
540/// - **支持**: 自定义模型训练
541/// - **输出**: 多种音频格式
542/// - **安装**: Python依赖和模型文件
543///
544/// # 使用示例
545///
546/// ```rust
547/// use rs_voice_toolkit_tts::{TtsService, TtsConfig, TtsEngineType};
548///
549/// // 使用默认引擎(Index-TTS)
550/// let service1 = TtsService::new(TtsConfig::default());
551///
552/// // 显式指定Index-TTS引擎
553/// let service2 = TtsService::new_with_engine(
554/// TtsConfig::default(),
555/// TtsEngineType::IndexTts
556/// );
557///
558/// // 未来使用其他引擎(尚未实现)
559/// // let service3 = TtsService::new_with_engine(
560/// // TtsConfig::default(),
561/// // TtsEngineType::Piper // 或 TtsEngineType::Coqui
562/// // );
563/// ```
564///
565/// # 引擎选择建议
566///
567/// - **通用应用**: 使用Index-TTS引擎
568/// - **离线需求**: 等待Piper引擎实现
569/// - **专业需求**: 等待Coqui引擎实现
570/// - **嵌入式设备**: 考虑未来的Piper引擎
571#[derive(Debug, Clone, PartialEq, Eq)]
572pub enum TtsEngineType {
573 /// Index-TTS 引擎
574 ///
575 /// 当前默认和唯一完整实现的TTS引擎。
576 /// 提供高质量的语音合成功能,支持多种语言和配置选项。
577 IndexTts,
578
579 /// Piper 引擎(未来支持)
580 ///
581 /// 计划中的轻量级TTS引擎,特点是:
582 /// - 单文件可执行程序
583 /// - 完全离线运行
584 /// - 支持多种说话人
585 /// - 适合嵌入式设备
586 ///
587 /// # 状态
588 /// 目前尚未实现,计划未来版本支持。
589 #[allow(dead_code)]
590 Piper,
591
592 /// Coqui 引擎(未来支持)
593 ///
594 /// 计划中的专业级TTS引擎,特点是:
595 /// - 高质量语音合成
596 /// - 支持自定义模型训练
597 /// - 多语言支持
598 /// - 专业应用场景
599 ///
600 /// # 状态
601 /// 目前尚未实现,计划未来版本支持。
602 #[allow(dead_code)]
603 Coqui,
604}
605
606impl Default for TtsEngineType {
607 fn default() -> Self {
608 Self::IndexTts
609 }
610}
611
612/// TTS引擎接口
613///
614/// 这个trait定义了所有TTS引擎必须实现的基本接口。通过这个统一的接口,
615/// 可以轻松添加新的TTS引擎实现,同时保持API的一致性。
616///
617/// # 接口设计原则
618///
619/// - **简洁性**: 只包含最核心的语音合成功能
620/// - **扩展性**: 易于添加新的引擎实现
621/// - **一致性**: 所有引擎提供相同的API接口
622/// - **异步性**: 支持异步操作,适合高并发场景
623///
624/// # 实现要求
625///
626/// 每个TTS引擎实现必须提供:
627/// - 文本到音频数据的转换功能
628/// - 文件输出功能
629/// - 引擎可用性检查
630/// - 支持的语言列表
631/// - 引擎类型标识
632///
633/// # 使用示例
634///
635/// ```rust
636/// use rs_voice_toolkit_tts::{TtsEngine, TtsError, TtsEngineType};
637/// use std::path::Path;
638///
639/// struct MyTtsEngine;
640///
641/// #[async_trait::async_trait]
642/// impl TtsEngine for MyTtsEngine {
643/// async fn synthesize(&self, text: &str) -> Result<Vec<u8>, TtsError> {
644/// // 实现文本到音频的转换
645/// Ok(Vec::new())
646/// }
647///
648/// async fn synthesize_to_file(&self, text: &str, output_path: &Path) -> Result<(), TtsError> {
649/// // 实现文件输出
650/// Ok(())
651/// }
652///
653/// async fn is_available(&self) -> bool {
654/// // 检查引擎是否可用
655/// true
656/// }
657///
658/// fn supported_languages(&self) -> Vec<String> {
659/// // 返回支持的语言列表
660/// vec!["zh".to_string(), "en".to_string()]
661/// }
662///
663/// fn engine_type(&self) -> TtsEngineType {
664/// // 返回引擎类型
665/// TtsEngineType::IndexTts
666/// }
667/// }
668/// ```
669///
670/// # 性能考虑
671///
672/// - `synthesize()` 方法应该避免重复的引擎初始化开销
673/// - `is_available()` 方法应该快速返回,不应该有昂贵的检查
674/// - `supported_languages()` 方法应该返回缓存的结果,避免重复计算
675/// - 文件操作应该使用异步方式以避免阻塞
676#[async_trait]
677pub trait TtsEngine {
678 /// 将文本转换为语音
679 ///
680 /// 这是核心的语音合成方法,将输入的文本转换为音频数据。
681 /// 返回的音频数据通常是WAV格式的二进制数据。
682 ///
683 /// # 参数
684 ///
685 /// - `text`: 要合成的文本内容
686 ///
687 /// # 返回值
688 ///
689 /// 返回 `Result<Vec<u8>, TtsError>`,成功时包含音频数据的字节向量,
690 /// 失败时返回相应的错误信息。
691 ///
692 /// # 错误处理
693 ///
694 /// 可能的错误包括:
695 /// - `TtsError::NotImplemented`: 功能未实现
696 /// - `TtsError::ConfigError`: 配置错误
697 /// - `TtsError::AudioGenerationError`: 音频生成失败
698 /// - `TtsError::EngineExecutionError`: 引擎执行失败
699 ///
700 /// # 示例
701 ///
702 /// ```rust
703 /// # use rs_voice_toolkit_tts::{TtsEngine, TtsError};
704 /// # struct MockEngine;
705 /// # #[async_trait::async_trait]
706 /// # impl TtsEngine for MockEngine {
707 /// async fn synthesize(&self, text: &str) -> Result<Vec<u8>, TtsError> {
708 /// if text.is_empty() {
709 /// return Err(TtsError::AudioGenerationError("文本不能为空".to_string()));
710 /// }
711 ///
712 /// // 模拟音频数据生成
713 /// let audio_data = vec![0u8; 1024]; // 实际应用中这里是真实的音频数据
714 /// Ok(audio_data)
715 /// }
716 /// # fn supported_languages(&self) -> Vec<String> { vec![] }
717 /// # fn engine_type(&self) -> rs_voice_toolkit_tts::TtsEngineType { unimplemented!() }
718 /// # async fn is_available(&self) -> bool { true }
719 /// # async fn synthesize_to_file(&self, _: &str, _: &std::path::Path) -> Result<(), TtsError> { Ok(()) }
720 /// # }
721 /// ```
722 ///
723 /// # 性能提示
724 ///
725 /// - 对于长文本,考虑分段处理以避免内存问题
726 /// - 多次调用此方法时,保持引擎实例以减少初始化开销
727 /// - 返回的音频数据应该及时处理或保存,避免内存泄漏
728 async fn synthesize(&self, text: &str) -> Result<Vec<u8>, TtsError>;
729
730 /// 将文本转换为语音并保存到文件
731 ///
732 /// 这个方法将文本转换为语音并直接保存到指定文件路径。
733 /// 这是 `synthesize()` 方法的便捷版本,避免在内存中保存大型音频文件。
734 ///
735 /// # 参数
736 ///
737 /// - `text`: 要合成的文本内容
738 /// - `output_path`: 输出文件的路径
739 ///
740 /// # 返回值
741 ///
742 /// 返回 `Result<(), TtsError>`,成功时表示文件保存成功,
743 /// 失败时返回相应的错误信息。
744 ///
745 /// # 错误处理
746 ///
747 /// 除了 `synthesize()` 方法可能返回的错误外,还可能包括:
748 /// - 文件系统相关的错误(通过 `TtsError::AudioGenerationError` 传递)
749 /// - 磁盘空间不足等IO错误
750 ///
751 /// # 示例
752 ///
753 /// ```rust
754 /// use rs_voice_toolkit_tts::{TtsEngine, TtsError};
755 /// use std::path::Path;
756 ///
757 /// # struct MockEngine;
758 /// # #[async_trait::async_trait]
759 /// # impl TtsEngine for MockEngine {
760 /// async fn synthesize_to_file(&self, text: &str, output_path: &Path) -> Result<(), TtsError> {
761 /// let audio_data = self.synthesize(text).await?;
762 /// std::fs::write(output_path, audio_data)
763 /// .map_err(|e| TtsError::AudioGenerationError(
764 /// format!("保存文件失败: {}", e)
765 /// ))?;
766 /// Ok(())
767 /// }
768 /// # fn supported_languages(&self) -> Vec<String> { vec![] }
769 /// # fn engine_type(&self) -> rs_voice_toolkit_tts::TtsEngineType { unimplemented!() }
770 /// # async fn is_available(&self) -> bool { true }
771 /// # async fn synthesize(&self, _: &str) -> Result<Vec<u8>, TtsError> { Ok(vec![]) }
772 /// # }
773 /// ```
774 ///
775 /// # 使用建议
776 ///
777 /// - 对于大型音频文件,建议使用此方法而不是 `synthesize()`
778 /// - 确保输出目录存在且有写权限
779 /// - 考虑文件命名冲突问题
780 async fn synthesize_to_file(&self, text: &str, output_path: &Path) -> Result<(), TtsError>;
781
782 /// 检查引擎是否可用
783 ///
784 /// 这个方法快速检查TTS引擎是否可用。应该在执行语音合成前调用此方法,
785 /// 以避免在引擎不可用时浪费时间。
786 ///
787 /// # 返回值
788 ///
789 /// 返回 `bool` 值:
790 /// - `true`: 引擎可用,可以正常进行语音合成
791 /// - `false`: 引擎不可用,需要检查安装或配置
792 ///
793 /// # 检查内容
794 ///
795 /// 具体的检查内容取决于引擎实现,通常包括:
796 /// - 可执行文件是否存在
797 /// - 依赖库是否完整
798 /// - 配置文件是否正确
799 /// - 权限是否足够
800 ///
801 /// # 示例
802 ///
803 /// ```rust
804 /// use rs_voice_toolkit_tts::{TtsEngine, TtsError};
805 ///
806 /// # struct MockEngine;
807 /// # #[async_trait::async_trait]
808 /// # impl TtsEngine for MockEngine {
809 /// async fn is_available(&self) -> bool {
810 /// // 检查可执行文件是否存在
811 /// std::path::Path::new("/usr/local/bin/index-tts").exists()
812 /// }
813 /// # fn supported_languages(&self) -> Vec<String> { vec![] }
814 /// # fn engine_type(&self) -> rs_voice_toolkit_tts::TtsEngineType { unimplemented!() }
815 /// # async fn synthesize(&self, _: &str) -> Result<Vec<u8>, TtsError> { Ok(vec![]) }
816 /// # async fn synthesize_to_file(&self, _: &str, _: &std::path::Path) -> Result<(), TtsError> { Ok(()) }
817 /// # }
818 /// ```
819 ///
820 /// # 性能考虑
821 ///
822 /// - 这个方法应该快速返回,避免昂贵的检查操作
823 /// - 可以缓存检查结果,避免重复的系统调用
824 /// - 考虑添加异步版本的检查以提高响应性
825 async fn is_available(&self) -> bool;
826
827 /// 获取支持的语言列表
828 ///
829 /// 返回该TTS引擎支持的语言代码列表。用户可以根据这个列表
830 /// 选择合适的语言进行语音合成。
831 ///
832 /// # 返回值
833 ///
834 /// 返回 `Vec<String>`,包含支持的语言代码。常见的语言代码包括:
835 /// - `"zh"`: 中文
836 /// - `"en"`: 英文
837 /// - `"ja"`: 日文
838 /// - `"ko"`: 韩文
839 /// - 等等
840 ///
841 /// # 示例
842 ///
843 /// ```rust
844 /// use rs_voice_toolkit_tts::{TtsEngine, TtsEngineType};
845 ///
846 /// # struct MockEngine;
847 /// # #[async_trait::async_trait]
848 /// # impl TtsEngine for MockEngine {
849 /// fn supported_languages(&self) -> Vec<String> {
850 /// vec![
851 /// "zh".to_string(),
852 /// "en".to_string(),
853 /// "auto".to_string(),
854 /// ]
855 /// }
856 /// # fn engine_type(&self) -> rs_voice_toolkit_tts::TtsEngineType { unimplemented!() }
857 /// # async fn is_available(&self) -> bool { true }
858 /// # async fn synthesize(&self, _: &str) -> Result<Vec<u8>, TtsError> { Ok(vec![]) }
859 /// # async fn synthesize_to_file(&self, _: &str, _: &std::path::Path) -> Result<(), TtsError> { Ok(()) }
860 /// # }
861 /// ```
862 ///
863 /// # 使用建议
864 ///
865 /// - 在选择语言前调用此方法检查支持情况
866 /// - 可以在应用启动时缓存此结果
867 /// - 考虑将此信息展示给用户供选择
868 fn supported_languages(&self) -> Vec<String>;
869
870 /// 获取引擎类型
871 ///
872 /// 返回该TTS引擎的类型标识。这个标识可以帮助用户了解当前使用的引擎,
873 /// 并在需要时进行引擎特定的配置或处理。
874 ///
875 /// # 返回值
876 ///
877 /// 返回 `TtsEngineType` 枚举值:
878 /// - `TtsEngineType::IndexTts`: Index-TTS引擎
879 /// - `TtsEngineType::Piper`: Piper引擎(未来支持)
880 /// - `TtsEngineType::Coqui`: Coqui引擎(未来支持)
881 ///
882 /// # 示例
883 ///
884 /// ```rust
885 /// use rs_voice_toolkit_tts::{TtsEngine, TtsEngineType};
886 ///
887 /// # struct MockEngine;
888 /// # #[async_trait::async_trait]
889 /// # impl TtsEngine for MockEngine {
890 /// fn engine_type(&self) -> TtsEngineType {
891 /// TtsEngineType::IndexTts
892 /// }
893 /// # fn supported_languages(&self) -> Vec<String> { vec![] }
894 /// # async fn is_available(&self) -> bool { true }
895 /// # async fn synthesize(&self, _: &str) -> Result<Vec<u8>, TtsError> { Ok(vec![]) }
896 /// # async fn synthesize_to_file(&self, _: &str, _: &std::path::Path) -> Result<(), TtsError> { Ok(()) }
897 /// # }
898 /// ```
899 ///
900 /// # 使用场景
901 ///
902 /// - 引擎特定的配置和优化
903 /// - 日志记录和调试信息
904 /// - 用户界面显示当前引擎
905 /// - 引擎切换和兼容性检查
906 fn engine_type(&self) -> TtsEngineType;
907}
908
909/// Index-TTS 引擎
910///
911/// 这是Index-TTS引擎的具体实现,提供了完整的文本转语音功能。
912/// Index-TTS是一个高质量的语音合成引擎,支持多种语言和灵活的配置选项。
913///
914/// # 主要特性
915///
916/// - **多语言支持**: 支持中文、英文等多种语言
917/// - **高质量合成**: 提供自然流畅的语音输出
918/// - **灵活配置**: 支持语言、说话人、采样率等多种参数配置
919/// - **异步处理**: 完全异步的API设计
920/// - **多种输出**: 支持内存输出和文件输出
921///
922/// # 使用示例
923///
924/// ## 基本使用
925///
926/// ```rust
927/// use rs_voice_toolkit_tts::{IndexTtsEngine, TtsConfig};
928///
929/// #[tokio::main]
930/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
931/// // 创建配置和引擎
932/// let config = TtsConfig::default();
933/// let engine = IndexTtsEngine::new(config);
934///
935/// // 检查引擎可用性
936/// if !engine.is_available().await {
937/// println!("Index-TTS 引擎不可用");
938/// return Ok(());
939/// }
940///
941/// // 文本转语音
942/// let text = "你好,世界!";
943/// let audio_data = engine.synthesize(text).await?;
944/// println!("生成音频数据大小: {} 字节", audio_data.len());
945///
946/// Ok(())
947/// }
948/// ```
949///
950/// ## 文件输出
951///
952/// ```rust
953/// use rs_voice_toolkit_tts::{IndexTtsEngine, TtsConfig};
954/// use std::path::Path;
955///
956/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
957/// let config = TtsConfig {
958/// language: Some("zh".to_string()),
959/// sample_rate: 22050,
960/// ..TtsConfig::default()
961/// };
962/// let engine = IndexTtsEngine::new(config);
963///
964/// let text = "这是保存到文件的语音合成示例。";
965/// let output_path = Path::new("output.wav");
966///
967/// engine.synthesize_to_file(text, output_path).await?;
968/// println!("语音已保存到: {:?}", output_path);
969/// # Ok(())
970/// # }
971/// ```
972///
973/// # 引擎要求
974///
975/// ## 系统要求
976/// - **操作系统**: Linux、macOS、Windows
977/// - **内存**: 至少100MB可用内存
978/// - **CPU**: 支持多线程处理
979/// - **磁盘**: 足够的临时文件空间
980///
981/// ## 软件依赖
982/// - **index-tts**: Index-TTS可执行文件
983/// - **which**: 用于查找可执行文件(可选)
984///
985/// ## 安装Index-TTS
986///
987/// 通常需要从Index-TTS的官方仓库下载可执行文件,
988/// 或通过包管理器安装:
989///
990/// ```bash
991/// # 示例安装命令(具体命令取决于发行版)
992/// wget https://github.com/open-mmlab/Index-TTS/releases/download/v1.0/index-tts
993/// chmod +x index-tts
994/// sudo mv index-tts /usr/local/bin/
995/// ```
996///
997/// # 性能优化
998///
999/// ## 引擎初始化
1000/// - 保持引擎实例,避免重复创建
1001/// - 预检查引擎可用性,避免运行时错误
1002///
1003/// ## 内存管理
1004/// - 对于大型音频文件,优先使用文件输出
1005/// - 及时处理或保存生成的音频数据
1006///
1007/// ## 并发处理
1008/// - 利用异步特性进行并发处理
1009/// - 注意引擎的并发限制
1010///
1011/// # 错误处理
1012///
1013/// 引擎可能返回的错误类型:
1014/// - `TtsError::ConfigError`: 配置错误
1015/// - `TtsError::AudioGenerationError`: 音频生成失败
1016/// - `TtsError::EngineExecutionError`: 引擎执行失败
1017///
1018/// # 注意事项
1019///
1020/// - 首次使用前确保Index-TTS已正确安装
1021/// - 长文本建议分段处理以避免内存问题
1022/// - 建议在使用前检查引擎可用性
1023/// - 注意生成的音频文件的版权问题
1024#[derive(Debug, Clone)]
1025pub struct IndexTtsEngine {
1026 /// TTS配置
1027 ///
1028 /// 存储引擎的配置参数,包括语言、说话人、采样率等设置。
1029 /// 这些配置会在语音合成时传递给Index-TTS引擎。
1030 cfg: TtsConfig,
1031}
1032
1033impl IndexTtsEngine {
1034 pub fn new(cfg: TtsConfig) -> Self {
1035 Self { cfg }
1036 }
1037
1038 pub async fn is_available(&self) -> bool {
1039 if let Some(path) = &self.cfg.executable_path {
1040 return path.exists();
1041 }
1042 which::which("index-tts").is_ok()
1043 }
1044
1045 async fn resolve_executable(&self) -> Result<PathBuf, TtsError> {
1046 if let Some(path) = &self.cfg.executable_path {
1047 return Ok(path.clone());
1048 }
1049 which::which("index-tts").map_err(|_| {
1050 TtsError::ConfigError(
1051 "找不到 index-tts 可执行文件,请设置 PATH 或配置 executable_path".into(),
1052 )
1053 })
1054 }
1055
1056 pub async fn synthesize_to_memory(&self, text: &str) -> Result<Vec<u8>, TtsError> {
1057 let exe = self.resolve_executable().await?;
1058 let mut args: Vec<String> = Vec::new();
1059 args.push("--text".into());
1060 args.push(text.into());
1061 if let Some(lang) = &self.cfg.language {
1062 args.push("--language".into());
1063 args.push(lang.clone());
1064 }
1065 if let Some(speaker) = &self.cfg.speaker {
1066 args.push("--speaker".into());
1067 args.push(speaker.clone());
1068 }
1069 args.push("--sample-rate".into());
1070 args.push(self.cfg.sample_rate.to_string());
1071 args.push("--output-format".into());
1072 args.push("wav".into());
1073 // 假设 index-tts 支持 stdout 输出;若不支持,需落盘再读出
1074 let output = Command::new(exe)
1075 .args(&args)
1076 .output()
1077 .await
1078 .map_err(|e| TtsError::EngineExecutionError(format!("执行失败: {e}")))?;
1079 if !output.status.success() {
1080 return Err(TtsError::EngineExecutionError(
1081 String::from_utf8_lossy(&output.stderr).to_string(),
1082 ));
1083 }
1084 Ok(output.stdout)
1085 }
1086
1087 pub async fn synthesize_to_file<P: AsRef<Path>>(
1088 &self,
1089 text: &str,
1090 output_path: P,
1091 ) -> Result<(), TtsError> {
1092 let exe = self.resolve_executable().await?;
1093 let mut args: Vec<String> = Vec::new();
1094 args.push("--text".into());
1095 args.push(text.into());
1096 if let Some(lang) = &self.cfg.language {
1097 args.push("--language".into());
1098 args.push(lang.clone());
1099 }
1100 if let Some(speaker) = &self.cfg.speaker {
1101 args.push("--speaker".into());
1102 args.push(speaker.clone());
1103 }
1104 args.push("--sample-rate".into());
1105 args.push(self.cfg.sample_rate.to_string());
1106 args.push("--output".into());
1107 args.push(output_path.as_ref().to_string_lossy().to_string());
1108 args.push("--output-format".into());
1109 args.push("wav".into());
1110 let status = Command::new(exe)
1111 .args(&args)
1112 .status()
1113 .await
1114 .map_err(|e| TtsError::EngineExecutionError(format!("执行失败: {e}")))?;
1115 if !status.success() {
1116 return Err(TtsError::EngineExecutionError(format!(
1117 "Index-TTS 退出状态异常: {:?}",
1118 status.code()
1119 )));
1120 }
1121 Ok(())
1122 }
1123}
1124
1125#[async_trait::async_trait]
1126impl TtsEngine for IndexTtsEngine {
1127 async fn synthesize(&self, text: &str) -> Result<Vec<u8>, TtsError> {
1128 self.synthesize_to_memory(text).await
1129 }
1130
1131 async fn synthesize_to_file(&self, text: &str, output_path: &Path) -> Result<(), TtsError> {
1132 self.synthesize_to_file(text, output_path).await
1133 }
1134
1135 async fn is_available(&self) -> bool {
1136 self.is_available().await
1137 }
1138
1139 fn supported_languages(&self) -> Vec<String> {
1140 vec!["zh".into(), "en".into(), "auto".into()]
1141 }
1142
1143 fn engine_type(&self) -> TtsEngineType {
1144 TtsEngineType::IndexTts
1145 }
1146}
1147
1148/// TTS服务
1149///
1150/// 这是TTS模块的主要服务类,提供了高级的文本转语音功能。
1151/// 它封装了具体的TTS引擎实现,为用户提供统一和便捷的API。
1152///
1153/// # 主要功能
1154///
1155/// - **统一接口**: 提供一致的API,隐藏底层引擎的复杂性
1156/// - **引擎管理**: 自动管理TTS引擎的创建和配置
1157/// - **错误处理**: 提供统一的错误处理机制
1158/// - **异步支持**: 完全异步的API设计,适合高并发场景
1159/// - **灵活配置**: 支持多种配置选项和引擎选择
1160///
1161/// # 使用示例
1162///
1163/// ## 基本使用
1164///
1165/// ```rust
1166/// use rs_voice_toolkit_tts::{TtsService, TtsConfig};
1167///
1168/// #[tokio::main]
1169/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
1170/// // 创建TTS服务
1171/// let config = TtsConfig::default();
1172/// let service = TtsService::new(config);
1173///
1174/// // 检查服务可用性
1175/// if !service.is_available().await {
1176/// println!("TTS服务不可用");
1177/// return Ok(());
1178/// }
1179///
1180/// // 文本转语音(内存输出)
1181/// let text = "你好,世界!欢迎使用语音工具库。";
1182/// let audio_data = service.text_to_speech(text).await?;
1183/// println!("生成音频数据大小: {} 字节", audio_data.len());
1184///
1185/// // 文本转语音(文件输出)
1186/// let output_path = "output/hello.wav";
1187/// service.text_to_file(text, output_path).await?;
1188/// println!("语音已保存到: {}", output_path);
1189///
1190/// Ok(())
1191/// }
1192/// ```
1193///
1194/// ## 自定义配置
1195///
1196/// ```rust
1197/// use rs_voice_toolkit_tts::{TtsService, TtsConfig, TtsEngineType};
1198///
1199/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1200/// // 创建自定义配置
1201/// let config = TtsConfig {
1202/// language: Some("zh".to_string()),
1203/// speaker: Some("female".to_string()),
1204/// sample_rate: 22050,
1205/// speed: 1.2,
1206/// pitch: 0.0,
1207/// executable_path: None,
1208/// };
1209///
1210/// // 使用自定义引擎创建服务
1211/// let service = TtsService::new_with_engine(config, TtsEngineType::IndexTts);
1212///
1213/// let text = "这是使用自定义配置生成的语音。";
1214/// let audio_data = service.text_to_speech(text).await?;
1215/// # Ok(())
1216/// # }
1217/// ```
1218///
1219/// ## 批量处理
1220///
1221/// ```rust
1222/// use rs_voice_toolkit_tts::{TtsService, TtsConfig};
1223///
1224/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
1225/// let service = TtsService::new(TtsConfig::default());
1226///
1227/// // 批量处理多个文本
1228/// let texts = vec![
1229/// "第一段文本内容。",
1230/// "第二段文本内容。",
1231/// "第三段文本内容。",
1232/// ];
1233///
1234/// for (i, text) in texts.iter().enumerate() {
1235/// let output_path = format!("output/speech_{}.wav", i + 1);
1236///
1237/// match service.text_to_file(text, &output_path).await {
1238/// Ok(_) => println!("✓ 成功生成: {}", output_path),
1239/// Err(e) => println!("✗ 生成失败: {} - {}", text, e),
1240/// }
1241/// }
1242/// # Ok(())
1243/// # }
1244/// ```
1245///
1246/// # 服务生命周期
1247///
1248/// ## 创建
1249/// - 通过 `TtsService::new()` 创建使用默认引擎的服务
1250/// - 通过 `TtsService::new_with_engine()` 创建使用指定引擎的服务
1251///
1252/// ## 使用
1253/// - 调用 `text_to_speech()` 进行内存输出
1254/// - 调用 `text_to_file()` 进行文件输出
1255/// - 调用 `is_available()` 检查服务可用性
1256///
1257/// ## 销毁
1258/// - 服务实例会在超出作用域时自动销毁
1259/// - 建议在应用生命周期内保持服务实例
1260///
1261/// # 性能优化
1262///
1263/// ## 实例管理
1264/// - 避免频繁创建和销毁服务实例
1265/// - 在应用启动时创建服务,全程复用
1266///
1267/// ## 并发处理
1268/// - 服务实例是线程安全的,可以并发使用
1269/// - 注意底层引擎的并发限制
1270///
1271/// ## 资源管理
1272/// - 及时处理大型音频数据,避免内存泄漏
1273/// - 优先使用文件输出处理大型音频
1274///
1275/// # 错误处理
1276///
1277/// 服务会将底层引擎的错误转换为统一的错误类型:
1278/// - `TtsError::NotImplemented`: 功能未实现
1279/// - `TtsError::ConfigError`: 配置错误
1280/// - `TtsError::AudioGenerationError`: 音频生成失败
1281/// - `TtsError::EngineExecutionError`: 引擎执行失败
1282///
1283/// # 注意事项
1284///
1285/// - 首次使用前确保相应的TTS引擎已正确安装
1286/// - 建议在使用前检查服务可用性
1287/// - 长文本建议分段处理以避免内存问题
1288/// - 注意生成的音频文件的版权问题
1289pub struct TtsService {
1290 /// TTS配置
1291 ///
1292 /// 存储服务的配置参数,这些参数会在创建引擎时使用。
1293 /// 配置包括语言、说话人、采样率等设置。
1294 #[allow(dead_code)]
1295 config: TtsConfig,
1296
1297 /// TTS引擎实例
1298 ///
1299 /// 实际的TTS引擎实现,负责具体的语音合成工作。
1300 /// 使用trait对象以支持多种引擎实现。
1301 engine: Box<dyn TtsEngine + Send + Sync>,
1302}
1303
1304impl TtsService {
1305 /// 创建新的TTS服务
1306 pub fn new(config: TtsConfig) -> Self {
1307 Self::new_with_engine(config, TtsEngineType::default())
1308 }
1309
1310 /// 使用指定引擎创建TTS服务
1311 pub fn new_with_engine(config: TtsConfig, engine_type: TtsEngineType) -> Self {
1312 let engine = Self::create_engine(config.clone(), engine_type);
1313 Self { config, engine }
1314 }
1315
1316 /// 创建指定类型的引擎
1317 fn create_engine(config: TtsConfig, engine_type: TtsEngineType) -> Box<dyn TtsEngine + Send + Sync> {
1318 match engine_type {
1319 TtsEngineType::IndexTts => Box::new(IndexTtsEngine::new(config)),
1320 TtsEngineType::Piper => {
1321 // 未来实现
1322 panic!("Piper 引擎尚未实现")
1323 }
1324 TtsEngineType::Coqui => {
1325 // 未来实现
1326 panic!("Coqui 引擎尚未实现")
1327 }
1328 }
1329 }
1330
1331 /// 文本转语音(内存)
1332 pub async fn text_to_speech(&self, text: &str) -> Result<Vec<u8>, TtsError> {
1333 self.engine.synthesize(text).await
1334 }
1335
1336 /// 文本转语音并保存到文件
1337 pub async fn text_to_file<P: AsRef<Path>>(
1338 &self,
1339 text: &str,
1340 output: P,
1341 ) -> Result<(), TtsError> {
1342 self.engine.synthesize_to_file(text, output.as_ref()).await
1343 }
1344
1345 /// 引擎可用性
1346 pub async fn is_available(&self) -> bool {
1347 self.engine.is_available().await
1348 }
1349}
1350
1351#[cfg(test)]
1352mod tests {
1353 use super::*;
1354
1355 #[tokio::test]
1356 async fn test_tts_service_creation() {
1357 let config = TtsConfig::default();
1358 let service = TtsService::new(config);
1359
1360 // 可用性检测(不保证 index-tts 存在,仅验证 API 不 panic)
1361 let _ = service.text_to_speech("你好").await.err();
1362 }
1363}