sherpa-onnx 集成 Nemotron-3.5 Streaming ASR:多语言流式转写模型的导出与解码实践

发布时间:2026/9/15 6:22:51
sherpa-onnx 集成 Nemotron-3.5 Streaming ASR:多语言流式转写模型的导出与解码实践 sherpa-onnx 集成 Nemotron-3.5 Streaming ASR多语言流式转写模型的导出与解码实践【免费下载链接】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本文以 scripts/nemo/nemotron-3.5-asr-streaming-0.6b/ 目录下的官方文档为主线完整讲解如何将 NVIDIA NeMo 的多语言流式语音识别模型nvidia/nemotron-3.5-asr-streaming-0.6b导出为 sherpa-onnx 的 streaming transducer 推理包并借助--language参数实现按语言强制转写与自动语言检测两种工作模式。读完本文你将掌握该模型的包结构、导出脚本的底层原理、prompt 机制的工作方式以及使用 sherpa-onnx 命令行完成端到端解码的完整方法。一、模型与导出产物总览Nemotron-3.5 Streaming ASR 0.6B 是一个多语言流式语音识别模型由 NVIDIA NeMo 训练并发布。本仓库目录 scripts/nemo/nemotron-3.5-asr-streaming-0.6b/ 提供了一键导出脚本 export_onnx.py将其转换为 sherpa-onnx 可直接加载的 streaming transducer 三件套。导出脚本写出的包布局与nvidia/nemotron-speech-streaming-en-0.6b保持一致最终产出一个完整的 sherpa-onnx 模型目录包含以下文件文件说明encoder.onnx/encoder.data流式编码器含 cache 状态输入输出权重以外部数据文件encoder.data存放decoder.onnxtransducer 解码器prediction networkjoiner.onnxtransducer joiner联合网络encoder.int8.onnx等上述三个 ONNX 图的 int8 动态量化变体encoder.int8.onnx、decoder.int8.onnx、joiner.int8.onnxtokens.txt由模型 SentencePiece tokenizer 转换得到的词表文件需要注意的是.data文件同样存在 int8 对应关系int8 量化图同样会导出对应的.data外部权重文件脚本中会为每个*.onnx生成同名的*.data。实际解码时sherpa-onnx 只认--encoder/--decoder/--joiner指定的 ONNX 路径因此既可以选择 FP32 图也可以选择 int8 图而 tokens.txt 则必须与模型词表一致。二、核心机制prompt_dictionary 与 auto_prompt_id这是该多语言模型区别于单语模型的关键设计。与普通 streaming transducer 不同Nemotron-3.5 的编码器是prompt-conditioned提示条件化的解码前需要向编码器注入一个语言提示prompt告诉模型当前这一段音频属于哪种语言。2.1 语言字符串 vs 数值 prompt id编码器的 ONNX 元数据metadata中包含两个关键字段prompt_dictionary一个 JSON 对象将语言字符串映射为整数 prompt id例如{auto: 101, en-US: 0, ja-JP: 1, ...}auto_prompt_id自动语言检测所使用的默认 prompt id 数值。对用户而言只需要以字符串形式按流per-stream设置语言数值型 prompt id 是内部实现细节由 sherpa-onnx 在加载模型时从元数据中解析出来并完成映射。这一设计让上层接口保持简单你写的是--languageja而真正进入 ONNX 图的是对应的整数张量。2.2 空语言与 auto 的语义文档明确指出空语言字符串与auto等价都使用模型内置的自动语言检测 prompt。也就是说不传--language即语言为空传--languageauto两者行为完全一致sherpa-onnx 都会走自动检测路径。2.3 推理端如何消费这些元数据在 sherpa-onnx/csrc/online-transducer-nemo-model.cc 中ParseLanguagePromptDictionary负责解析prompt_dictionary元数据把 JSON 中每个语言字符串到整数 id 的映射载入内存ReadPromptIdFromMetadata则读取auto_prompt_id。源码同时定义了一个兜底常量kDefaultAutoPromptId 101L44用于元数据缺失时的默认回退。加载时如果编码器声明了prompt_index输入但元数据里没有可用的prompt_dictionarysherpa-onnx 会打印警告并让所有语言回退到 autoL547-L551——因此使用本仓库的导出脚本生成包能保证元数据完整、两种模式均可正常工作。三、环境准备与模型导出3.1 环境依赖文档特别强调了一个版本陷阱截至 2026 年 6 月稳定的 NeMo 发行版尚不含EncDecRNNTBPEModelWithPrompt该模型类因此必须从 NeMo 的 git main 分支安装。推荐使用虚拟环境或容器隔离避免污染系统 Python。pip install Cython packaging pip install nemo_toolkit[asr] githttps://github.com/NVIDIA/NeMo.gitmain pip install onnxruntime ipython sentencepiece pip install kaldi-native-fbank pip install soundfile librosa依赖项作用说明nemo_toolkit[asr]加载 NeMo 模型并执行导出必须来自 main 分支onnxruntime脚本用它做 int8 动态量化quantize_dynamicsentencepieceNeMo 模型使用 SentencePiece tokenizer词表转换依赖它kaldi-native-fbank/soundfile/librosa用于特征提取与音频处理保证导出配置与推理端特征对齐Cython/packagingNeMo 安装与运行的常见依赖。3.2 执行导出python3 ./export_onnx.py导出脚本一次运行会依次生成80ms、160ms、320ms、560ms、1120ms五种 chunk size 的模型脚本内部按--chunk-size-ms参数分别导出并存入以毫秒数命名的子目录。实际使用时按延迟与精度的权衡选择其一例如官方解码示例选用 560ms 的 int8 版本。四、导出脚本源码剖析export_onnx.py 是理解整个流程的钥匙下面拆解几个关键设计。4.1 编码器输入输出契约编码器 ONNX 图的输入输出名在 L15-L30 中硬编码这是与 sherpa-onnx 推理端约定好的接口ENCODER_INPUT_NAMES [ audio_signal, length, cache_last_channel, cache_last_time, cache_last_channel_len, prompt_index, ] ENCODER_OUTPUT_NAMES [ outputs, encoded_lengths, cache_last_channel_next, cache_last_time_next, cache_last_channel_next_len, ]注意输入中的prompt_index它是把 NeMo 原生的Python 推理设置固化为真实 ONNX 输入的关键使得语言 prompt 可以在推理阶段按批batch动态指定。4.2 PromptedStreamingEncoder把 prompt 注入前向过程L93-L149 定义了PromptedStreamingEncoder它包装了 NeMo 编码器与prompt_kernel先调用encoder.forward_for_export()得到常规的流式编码输出与 cache 状态构造形状为(B, T, num_prompts)的 one-hot 张量将prompt_index通过scatter_落到对应位置把编码结果与该 prompt 张量cat后送入prompt_kernel得到最终编码输出。这等价于 NeMoPromptStreamingMixin._apply_prompt_to_encoded()的语义区别在于 prompt id 变成了 ONNX 输入而不是 Python 侧的推理设置——这样 sherpa-onnx 才能在 C 侧按流指定语言。4.3 导出参数与元数据动态轴audio_signal的 batch 与 time 维、两个 cache 张量的部分维度以及prompt_index的 batch 维均声明为动态轴L232-L244保证 batch 推理与不同 chunk 大小下可复用同一份图。窗口大小window_size chunk_size pre_encode_cache_sizeL315其中chunk_size ms // 80 - 1说明模型以 80ms 为基本帧。关键元数据L355-L380vocab_size、window_size、chunk_size_ms、chunk_shift、normalize_type、三个 cache 张量的维度、pred_rnn_layers、pred_hidden、subsampling_factor8、feat_dim128、prompt_dictionaryJSON 字符串与auto_prompt_id。这些元数据正是推理端初始化特征提取器、校验词表、解析语言映射的依据。词表save_tokens()L86-L90把joint.vocabulary逐行写成token id格式并在末尾追加blk {vocab_size-1}。推理端 online-recognizer-transducer-nemo-impl.h 会严格校验tokens.txt必须包含blk且其为最后一个 token、行数必须等于vocab_size否则直接报错退出。int8 量化最后对 encoder/decoder/joiner 三个图统一执行quantize_dynamic(..., weight_typeQuantType.QUInt8)生成 int8 变体L384-L389。五、使用 sherpa-onnx 解码导出完成后模型目录例如sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/即可被 sherpa-onnx 加载。以下命令假设你已经按项目流程编译出./build/bin/sherpa-onnx可执行文件且模型目录与test_wavs/ja.wav已就位。5.1 强制指定语言解码./build/bin/sherpa-onnx \ --encoder./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/encoder.int8.onnx \ --decoder./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/decoder.int8.onnx \ --joiner./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/joiner.int8.onnx \ --tokens./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/tokens.txt \ --languageja \ ./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/test_wavs/ja.wav--languageja表示强制按日语 prompt 解码。此时 sherpa-onnx 会把ja规范化为ja并查表得到其 prompt id通过prompt_index输入注入编码器。5.2 自动语言检测解码./build/bin/sherpa-onnx \ --encoder./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/encoder.int8.onnx \ --decoder./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/decoder.int8.onnx \ --joiner./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/joiner.int8.onnx \ --tokens./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/tokens.txt \ --languageauto \ ./sherpa-onnx-nemotron-3.5-asr-streaming-0.6b-560ms-int8-2026-06-11/test_wavs/ja.wav省略--language参数时行为与--languageauto完全一致均由模型自动判别语种。5.3 语言参数的解析与容错语言字符串在推理端的处理逻辑位于 online-transducer-nemo-model.cc 的NormalizeLanguage自动去除首尾空格与引号去掉...形式的包裹符将_替换为-统一转为小写。例如JA-JP、ja_jp、ja-JP都会被归一化为ja-jp。此外源码还会从en-US这类带地区码的条目自动派生en别名AddBaseLanguageAliasesL82-L94因此传--languageen也能命中。GetLanguagePromptIdL323-L348的完整决策顺序是非多语言模型或语言字符串为空 → 返回默认 prompt id即 auto命中language_prompt_ids_映射或归一化后命中→ 返回对应 id归一化结果为空或为auto→ 返回默认autoid查不到的语言 → 打印Unsupported language ... using auto错误日志并回退 auto。在批处理场景中每个流OnlineStream通过SetOption(language, ...)携带自己的语言online-recognizer-transducer-nemo-impl.h 的GetLanguagePromptIds会逐流解析出 prompt id 向量随prompt_index一并送入编码器从而实现同一批内不同流各自使用不同语言的混合多语言 batch 解码。六、小结Nemotron-3.5 Streaming ASR 0.6B 的多语言能力建立在 prompt-conditioned 编码器之上而 sherpa-onnx 通过一套字符串语言 → 数值 prompt id的元数据映射机制把这一能力封装成了简单的--language参数导出侧export_onnx.py 固化prompt_index输入、写入prompt_dictionary与auto_prompt_id元数据并产出 5 种 chunk 的 FP32/int8 全套图推理侧online-transducer-nemo-model.cc 负责解析元数据、归一化语言字符串并做容错回退使用侧强制语言用--languagecode自动检测用--languageauto或直接省略。这套流程同样适用于同目录下其他 NeMo streaming 模型的导出与接入是 sherpa-onnx 承载 NeMo 多语言流式 ASR 的标准路径。【免费下载链接】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),仅供参考