文字转语音——sherpa-onnx语音识别离线部署C++实现
目的:
C++项目中接入Sherpa-onnx实现文字转语音功能
开发环境
Windows、VS2022
步骤:
1.创建C++空项目,位置放到合适的地方即可。
2.下载Sherpa-onnx动态库。
选择动态库是因为能够避免一些配置上的bug。
方法一:
库文件地址:https://huggingface.co/csukuangfj/sherpa-onnx-libs/tree/main 里边有各个平台的库文件,选择最新版本的window 64bit shared下载。
方法二:
git地址:https://github.com/makdi76/sherpa-onnx
sherpa-onnx教程地址:sherpa-onnx — sherpa 1.3 documentation。如下图:
点击后进入
进入后点击Installation——>Windows 64bit Windows(x64)
进入后是一下界面,选择64-bit Windows(shared lib),点击下载
3.导入动态库
创建third_party文件夹,将上一步下载的压缩包解压到third_party文件夹。
创建models文件夹,用来放模型文件,暂时先不管
解压缩后目录如下图:
4.动态库设置
打开解决方案窗口,右击项目名“Sherpa_onnx” ——> 点击“属性”
打开界面:
修改内容:
1.C++标准改为 17,如图:
2.配置属性 → VC++目录 → 包含目录:添加目录
E:\\VS\\Sherpa_onnx\\third_party\\sherpa-onnx-v1.11.2-win-x64-shared\\include
E:\\VS\\Sherpa_onnx\\third_party\\sherpa-onnx-v1.11.2-win-x64-shared\\include\\sherpa-onnx\\c-api
自己添加的时候把目录替换成自己工程的,主要是添加动态库的include和c-api这两个文件夹路径
3.链接器 → 常规 → 附加库目录:添加
E:\\VS\\Sherpa_onnx\\third_party\\sherpa-onnx-v1.11.2-win-x64-shared\\lib
替换成自己的解压的动态库 lib 文件夹路径
3.链接器 → 输入 → 附加依赖项:添加
cargs.lib
sherpa-onnx-c-api.lib
sherpa-onnx-cxx-api.lib
5.下载语言模型
从下边地址能找到预训练模型,我工程里用了kokoro-multi-lang-v1_0和vits-melo-tts-zh_en模型做测试。下载模型后解压到工程目录的models文件夹下。(models是在步骤3导入动态库的时候一并创建的)
模型地址:RTF of pre-trained models — sherpa 1.3 documentationhttps://k2-fsa.github.io/sherpa/onnx/tts/pretrained_models/rtf.html
点击上图对应的模型回跳转到教程中对应模型的位置,由对应模型的下载地址,直接复制下载即可。地址位置如下图:
6.创建Main.cpp
在解决方案中:右击 源文件→添加→新建项→改文件名
7.写代码
代码可以查看sherp-onnx中的C++示例代码,下边是根据示例代码写的Kokoro模型和Vits模型。
在Main方法中调用对应方法即可生成对应的音频文件。
#include #include #include #include #include int CheckModelFile(std::string model_path) { std::filesystem::path path(model_path); if (std::filesystem::exists(path)) { std::cout << \"Model file exists at: \" << model_path << std::endl; return 0; } else { std::cerr << \"Model file does not exist at: \" << model_path < faster in speech speed GeneratedAudio audio = tts.Generate(text, sid, speed);#if 0 // If you don\'t want to use a callback, then please enable this branch GeneratedAudio audio = tts.Generate(text, sid, speed);#else //GeneratedAudio audio = tts.Generate(text, sid, speed, ProgressCallback);#endif WriteWave(filename, { audio.samples, audio.sample_rate }); fprintf(stderr, \"Input text is: %s\\n\", text.c_str()); fprintf(stderr, \"Speaker ID is is: %d\\n\", sid); fprintf(stderr, \"Saved to: %s\\n\", filename.c_str()); return 0;}int Vits() { using namespace sherpa_onnx::cxx; OfflineTtsConfig config; config.model.vits.model = \"../models/vits-melo-tts-zh_en/model.onnx\"; config.model.vits.lexicon = \"../models/vits-melo-tts-zh_en/lexicon.txt\"; config.model.vits.tokens = \"../models/vits-melo-tts-zh_en/tokens.txt\"; config.model.vits.dict_dir = \"../models/vits-melo-tts-zh_en/dict\"; config.model.num_threads = 1; // 线程数 config.model.debug = 1; // 是否启用调试输出 //config.model.provider = \"cpu\"; // 使用CPU或CUDA CheckModelFile(config.model.vits.model); CheckModelFile(config.model.vits.lexicon); CheckModelFile(config.model.vits.tokens); CheckModelFile(config.model.vits.dict_dir); std::string filename = \"./generated-vits-zh-en-cxx.wav\"; std::string text = \"中英文语音合成测试。This is generated by next generation Kaldi using \" \"Kokoro without Misaki. 你觉得中英文说的如何呢?\"; auto tts = OfflineTts::Create(config); int32_t sid = 0; float speed = 1.0; // larger -> faster in speech speed GeneratedAudio audio = tts.Generate(text, sid, speed);#if 0 // If you don\'t want to use a callback, then please enable this branch GeneratedAudio audio = tts.Generate(text, sid, speed);#else //GeneratedAudio audio = tts.Generate(text, sid, speed, ProgressCallback);#endif WriteWave(filename, { audio.samples, audio.sample_rate }); fprintf(stderr, \"Input text is: %s\\n\", text.c_str()); fprintf(stderr, \"Speaker ID is is: %d\\n\", sid); fprintf(stderr, \"Saved to: %s\\n\", filename.c_str()); return 0;}int main() { return Kokoro();}
8.编译运行程序
运行程序 管理器配置 Release x64
可能报错:
1.sherpa_onnx.exe系统错误,找不到 ××××××.dll ,如下图:
解决方法: 将找不到的dll文件复制到sherpa_onnx.exe同级目录下。
sherpa-onnx-cxx-api.dll文件是我们的动态库文件,在项目内\\third_party\\sherpa-onnx-v1.11.2-win-x64-shared\\lib文件夹下。
sherpa_onnx.exe是生成的可执行文件,在项目内\\x64\\Release文件夹下。
复制后如图:
2.遇到下图 0x00007FFFDACF6F4E (sherpa-onnx-c-api.dll)处(位于 Sherpa_onnx.exe 中)引发的异常: 0xC0000005: 读取位置 0x0000000000000000 时发生访问冲突问题,需要结合控制台输出查看,分为两种情况。
第一种:动态链接库问题
下图控制台第一行:The given version [17] is not supported, only version 1 to 10 is supported in this build.
此信息是动态链接库版本不匹配 问题,是onnxruntime.dll 版本冲突系统中存在多个版本的 onnxruntime.dll
,程序运行时错误加载了低版本库(如系统目录 /Windows/System32
中的旧版本)。
解决方法:
把动态库文件目录(\\third_party\\sherpa-onnx-v1.11.2-win-x64-shared\\lib文件夹)下的onnxruntime_providers_shared.dll和onnxruntime.dll从动态库目录复制到sherpa_onnx.exe同级目录(\\x64\\Release)下。
第二种:代码中指定的模型地址不对
解决方法:
或
调用模型的地址修改为正确的路径地址即可。
(此处有点疑问:相对路径究竟是从哪开始的?
最初的工程配置的地址是正常运行了,但在写文章重新建工程时,原本的路径写法是第二张图的,运行报错。修改为第一种写法运行正常。
查问题是相对路径应该是相对于exe文件的,但是两个工程的相对路径的起始位置在变化,导致文件读取失败。)
9.生成音频文件
出现图中 Saved to: ./×××.wav 文件即成功生成
文件位置:
嗯嗯嗯。。 从此处文件生成位置来看,他的根目录位置是工程下的Sherpa_onnx文件夹。嗯。所以这个相对目录目前还比较迷。待之后再查查资料再看。
以上就是接入的全部内容。C++菜鸡,全流程靠ai和网上信息实现......