sherpa-onnx C API 示例完全指南:在 C 语言中实现流式语音识别、离线 TTS 与语音增强
【免费下载链接】sherpa-onnxSpeech-to-text, text-to-speech, speaker diarization, speech enhancement, source separation, and VAD using next-gen Kaldi with onnxruntime without Internet connection. Support embedded systems, Android, iOS, HarmonyOS, Raspberry Pi, RISC-V, RK NPU, Axera NPU, Ascend NPU, x86_64 servers, websocket server/client, support 12 programming languages项目地址: https://gitcode.com/GitHub_Trending/sh/sherpa-onnx
本文以c-api-examples/目录及其 README 为核心,系统讲解 sherpa-onnx 项目 C API 的示例集合:如何准备构建环境并编译这些 C 示例、如何阅读最关键的三个典型示例(流式 ASR 的 decode-file-c-api.c、离线 TTS 的 offline-tts-c-api.c、语音增强的 speech-enhancement-gtcrn-c-api.c),以及每个关键 API 调用链的含义。读完后,你将能够独立编写、编译并运行一个基于 sherpa-onnx C API 的语音识别或语音合成 C 程序。
一、c-api-examples 目录是什么
c-api-examples/README.md 说明:该目录包含 sherpa-onnx 的 C API 使用示例,完整的 C API 参考文档由 Doxygen 生成,文档源码位于 sherpa-onnx/c-api/ 目录(包含 Doxyfile 与 README.md,其中给出了在 Ubuntu/Debian 或 macOS 上安装 doxygen、graphviz 后用doxygen ./Doxyfile生成文档的方法)。
C API 的声明集中在头文件 sherpa-onnx/c-api/c-api.h 中,全部为纯 C 接口(SherpaOnnx*前缀函数),这也是 C/C++ 之外的语言(如仓库中pascal-api、dart等绑定方向)集成 sherpa-onnx 的入口。
README 中逐一点名了 6 个核心示例,下面完整继承并展开:
| 示例文件 | 用途 |
|---|---|
| decode-file-c-api.c | 使用 C API 以流式模型做语音识别(识别一个 wav 文件) |
| offline-tts-c-api.c | 使用 C API 以非流式模型把文本合成为语音 |
| speech-enhancement-gtcrn-c-api.c | 使用 GTCRN 模型做非流式语音增强 |
| speech-enhancement-dpdfnet-c-api.c | 使用 DPDFNet 模型做非流式语音增强:下游接 ASR 时用 16 kHz 的dpdfnet_baseline.onnx、dpdfnet2.onnx、dpdfnet4.onnx或dpdfnet8.onnx;需要 48 kHz 增强输出时用dpdfnet2_48khz_hr.onnx |
| online-speech-enhancement-gtcrn-c-api.c | 使用 GTCRN 模型做流式(在线)语音增强 |
| online-speech-enhancement-dpdfnet-c-api.c | 使用 DPDFNet 模型做流式语音增强:dpdfnet_baseline.onnx、dpdfnet2.onnx、dpdfnet4.onnx、dpdfnet8.onnx均为 16 kHz 输出 |
除上述 6 个外,目录实际包含 50 余个.c示例,覆盖 Whisper、Paraformer、SenseVoice、Moonshine、NeMo 等离线识别,流式 Transducer/CTC/Paraformer 识别,Whisper/Paraformer/SenseVoice/Moonshine 的 VAD 集成识别,Whisper 语种识别、说话人识别、离线说话人分离、音频打标、离线/在线标点恢复、声纹聚类以及 VITS/Kokoro/Matcha/Kitten/Pocket/Supertonic/ZipVoice 等各系 TTS 模型(完整清单见 c-api-examples/CMakeLists.txt)。此外c-api-examples/asr-microphone-example/子目录提供了一个基于 PortAudio 的实时麦克风识别完整工程。
二、编译前提:先构建 sherpa-onnx 主工程
所有 C 示例都依赖主工程编译产物。以 c-api-examples/Makefile 为例,其编译与链接配置揭示了依赖关系:
CFLAGS := -I ../ -I ../build/_deps/cargs-src/include/ LDFLAGS := -L ../build/lib LDFLAGS += -L ../build/_deps/onnxruntime-src/lib LDFLAGS += -lsherpa-onnx-c-api -lsherpa-onnx-core -lkaldi-decoder-core -lsherpa-onnx-kaldifst-core -lsherpa-onnx-fstfar -lsherpa-onnx-fst -lkaldi-native-fbank-core -lkissfft-float -lpiper_phonemize -lespeak-ng -lucd -lcargs -lonnxruntime LDFLAGS += -framework Foundation # macOS 专有 LDFLAGS += -lc++ LDFLAGS += -Wl,-rpath,${CUR_DIR}/../build/lib LDFLAGS += -Wl,-rpath,${CUR_DIR}/../build/_deps/onnxruntime-src/lib从源码结构看,可以推断出两点:
- 头文件搜索路径
-I ../使#include "sherpa-onnx/c-api/c-api.h"命中仓库内的 c-api.h;cargs.h则来自主工程 CMake 构建时拉取的依赖build/_deps/cargs-src。 - 运行时通过
-Wl,-rpath直接指向build/lib与build/_deps/onnxruntime-src/lib,因此必须先完成主工程的 CMake 构建(产出build/目录)后再执行make;Makefile 默认只构建decode-file-c-api与offline-tts-c-api两个目标(见 Makefile 第 15-21 行),其余示例需自行追加目标。
推荐做法是使用 CMake,随主工程一起构建。c-api-examples/CMakeLists.txt 的写法非常统一:
include(cargs) include_directories(${PROJECT_SOURCE_DIR}) add_executable(decode-file-c-api decode-file-c-api.c) target_link_libraries(decode-file-c-api sherpa-onnx-c-api cargs)即只需链接sherpa-onnx-c-api一个目标,底层依赖由该目标传递。注意条件开关:TTS 类示例(offline-tts-c-api、matcha/kokoro/kitten/pocket/supertonic/zipvoice等)位于if(SHERPA_ONNX_ENABLE_TTS)块内(CMakeLists.txt 第 33 行起),说话人分离示例位于if(SHERPA_ONNX_ENABLE_SPEAKER_DIARIZATION)块内(第 62-65 行)——构建主工程时若未开启对应开关,这些示例不会生成。
三、示例精讲一:decode-file-c-api.c——从文件模拟流式识别
这是 README 首推的示例,演示如何把整段 wav 文件切成小块、模拟流式输入,用 streaming transducer 模型完成识别。
3.1 命令行接口
程序基于cargs库解析参数(options 定义,第 15-69 行):
| 参数 | 含义 | 默认值 |
|---|---|---|
--tokens | tokens 文本文件路径 | 必填 |
--encoder/--decoder/--joiner | transducer 三个 ONNX 模型文件 | 必填 |
--num-threads | 推理线程数 | 1 |
--provider | 推理后端:cpu(默认)、cuda、coreml | cpu |
--decoding-method | greedy_search(默认)或modified_beam_search | greedy_search |
--hotwords-file | 热词文件,每行一个词/短语,BPE/中文字符之间用空格分隔(如▁HE LL O ▁WORLD、你 好 世 界) | 空 |
--hotwords-score | 热词加分,仅在modified_beam_search下生效 | 0 |
典型用法(摘自程序内置 usage,第 71-90 行):
./decode-file-c-api \ --tokens=/path/to/tokens.txt \ --encoder=/path/to/encoder.onnx \ --decoder=/path/to/decoder.onnx \ --joiner=/path/to/joiner.onnx \ --provider=cpu \ /path/to/foo.wav注意 usage 末尾的约束:该文件仅支持流式 transducer 模型(streaming transducer)。
3.2 默认配置
参数解析前,程序先填充一组默认值(第 98-115 行),这些字段与 C API 头文件中的SherpaOnnxOnlineRecognizerConfig一一对应:
SherpaOnnxOnlineRecognizerConfig config; memset(&config, 0, sizeof(config)); config.model_config.debug = 0; config.model_config.num_threads = 1; config.model_config.provider = "cpu"; config.decoding_method = "greedy_search"; config.max_active_paths = 4; config.feat_config.sample_rate = 16000; // 输入采样率 16 kHz config.feat_config.feature_dim = 80; // 80 维 Fbank config.enable_endpoint = 1; // 开启端点检测 config.rule1_min_trailing_silence = 2.4; // 规则1:句尾静音 >= 2.4s 判端点 config.rule2_min_trailing_silence = 1.2; // 规则2:已有文本且静音 >= 1.2s 判端点 config.rule3_min_utterance_length = 300; // 规则3:已识别时长 >= 300(约20s)判端点端点检测的三规则机制是该示例能够把长音频自动切分为多个“句子”并逐句输出的关键。
3.3 核心调用链(值得逐行学习)
创建识别器与流(第 165-168 行):
const SherpaOnnxOnlineRecognizer *recognizer = SherpaOnnxCreateOnlineRecognizer(&config); const SherpaOnnxOnlineStream *stream = SherpaOnnxCreateOnlineStream(recognizer);读取 wav:
SherpaOnnxReadWave(filename)返回SherpaOnnxWave(含sample_rate、num_samples、samples指针),失败需判空。模拟流式输入(第 181-215 行):以
N = 3200个采样(16 kHz 下 0.2 秒)为一块循环喂入:while (k < wave->num_samples) { int32_t start = k; int32_t end = (start + N > wave->num_samples) ? wave->num_samples : (start + N); k += N; SherpaOnnxOnlineStreamAcceptWaveform(stream, wave->sample_rate, wave->samples + start, end - start); while (SherpaOnnxIsOnlineStreamReady(recognizer, stream)) { SherpaOnnxDecodeOnlineStream(recognizer, stream); } const SherpaOnnxOnlineRecognizerResult *r = SherpaOnnxGetOnlineStreamResult(recognizer, stream); if (strlen(r->text)) { SherpaOnnxPrint(display, segment_id, r->text); } if (SherpaOnnxOnlineStreamIsEndpoint(recognizer, stream)) { if (strlen(r->text)) { ++segment_id; } SherpaOnnxOnlineStreamReset(recognizer, stream); // 重置流,开始下一句 } SherpaOnnxDestroyOnlineRecognizerResult(r); }注意
SherpaOnnxIsOnlineStreamReady是 while 条件而非 if——内部特征缓存可能一次攒够多个解码步,必须解码到“不再就绪”为止。SherpaOnnxDestroyOnlineRecognizerResult每次取结果后必须调用,防止内存泄漏。收尾(第 217-234 行):追加 0.3 秒静音尾垫(4800 个 0)让模型把尾部文本解码完整,然后
SherpaOnnxOnlineStreamInputFinished标记输入结束,再次循环解码直到就绪条件不成立,取出最终结果打印。资源释放顺序(第 238-240 行):
DestroyDisplay→DestroyOnlineStream→DestroyOnlineRecognizer,遵循“先流后识别器”的从内到外顺序。
以上“配置 → 建识别器 → 建流 → 分块 AcceptWaveform → Ready/Decode 循环 → GetResult → 端点判断/Reset → 尾垫 + InputFinished → 逐级销毁”就是 sherpa-onnx 流式 ASR 的标准 C 调用范式,目录中其余流式示例(streaming-zipformer-c-api.c、streaming-paraformer-c-api.c等)结构完全一致,可直接套用时把模型字段换成对应模型类型(CTC、Paraformer 等)。
四、示例精讲二:offline-tts-c-api.c——非流式文本转语音
offline-tts-c-api.c 演示用 VITS 类非流式 TTS 模型把一句文本合成为 wav 文件。内置 usage(第 93-130 行)给出了可直接复制的运行方式:
./offline-tts-c-api \ --vits-model=./vits-ljs.onnx \ --vits-lexicon=./lexicon.txt \ --vits-tokens=./tokens.txt \ --sid=0 \ --output-filename=./generated.wav \ 'liliana, the most beautiful and lovely assistant of our team!'参数全集(options 定义,第 15-91 行):
| 参数 | 含义 | 默认值 |
|---|---|---|
--vits-model | VITS 模型 ONNX 文件路径 | 必填 |
--vits-lexicon | 发音词典lexicon.txt | 必填(若给了--vits-data-dir则被忽略) |
--vits-tokens | tokens.txt路径 | 必填 |
--vits-noise-scale | VITS 的 noise_scale | 0.667 |
--vits-noise-scale-w | VITS 的 noise_scale_w | 0.8 |
--vits-length-scale | 语速控制:越小越快、越大越慢 | 1.0 |
--num-threads | 推理线程数 | 1 |
--provider | cpu(默认)、cuda、coreml | cpu |
--debug | 1 表示加载模型时打印调试信息 | 0 |
--sid | 说话人 ID;单说话人模型不生效 | 0 |
--output-filename | 输出 wav 文件名 | ./generated.wav |
--tts-rule-fsts | 逗号分隔的 rule FST 列表,从左到右依次应用(文本规整用) | 空 |
--max-num-sentences | 单批处理句数上限,防止长文本 OOM;设为 -1 表示全部句子单批处理 | 2 |
--vits-data-dir | espeak-ng-data 目录;给出后忽略--vits-lexicon(多语言 Piper 类模型用) | 空 |
--vits-noise-scale与--vits-noise-scale-w对应 VITS 采样时两个噪声向量的幅度,--vits-length-scale则控制时长预测缩放——这两组参数是实际调音色稳定性与语速时最常调整的旋钮。
五、示例精讲三:语音增强四件套(GTCRN / DPDFNet,离线与流式)
README 中专门描述了四个语音增强示例,它们分别覆盖“离线/在线” × “GTCRN/DPDFNet”的组合,对应 C API 中SherpaOnnx*SpeechDenoiser*一族函数。
5.1 非流式 GTCRN:三十行代码讲清离线增强流程
speech-enhancement-gtcrn-c-api.c 全文仅约 56 行,是最短的完整“加载模型 → 处理整段音频 → 写回文件”流程(main 函数,第 22-56 行),可视为离线语音增强的最小可运行模板:
SherpaOnnxOfflineSpeechDenoiserConfig config; memset(&config, 0, sizeof(config)); config.model.gtcrn.model = "./gtcrn_simple.onnx"; // 指向 GTCRN 模型 const SherpaOnnxOfflineSpeechDenoiser *sd = SherpaOnnxCreateOfflineSpeechDenoiser(&config); const SherpaOnnxWave *wave = SherpaOnnxReadWave("./inp_16k.wav"); const SherpaOnnxDenoisedAudio *denoised = SherpaOnnxOfflineSpeechDenoiserRun( sd, wave->samples, wave->num_samples, wave->sample_rate); SherpaOnnxWriteWave(denoised->samples, denoised->n, denoised->sample_rate, "./enhanced.wav"); SherpaOnnxDestroyDenoisedAudio(denoised); SherpaOnnxFreeWave(wave); SherpaOnnxDestroyOfflineSpeechDenoiser(sd);调用链即:SherpaOnnxCreateOfflineSpeechDenoiser(创建)→SherpaOnnxOfflineSpeechDenoiserRun(整段处理,返回SherpaOnnxDenoisedAudio)→SherpaOnnxWriteWave(落盘)→ 三个 Destroy/Free 收尾。模型可从项目发布的 speech-enhancement-models 资源中下载(如gtcrn_simple.onnx),测试输入inp_16k.wav也是 16 kHz。
5.2 模型与采样率选择(DPDFNet)
README 对 DPDFNet 的选型给出了明确指引,务必注意采样率匹配:
- 非流式(speech-enhancement-dpdfnet-c-api.c):增强结果还要送下游 ASR 时,用16 kHz模型:
dpdfnet_baseline.onnx、dpdfnet2.onnx、dpdfnet4.onnx、dpdfnet8.onnx;只追求 48 kHz 高保真增强输出时用dpdfnet2_48khz_hr.onnx。 - 流式(online-speech-enhancement-dpdfnet-c-api.c):
dpdfnet_baseline.onnx、dpdfnet2.onnx、dpdfnet4.onnx、dpdfnet8.onnx输出均为 16 kHz。
流式两个示例(online-speech-enhancement-gtcrn-c-api.c与online-speech-enhancement-dpdfnet-c-api.c)对应 C API 中的在线降噪器接口,其处理模式与第三章流式识别同构:创建在线 denoiser → 按帧AcceptWaveform→ 判断就绪后Run取回增强帧,适合麦克风实时场景。
六、如何选用与扩展这些示例
- 只读一个文件学流式 ASR:以 decode-file-c-api.c 为模板,改
model_config中对应的模型字段(如ctc、paraformer、whisper等,见 c-api.h 中的各 Config 结构)即可适配目录中其他 50 余个 ASR 示例。 - 需要真实麦克风:参考
c-api-examples/asr-microphone-example/子目录(含 CMake 工程、PortAudio 采集与麦克风识别完整工程)。 - 批量构建验证:目录内提供了 run.sh 脚本,用于在构建产物上运行各示例做端到端验证。
- CMake 集成:若在自己的 CMake 工程中链接
sherpa-onnx-c-api目标,即可复用本章所有调用代码;若以预编译库 + Makefile 方式集成,注意 Makefile 中的rpath写法在 macOS 上需替换为-rpath的 Mach-O 语法,并去掉-framework Foundation一行在 Linux 上的不适用项(该行仅 macOS 需要)。
七、小结
c-api-examples/是理解 sherpa-onnx C 层的最佳切入口:README 点名的 6 个示例分别对应“流式 ASR、离线 TTS、离线/流式语音增强(GTCRN + DPDFNet)”四大能力,而 CMakeLists.txt 与目录中其余 50 余个.c文件则展示了同一套 C API 在 Whisper、Paraformer、SenseVoice、说话人识别/分离、标点恢复、音频打标、各系 TTS 模型上的统一用法。掌握第三章的“分块喂入 + Ready/Decode 循环 + 端点重置”范式与第四章的“配置 → 创建 → 运行 → 逐级销毁”资源纪律后,编写新的 C API 程序基本只是更换 Config 字段与模型路径的工作。
【免费下载链接】sherpa-onnxSpeech-to-text, text-to-speech, speaker diarization, speech enhancement, source separation, and VAD using next-gen Kaldi with onnxruntime without Internet connection. Support embedded systems, Android, iOS, HarmonyOS, Raspberry Pi, RISC-V, RK NPU, Axera NPU, Ascend NPU, x86_64 servers, websocket server/client, support 12 programming languages项目地址: https://gitcode.com/GitHub_Trending/sh/sherpa-onnx
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考