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}