【迭代】:本地高性能c++对话系统e2e_voice
开源语音对话系统更新:新增英文Matcha-TTS支持与远场VAD优化
项目简介
最近我对开源的端到端C++语音对话系统进行了两个重要更新:
- 远场VAD支持优化 - 提升远距离语音检测能力
- 英文Matcha-TTS集成 - 新增高质量英文文本转语音功能
项目地址:https://github.com/muggle-stack/e2e_voice
主要更新内容
1. 远场VAD增强
- VAD缓冲区放大100倍,显著提升远场语音检测灵敏度
- 支持双声道音频采样,智能混合左右声道提升音频质量
- 自适应放大算法,根据信号强度动态调整检测参数
- 适用于会议室、教室等大空间环境的语音交互
2. 英文Matcha-TTS支持
- 集成英文Matcha-TTS模型,支持高质量英文语音合成
- 依赖espeak-ng进行英文文本到音素转换
- 自动模型下载管理,首次使用时按语言类型下载对应模型
- 与中文TTS共享Vocos声码器,优化存储空间
如何使用英文TTS
系统要求
确保已安装espeak-ng(英文TTS必需):
# Ubuntu/Debian
sudo apt install espeak-ng# macOS 安装 espeak 或者 espeak-ng
brew install espeak
编译项目
git clone https://github.com/muggle-stack/e2e_voice.git
cd e2e_voice
./build.sh
使用方法
1. 完整对话系统(支持语言切换)
# 使用中文TTS
./build/bin/asr_llm_tts --tts_type zh# 使用英文TTS
./build/bin/asr_llm_tts --tts_type en
2. 独立TTS工具
# 中文语音合成
./build/bin/tts --text "你好世界" --tts_type zh --save_audio_path chinese.wav# 英文语音合成
./build/bin/tts --text "Hello World" --tts_type en --save_audio_path english.wav
3. 核心代码实现:多语言TTS适配
1. 头文件中添加语言特定常量定义
在 include/tts/tts_model_downloader.hpp
中:
class TTSModelDownloader {
public:// 模型文件路径常量static constexpr const char* MATCHA_ZH_MODEL = "matcha-icefall-zh-baker/model-steps-3.onnx";static constexpr const char* MATCHA_ZH_LEXICON = "matcha-icefall-zh-baker/lexicon.txt";static constexpr const char* MATCHA_ZH_TOKENS = "matcha-icefall-zh-baker/tokens.txt";static constexpr const char* MATCHA_ZH_DICT_DIR = "matcha-icefall-zh-baker/dict";static constexpr const char* MATCHA_EN_MODEL = "matcha-icefall-en_US-ljspeech/model-steps-3.onnx";static constexpr const char* MATCHA_EN_TOKENS = "matcha-icefall-en_US-ljspeech/tokens.txt";static constexpr const char* MATCHA_EN_DATA_DIR = "matcha-icefall-en_US-ljspeech/espeak-ng-data";static constexpr const char* VOCOS_VOCODER = "vocos-22khz-univ.onnx";// 新增语言特定的模型检查方法bool ensureModelsExist(const std::string& language);
};
2. 语言特定的模型下载实现
在 src/tts/tts_model_downloader.cpp
中添加:
bool TTSModelDownloader::ensureModelsExist(const std::string& language) {if (!ensureCacheDir()) {return false;}// 首先确保声码器存在(所有语言共享)std::string vocoder_path = getModelPath(VOCOS_VOCODER);if (!fs::exists(vocoder_path)) {if (!downloadVocoder()) {std::cerr << "Failed to download vocoder" << std::endl;return false;}}// 检查语言特定模型if (language == "zh") {std::string model_path = getModelPath(MATCHA_ZH_MODEL);std::string lexicon_path = getModelPath(MATCHA_ZH_LEXICON);std::string tokens_path = getModelPath(MATCHA_ZH_TOKENS);std::string dict_path = getModelPath(MATCHA_ZH_DICT_DIR);if (!fs::exists(model_path) || !fs::exists(lexicon_path) || !fs::exists(tokens_path) || !fs::exists(dict_path)) {if (!downloadLanguageModel("zh")) {return false;}}} else if (language == "en") {std::string model_path = getModelPath(MATCHA_EN_MODEL);std::string tokens_path = getModelPath(MATCHA_EN_TOKENS);std::string data_dir = getModelPath(MATCHA_EN_DATA_DIR);if (!fs::exists(model_path) || !fs::exists(tokens_path) || !fs::exists(data_dir)) {if (!downloadLanguageModel("en")) {return false;}}} else {std::cerr << "Unsupported language: " << language << std::endl;return false;}std::cout << "All TTS models for " << language << " are ready!" << std::endl;return true;
}
3. 应用程序中的语言适配逻辑
在 src/main_asr_llm_tts.cpp
和 src/main_asr_llm_tts_api.cpp
中:
// TTS配置根据语言类型动态设置
if (params_.tts_type == "zh") {// 中文TTS配置tts_config.acoustic_model_path = tts_downloader.getModelPath(tts::TTSModelDownloader::MATCHA_ZH_MODEL);tts_config.vocoder_path = tts_downloader.getModelPath(tts::TTSModelDownloader::VOCOS_VOCODER);tts_config.lexicon_path = tts_downloader.getModelPath(tts::TTSModelDownloader::MATCHA_ZH_LEXICON);tts_config.tokens_path = tts_downloader.getModelPath(tts::TTSModelDownloader::MATCHA_ZH_TOKENS);tts_config.data_dir = tts_downloader.getModelPath(tts::TTSModelDownloader::MATCHA_ZH_DICT_DIR);tts_config.language = "zh";
} else if (params_.tts_type == "en") {// 英文TTS配置tts_config.acoustic_model_path = tts_downloader.getModelPath(tts::TTSModelDownloader::MATCHA_EN_MODEL);tts_config.vocoder_path = tts_downloader.getModelPath(tts::TTSModelDownloader::VOCOS_VOCODER);tts_config.tokens_path = tts_downloader.getModelPath(tts::TTSModelDownloader::MATCHA_EN_TOKENS);tts_config.data_dir = tts_downloader.getModelPath(tts::TTSModelDownloader::MATCHA_EN_DATA_DIR);tts_config.language = "en";
}// 调用语言特定的模型确保方法
if (!tts_downloader.ensureModelsExist(params_.tts_type)) {std::cerr << "Failed to ensure TTS models exist" << std::endl;return false;
}
4. 参数结构体更新
在参数结构体中添加TTS语言类型字段:
struct Params {// 其他参数...std::string tts_type; // TTS语言类型Params() :// 其他默认值...tts_type("zh") {} // 默认中文
};
这种设计保持了原有接口的兼容性,同时支持了多语言扩展。
模型文件结构
更新后的模型文件组织更加清晰:
~/.cache/matcha-tts/
├── vocos-22khz-univ.onnx # 共享声码器
├── matcha-icefall-zh-baker/ # 中文TTS模型
│ ├── model-steps-3.onnx
│ ├── lexicon.txt
│ ├── tokens.txt
│ └── dict/
└── matcha-icefall-en_US-ljspeech/ # 英文TTS模型├── model-steps-3.onnx├── tokens.txt└── espeak-ng-data/
核心技术特性
智能模型管理
- 首次运行时根据选择的语言类型自动下载对应模型
- 中文和英文模型分别存储,按需下载节省存储空间
- 声码器在两种语言间共享,提高资源利用效率
远场录音优化
- 支持双声道录音:
--channels 2
- 远场VAD增强自动启用,提升大空间环境下的语音检测能力
- 智能信号放大,根据距离动态调整检测灵敏度
从单语言到双语言的升级
如果您之前使用的是只支持中文的版本,升级非常简单:
- 拉取最新代码
git pull origin master
./build.sh
- 清理旧模型(可选)
rm -rf ~/.cache/matcha-tts/
- 选择语言运行
# 自动下载中文模型
./build/bin/asr_llm_tts --tts_type zh# 自动下载英文模型
./build/bin/asr_llm_tts --tts_type en
配置参数说明
新增的主要参数:
参数 | 说明 | 默认值 | 示例 |
---|---|---|---|
--tts_type | TTS语言类型 | zh | en |
--channels | 音频通道数 | 1 | 2 |
实际效果展示
远场录音测试
- 测试环境:5米距离,会议室环境
- 传统VAD:检测成功率约60%
- 增强VAD:检测成功率提升至85%+
英文TTS质量
- 发音准确性:基于espeak-ng的IPA音素,发音标准
- 音质表现:与中文TTS相当的自然度
- 响应速度:合成速度0.9x实时,满足实时对话需求
使用建议
故障排查
- 英文TTS无声音:检查是否安装espeak-ng
- 模型下载失败:检查网络连接,可手动下载模型文件
- 远场检测不灵敏:尝试使用双声道录音
--channels 2
后续计划
- 支持更多语言(德语、法语等)
- 添加三通道回采,双mic以上降噪、声纹、声源等
- 优化模型推理速度
- 添加语音情感控制
- 实现实时语音克隆
联系方式
- GitHub: muggle-stack
- 项目地址: e2e_voice
- 邮箱: promuggle@gmail.com
如果觉得这个项目对您有帮助,请给个⭐Star支持一下!
欢迎提交Issue和PR,一起完善这个开源语音对话系统!
开源许可:个人学习研究免费使用,商业用途需要许可