文字转语音——sherpa-onnx语音识别离线部署C++实现

原文:https://blog.csdn.net/huanrx/article/details/147047543

目的:

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导入动态库的时候一并创建的)

模型地址:

https://k2-fsa.github.io/sherpa/onnx/tts/pretrained_models/rtf.html

点击上图对应的模型回跳转到教程中对应模型的位置,由对应模型的下载地址,直接复制下载即可。地址位置如下图:

6.创建Main.cpp

在解决方案中:右击 源文件→添加→新建项→改文件名

7.写代码

代码可以查看sherp-onnx中的C++示例代码,下边是根据示例代码写的Kokoro模型和Vits模型。

在Main方法中调用对应方法即可生成对应的音频文件。

cpp 复制代码
#include <iostream>
#include <memory>
#include <c-api.h>
#include <cxx-api.h>
#include <filesystem>
 
 
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 << std::endl;
        return 1;
    }
}
 
int Kokoro() {
 
    using namespace sherpa_onnx::cxx;
    OfflineTtsConfig config;
 
    config.model.kokoro.model = "../models/kokoro-multi-lang-v1_0/model.onnx";
    config.model.kokoro.voices = "../models/kokoro-multi-lang-v1_0/voices.bin";
    config.model.kokoro.tokens = "../models/kokoro-multi-lang-v1_0/tokens.txt";
    config.model.kokoro.data_dir = "../models/kokoro-multi-lang-v1_0/espeak-ng-data";
    config.model.kokoro.dict_dir = "../models/kokoro-multi-lang-v1_0/dict";
    config.model.kokoro.lexicon =
        "../models/kokoro-multi-lang-v1_0/lexicon-us-en.txt,../models/kokoro-multi-lang-v1_0/lexicon-zh.txt";
 
    config.model.num_threads = 2;
    CheckModelFile(config.model.kokoro.model);
    CheckModelFile(config.model.kokoro.voices);
    CheckModelFile(config.model.kokoro.tokens);
    CheckModelFile(config.model.kokoro.data_dir);
    CheckModelFile(config.model.kokoro.dict_dir);
    // If you don't want to see debug messages, please set it to 0
    config.model.debug = 1;
 
    std::string filename = "./generated-kokoro-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 = 50;
    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 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和网上信息实现......

相关推荐
一点都不方女士2 小时前
.NET Framework 3.5官网下载与5种常见故障解决方法
c++·windows·framework·.net·动态链接库·运行库
semicolon_hello4 小时前
C++中 optional variant any 的使用
开发语言·c++
草莓熊Lotso4 小时前
《测试视角下的软件工程:需求、开发模型与测试模型》
java·c++·测试工具·spring·软件工程
报错小能手4 小时前
C++笔记(基础)string基础
开发语言·c++·笔记
青草地溪水旁5 小时前
从“手机拆修”看懂POD与非POD的区别
c++
先知后行。5 小时前
Qt 网络编程
开发语言·网络·qt
做运维的阿瑞6 小时前
Python零基础入门:30分钟掌握核心语法与实战应用
开发语言·后端·python·算法·系统架构
Q_Q19632884756 小时前
python+spring boot洪涝灾害应急信息管理系统 灾情上报 预警发布 应急资源调度 灾情图表展示系统
开发语言·spring boot·python·django·flask·node.js·php
༾冬瓜大侠༿7 小时前
C语言:自定义类型——联合体和枚举
java·c语言·开发语言