资讯动态

TEN Framework vosk_asr_cpp 扩展深入解析:用 C++ 构建基于 Vosk 的本地实时语音识别

发布时间:2026/9/25 7:50:17 来源:尧图企业网站定制
人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载本文以 TEN Framework 仓库中的vosk_asr_cpp示例扩展为主线系统讲解如何将开源语音识别引擎 Vosk 封装为一个标准的 TEN Framework C 扩展从 VOSK SDK 与识别模型的手工部署到扩展属性property.json配置、扩展生命周期回调on_init/on_audio_frame/on_deinit的源码走读再到基于 googletest 的独立测试与tman安装集成流程。读完本文你可以完整复现该扩展的部署与构建过程并理解 TEN Framework 音频扩展帧进、结果出的数据流设计。一、扩展定位TEN Framework 中的 C ASR 扩展vosk_asr_cpp是一个为 TEN Framework 用 C 编写的 Vosk 自动语音识别ASR扩展其定位是接收上游如音频文件播放器、麦克风采集模块送入的音频帧逐帧送入 Vosk 识别器进行解码并以data消息的形式输出识别文本——既包括说话过程中的部分结果partial result也包括语句结束时的最终结果final result从而天然适配实时转写场景。从 manifest.json 可以看到该扩展的元信息type为extension包名为vosk_asr_cpp当前版本0.11.73tags标注为cpp表明这是一个 C 实现的扩展依赖两个系统包ten_runtime扩展运行时版本0.11.73与googletest版本1.7.0-rc2用于独立测试。manifest 中还定义了两个常用脚本体现了该包的日常开发方式scripts: { test: bin/vosk_asr_cpp_test, build: sh -c cd .ten/app tgn gen linux x64 debug -- ten_enable_standalone_testtrue tgn build linux x64 debug }其中build脚本通过tgn gen生成构建文件并显式开启ten_enable_standalone_testtrue再执行tgn build这与第六节介绍的独立测试机制直接对应。二、环境准备手工部署 VOSK SDK为什么 SDK 不随扩展自带VOSK SDK包含头文件与动态库体积较大因此vosk_asr_cpp默认不内置SDK需要使用者自行下载并部署。官方文档README.en-US.md、README.ja-JP.md 等多语言版本给出的做法是从 vosk-api 的官方发行页alphacep/vosk-api 的 releases下载与当前平台匹配的预编译包然后按以下两个位置放置文件文件放置位置作用vosk_api.h扩展根目录下的include/目录编译期头文件src/main.cc中#include vosk_api.h直接依赖它libvosk.so扩展根目录下的lib_private/目录运行期动态库构建时链接、运行时通过 rpath 查找rpathlib_private/是如何被找到的这一目录约定并非随意规定BUILD_release.gn 中有明确的构建配置佐证ten_package(vosk_asr_cpp) { package_kind extension enable_build true sources [ src/main.cc ] include_dirs [ include, include/nlohmann_json, ] # Add rpath to find vosk library. if (is_mac) { ldflags [ -Wl,-rpath,loader_path/../lib_private ] } else if (is_linux) { ldflags [ -Wl,-rpath\$ORIGIN/../lib_private ] } lib_dirs [ lib_private ] libs [ vosk ] }可以看到include目录被加入头文件搜索路径vosk_api.h由此被找到lib_dirs指向lib_private链接期找到libvosk同时通过平台相关的-rpathLinux 下$ORIGIN/../lib_privatemacOS 下loader_path/../lib_private确保扩展编译出的动态库在运行期也能从相对自身路径的lib_private/目录加载libvosk.so而不依赖系统库搜索路径或LD_LIBRARY_PATH。这就是头文件放include/、动态库放lib_private/这一约定的底层原因。注意仓库中include/目录当前已内置了nlohmannJSON 库头文件说明该扩展在构建配置层面预留了第三方头文件扩展能力而 vosk 相关头文件仍需使用者按上述说明手工补充。三、安装 VOSK 识别模型SDK 只解决怎么跑识别引擎的问题真正的识别能力来自 Vosk 模型。文档要求从 Vosk 模型官网alphacephei.com/vosk/models下载所需模型解压后放到扩展根目录的models/目录下。模型加载逻辑在源码中非常直接。src/main.cc 的on_init回调中void on_init(ten::ten_env_t ten_env) override { auto model_name ten_env.get_property_string(model_name); // Open the specified model. vosk_model vosk_model_new((std::string(models/) model_name).c_str()); if (vosk_model nullptr) { TEN_LOGE(Failed to load model, check if exists in the folder); exit(EXIT_FAILURE); } auto sample_rate ten_env.get_property_float32(sample_rate); TEN_ENV_LOG_INFO(ten_env, (std::string(Specify sample rate: ) std::to_string(sample_rate)).c_str()); vosk_recognizer vosk_recognizer_new(vosk_model, sample_rate); if (vosk_recognizer nullptr) { TEN_LOGE(Failed to create recognizer); exit(EXIT_FAILURE); } ten_env.on_init_done(); }要点模型名不是硬编码的而是从扩展属性model_name读取再以models/ model_name拼接成相对路径调用vosk_model_new加载——这就是模型必须放在models/目录下的强制约定加载失败会打印Failed to load model, check if exists in the folder并直接exit(EXIT_FAILURE)排查部署问题时可优先检查日志中这条信息识别器vosk_recognizer_new的第二个参数是采样率来自属性sample_ratefloat32 类型识别器的解码行为会严格基于该采样率设计。四、属性配置property.json 的两个核心参数扩展根目录下的 property.json 定义了该扩展的全部可配置属性默认内容如下{ model_name: vosk-model-small-en-us-0.15, sample_rate: 16000.0 }属性类型默认值含义与约束model_namestringvosk-model-small-en-us-0.15models/目录下的模型子目录名对应从官网下载的英文小模型更换模型如中文模型时同步修改此项sample_ratefloat3216000.0送入识别器的音频采样率Vosk 官方小模型基于 16 kHz 设计修改该值时须与模型要求及上游音频流一致sample_rate在on_init中会以TEN_ENV_LOG_INFO打印日志形如Specify sample rate: 16000便于运行时核对配置是否生效。测试代码 tests/basic.cc 的注释也再次强调测试音频需为16 kHz 采样率的 PCM 格式。五、核心实现走读音频帧进、识别结果出数据流总览从源码结构看整个扩展的数据流是一个清晰的单向管线上游音频帧 (audio_frame) └─ on_audio_frame ├─ frame-lock_buf() 锁定 PCM 数据 ├─ vosk_recognizer_accept_waveform() 送入 Vosk 解码 ├─ 判断 is_final0仍在说话非0一句话结束 │ ├─ 非最终句vosk_recognizer_partial_result() │ └─ 最终句vosk_recognizer_result() └─ send_data(recognition_result) 输出 data 消息 ├─ property: result (string) └─ property: is_final (int)on_audio_frame逐帧解码与部分/最终结果关键实现在 src/main.ccvoid on_audio_frame(ten::ten_env_t ten_env, std::unique_ptrten::audio_frame_t frame) override { std::string frame_name frame-get_name(); TEN_ENV_LOG_INFO( ten_env, (std::string(Received audio frame ) frame_name ).c_str()); ten::buf_t locked_in_buf frame-lock_buf(); int is_final vosk_recognizer_accept_waveform( vosk_recognizer, reinterpret_castconst char *(locked_in_buf.data()), static_castint(locked_in_buf.size())); frame-unlock_buf(locked_in_buf); const char *result nullptr; if (is_final ! 0) { result vosk_recognizer_result(vosk_recognizer); } else { result vosk_recognizer_partial_result(vosk_recognizer); } auto recognition_result ten::data_t::create(recognition_result); recognition_result-set_property(result, result); recognition_result-set_property(is_final, is_final); bool rc ten_env.send_data(std::move(recognition_result)); TEN_ASSERT(rc, Should not happen.); }几个实现细节值得注意缓冲区生命周期管理lock_buf()/unlock_buf()是 TEN Framework 音频帧的加锁/解锁配对操作。Vosk 的accept_waveform是同步调用解码完成并取走结果后即可解锁保证帧内存可被框架复用is_final的双义性vosk_recognizer_accept_waveform的返回值0 或非 0本身表示这一帧是否触发了语句结束扩展原样把它透传给下游is_final属性下游节点如 TTS、日志节点可据此区分流式部分结果与完整句子结果消息命名输出的data消息固定命名为recognition_result携带result识别文本与is_final两个属性这与测试代码的读取方式完全对称。on_deinit 与扩展注册资源释放与注册分别见 src/main.ccon_deinit中先释放识别器、再释放模型vosk_recognizer_free→vosk_model_free并置空指针最后调用ten_env.on_deinit_done()通知框架文件末尾通过宏TEN_CPP_REGISTER_ADDON_AS_EXTENSION(vosk_asr_cpp, vosk_asr_cpp_t)将 C 类注册为 TEN 扩展扩展名与包名保持一致。六、独立测试用 test.wav 验证端到端识别该扩展自带一个基于 googletest 的独立standalone测试可在不启动完整 TEN 应用的情况下验证音频进、文本出的完整链路。前置条件安装 googletest 系统包BUILD_release.gn 中的注释给出了明确的命令tman install system googletest对应manifest.json中声明的googletest依赖。之后通过tgn gen ... -- ten_enable_standalone_testtrue生成构建时才会启用如下测试目标if (ten_enable_standalone_test) { ten_package_test(vosk_asr_cpp_test) { package_kind extension sources [ .ten/app/ten_packages/system/googletest/src/gtest-all.cc, .ten/app/ten_packages/system/googletest/src/gtest_main.cc, tests/basic.cc, ] ... } }测试流程解析tests/basic.cc 的实现思路是模拟一个真实音频源构造函数打开./tests/test.wav注释明确要求PCM 格式、16 kHz 采样率该样例音频随包提供tests/test.wavon_start中按 4096 字节为块循环fread每块数据封装成一个名为recognize的audio_frame_t通过lock_buf/memcpy/unlock_buf写入 PCM 数据后send_audio_frame送入扩展模拟持续灌入音频流on_data回调读取扩展输出的recognition_result消息打印result与is_final一旦收到is_final 0的最终结果即调用ten_env.stop_test()结束测试——这隐含了 test.wav 中应包含一段完整语句的假设TEST(Test, Basic)入口通过set_test_mode_single(vosk_asr_cpp)声明被测扩展随后run()执行整个生命周期。提醒独立测试要求models/目录中已按property.json的model_name配置好模型否则扩展会在on_init阶段直接失败退出。七、安装与集成到 TEN 应用官方文档说明安装方式为遵循 TEN Framework 的包安装指南。结合仓库快速上手文档 docs/getting-started/quick-start.md 中介绍 C 扩展的标准流程以webrtc_vad_cpp为例vosk_asr_cpp的集成路径为安装扩展在应用目录如示例应用transcriber_demo下执行tman install extension vosk_asr_cpp将扩展连同本文第二节、第三节要求手工放置的 SDK 与模型文件拉入应用的.ten包环境重新构建执行tman run build构建系统会依据BUILD_release.gn把src/main.cc编译成扩展动态库并链接libvosk在应用中编排按 TEN Framework 的应用规范将该扩展挂入音频处理链路让上游节点如音频文件播放器的音频帧发往vosk_asr_cpp下游节点消费recognition_result数据消息即可。此外C 扩展的编译要求宿主机具备 C 工具链gcc/g 或 clang快速上手文档中给出了各平台的安装示例manifest.json的build脚本则展示了在 Linux x64 debug 模式下手工驱动tgn gentgn build的等价做法。八、目录结构与许可证小结综合 BUILD.gn 的打包规则与仓库实际内容该扩展的目录职责如下路径内容说明src/main.cc扩展唯一源码生命周期回调与 Vosk 调用本文第五节include/头文件内置 nlohmann 头文件vosk 头文件需手工放入lib_private/私有动态库需手工放入libvosk.so由 rpath 定位models/识别模型需手工下载解压放置名称与model_name属性一致property.json属性默认值model_name与sample_ratetests/basic.cc、tests/test.wav独立测试与样例音频16 kHz PCMBUILD.gn/BUILD_release.gn构建定义开发态打包 / 发布态编译含 rpath 与链接配置docs/README.*.md多语言文档en-US、zh-CN、zh-TW、ja-JP、ko-KR 五个版本关于许可证官方文档声明该包是 TEN Framework 项目的一部分遵循仓库顶层 LICENSE 所约定的 Apache License 2.0 许可。九、小结vosk_asr_cpp虽然代码量很小但它是理解 TEN Framework C 扩展机制的一个理想样本手工部署第三方 SDKinclude/lib_private/ rpath、通过property.json声明可配置项、在on_init/on_audio_frame/on_deinit三个回调中完成资源初始化、流式解码与释放最后用 googletest 独立测试验证端到端行为。掌握这套模式后将其他本地推理引擎封装成 TEN Framework 音频扩展只需替换解码核心、保持音频帧进、data 消息出的边界约定即可。赞分享人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载相关推荐TEN Framework vosk_asr_cpp 扩展实战Vosk C 语音识别扩展的 SDK 部署、属性配置与源码解析TEN Framework vosk_asr_cpp 扩展实战Vosk C 语音识别扩展的 SDK 部署、属性配置与源码解析 本文以 TEN Framew人工智能AI Agent多模态语音AI 应用TEN Framework 集成指南基于 AWS Transcribe 的异步实时语音识别扩展 aws_asr_pythonTEN Framework 集成指南基于 AWS Transcribe 的异步实时语音识别扩展 aws_asr_python 导读 本文深入讲解 TEN Fr人工智能AI Agent多模态语音AI 应用TEN Framework 中的 Soniox 实时语音识别扩展soniox_asr_python使用与源码解析TEN Framework 中的 Soniox 实时语音识别扩展soniox_asr_python使用与源码解析 本指南以 TEN Framework 仓库人工智能AI Agent多模态语音AI 应用上一篇微信聊天记录永久保存完全指南如何让珍贵对话永不丢失下一篇如何永久保存微信聊天记录WeChatMsg导出工具完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑