
GigaAM 俄语语音识别模型转换指南从 NeMo/GigaAM 到 sherpa-onnx 的 CTC 与 RNNT 全流程【免费下载链接】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/GigaAM/README.md 所述的核心任务展开将 SberDevices 开源的GigaAM 俄语语音识别模型包含 CTC 与 RNNT 两类架构转换为 sherpa-onnx 可加载的 ONNX 格式。读完本文你将掌握从环境搭建、权重下载、ONNX 导出、INT8 量化到最终在 sherpa-onnx 中离线推理的完整实战链路并理解转换脚本与推理端 C 实现之间的元数据约定。一、背景GigaAM 与 sherpa-onnx 的衔接GigaAM 是一系列面向俄语语音识别的模型集合由 salute-developers 团队开源。本仓库的 scripts/nemo/GigaAM 目录提供了一整套转换脚本负责将 GigaAM 模型从 PyTorch/NeMo 生态迁移到基于 onnxruntime 的 sherpa-onnx 推理框架。这些模型之所以能无缝衔接 sherpa-onnx核心在于转换脚本会向导出的 ONNX 模型写入一组元数据meta data例如model_type、vocab_size、subsampling_factor、is_giga_am等。推理端在加载模型时会读取这些元数据来决定特征提取方式、词表大小与解码策略详见后文 八、与 sherpa-onnx 推理端的集成。该目录覆盖两类主流模型架构架构导出脚本说明CTCexport-onnx-ctc*.py字符级或 BPE 词表单模型文件输出logprobsRNNTexport-onnx-rnnt*.py拆分为 encoder / decoder / joiner 三个 ONNX 文件二、目录结构与脚本总览scripts/nemo/GigaAM 下的脚本按导出export— 运行run— 测试test三段式组织并存在v1 / v2 / v3 / v3-punct等多个模型版本变体文件用途export-onnx-ctc.py从 NeMoEncDecCTCModel导出 CTC 模型v1基于 NeMo 工具链export-onnx-ctc-v2.py基于官方gigaamPython 包导出 v2 CTC 模型export-onnx-ctc-v3.py导出 v3 CTC 模型字符级34 类输出export-onnx-ctc-v3-punct.py导出 v3 带标点 CTC 模型BPE257 类输出export-onnx-rnnt.py从 NeMoEncDecRNNTBPEModel导出 RNNT 三分模型v1export-onnx-rnnt-v2.py/export-onnx-rnnt-v3.py/export-onnx-rnnt-v3-punct.py对应 v2 / v3 / v3-punct 的 RNNT 版本run-ctc.sh/run-rnnt.sh及 v2/v3 变体一键执行装环境 → 下权重 → 导出 → 测试test-onnx-ctc.py/test-onnx-rnnt.py用 onnxruntime 验证导出结果并打印识别文本其中test-onnx-ctc.py与test-onnx-rnnt.py对所有 CTC / RNNT 版本通用脚本顶部注释与模型 IO 打印信息display函数直接反映了各版本导出的 ONNX 图结构。三、环境准备与一键转换流程以 v1 版本为例run-ctc.sh 与 run-rnnt.sh 的流程完全一致分为三步安装依赖 → 下载模型文件 → 执行导出与测试。3.1 依赖安装install_nemoCTC 与 RNNT 的 v1 脚本共用同一套环境见run-ctc.sh第 6-21 行pip install torch2.4.0 torchaudio2.4.0 -f https://download.pytorch.org/whl/torch_stable.html pip install -qq wget text-unidecode matplotlib3.3.2 onnx onnxruntime1.17.1 \ pybind11 Cython einops kaldi-native-fbank soundfile librosa pip install -qq ipython python3 -m pip install githttps://github.com/NVIDIA/NeMo.gitmain#eggnemo_toolkit[asr] pip install numpy1.26.4关键点说明onnxruntime 固定为 1.17.1与后续动态量化 APIquantize_dynamic及导出兼容性相关kaldi-native-fbank用于测试阶段的 Fbank 特征提取与 sherpa-onnx 推理端使用的特征提取库一致保证数值对齐numpy1.26.4在 NeMo 安装之后单独固定避免依赖冲突脚本中注释掉了apt-get install sox libsndfile1 ffmpeg如系统缺失相关音频库可自行启用。而v2 / v3 脚本如 run-ctc-v2.sh不再依赖 NeMo 工具链改为直接安装 GigaAM 官方 Python 包python3 -m pip install githttps://github.com/salute-developers/GigaAM.gitmain#egggigaam python3 -m pip install -qq kaldi-native-fbank pip install numpy1.26.4v2/v3 脚本还直接下载了example.wav与模型仓库的LICENSE文件说明新版模型由官方 gigaam 包内置下载与加载逻辑。3.2 模型文件下载download_filesv1 的 CTC 与 RNNT 所需文件不同CTCctc_model_weights.ckpt、ctc_model_config.yaml、example.wav、long_example.wav、GigaAM License_NC.pdfRNNT除rnnt_model_weights.ckpt、rnnt_model_config.yaml及音频样本外还额外需要tokenizer_all_sets.tarBPE 分词器下载后解压得到tokenizer_all_sets目录curl -SL -O rnnt_model_weights.ckpt 下载地址 curl -SL -O rnnt_model_config.yaml 下载地址 curl -SL -O example.wav curl -SL -O long_example.wav curl -SL -O tokenizer_all_sets.tar tar -xf tokenizer_all_sets.tar rm tokenizer_all_sets.tar注意GigaAM License_NC.pdf文件名中的NC代表 Non-Commercial非商业许可使用前务必核对模型许可条款详见 九、许可与注意事项。3.3 一键执行# CTC v1 bash run-ctc.sh # RNNT v1 bash run-rnnt.sh脚本末尾依次执行导出、ls -lh查看产物、运行测试脚本。其中run-rnnt.sh在测试后还会删除中间产物encoder.onnx仅保留量化后的encoder.int8.onnx。四、CTC 模型导出字符级词表与 INT8 量化4.1 v1基于 NeMo 工具链导出export-onnx-ctc.py 的核心流程model EncDecCTCModel.from_config_file(./ctc_model_config.yaml) ckpt torch.load(./ctc_model_weights.ckpt, map_locationcpu) model.load_state_dict(ckpt, strictFalse) model.eval() # 生成 tokens.txt字符级词表space 的 id 为 0blk 为最后一个 token with open(tokens.txt, w, encodingutf-8) as f: for i, t in enumerate(model.cfg.labels): f.write(f{t} {i}\n) f.write(fblk {i1}\n) model.export(model.onnx)转换要点strictFalse加载权重容忍配置与 checkpoint 之间的键差异词表规则GigaAM CTC 模型为字符级词表空格的 token id 固定为0blkblank追加在最后一个 id这一约定在测试脚本中通过blank len(id2token) - 1呼应导出后立即为model.onnx写入元数据meta_data { vocab_size: len(model.cfg.labels) 1, normalize_type: , # 特征不做归一化 subsampling_factor: 4, # 时间维下采样 4 倍 model_type: EncDecCTCModel, version: 1, model_author: https://github.com/salute-developers/GigaAM, license: https://github.com/salute-developers/GigaAM/blob/main/GigaAM%20License_NC.pdf, language: Russian, is_giga_am: 1, # 标记为 GigaAM 模型推理端据此调整特征参数 }其中is_giga_am: 1是 sherpa-onnx 推理端识别 GigaAM 模型的关键标志详见第八节。随后调用 onnxruntime 的动态量化生成 INT8 版本quantize_dynamic( model_inputmodel.onnx, model_outputmodel.int8.onnx, weight_typeQuantType.QUInt8, )最终目录下同时保留model.onnxFP32与model.int8.onnxINT8供不同精度需求的部署场景选用。4.2 前处理适配Mel 谱与 NeMo 的参数兼容导出脚本中定义了两个子类FilterbankFeaturesTA与AudioToMelSpectrogramPreprocessorexport-onnx-ctc.py第 18-54 行用于在导出阶段注入与 sherpa-onnx 一致的 Mel 特征计算参数丢弃 NeMo 传入的window_size/window_stride改用显式构造的torchaudio.transforms.MelSpectrogram特征参数n_fft320、win_length320、hop_length160、mel_scalehtk、nfilt64将 NeMo 的features参数重映射为nfilt保证配置兼容。这些参数与测试脚本、C 推理端的特征提取配置一一对应见第六节是导出即对齐的关键。4.3 v2 / v3 / v3-punct 变体v2export-onnx-ctc-v2.py改用gigaam.load_model(v2_ctc)通过model.to_onnx(.)导出词表同样来自model.cfg[labels]产出文件名为v2_ctc.onnx随后量化为统一的model.int8.onnxv3export-onnx-ctc-v3.py词表取自model.cfg[decoding][vocabulary]配置注释中给出了完整的 v3 模型结构ConformerEncoder16 层d_model 7688 倍 FFN 扩展16 头 rotary 自注意力conv1d 下采样核 5CTC 输出 34 类空格 32 个俄语字符 blankv3-punctexport-onnx-ctc-v3-punct.py带标点版本v3_e2e_ctc输出维度提升到257BPE 词表词表通过model.decoding.tokenizer.modelsentencepiece 模型生成并在元数据中额外写入comment: v3以区分版本。五、RNNT 模型导出encoder / decoder / joiner 三分结构RNNTTransducer架构与 CTC 不同export-onnx-rnnt.py 将模型拆分为三个独立 ONNX 文件model EncDecRNNTBPEModel.from_config_file(./rnnt_model_config.yaml) # ... model.encoder.export(encoder.onnx) model.decoder.export(decoder.onnx) model.joint.export(joiner.onnx)要点词表RNNT 使用 BPE 词表直接取自model.joint.vocabulary同样把blk追加为最后一个 id写入tokens.txt元数据写入 encoder.onnx并额外包含解码器结构信息meta_data { vocab_size: model.decoder.vocab_size, # 不含 blankC 端会自行加 1 pred_rnn_layers: model.decoder.pred_rnn_layers, # 预测网络 LSTM 层数 pred_hidden: model.decoder.pred_hidden, # 预测网络隐藏维度 normalize_type: , subsampling_factor: 4, model_type: EncDecRNNTBPEModel, language: Russian, is_giga_am: 1, ... }量化仅针对encoderencoder.int8.onnxdecoder 与 joiner 保持 FP32test-onnx-rnnt.py通过meta[pred_rnn_layers]/meta[pred_hidden]动态构造 decoder 的初始 LSTM 状态见第七节。六、特征提取协议Fbank 参数与模型输入输出6.1 Fbank 特征参数导出端、测试端、推理端三方一致两个测试脚本中的create_fbank()完全一致定义了 GigaAM 系列模型的统一特征协议opts.frame_opts.dither 0 opts.frame_opts.remove_dc_offset False opts.frame_opts.preemph_coeff 0 opts.frame_opts.window_type hann opts.frame_opts.round_to_power_of_two False opts.mel_opts.low_freq 0 opts.mel_opts.high_freq 8000 opts.mel_opts.num_bins 64 # 64 维 Fbank音频统一按16 kHz单声道处理fbank.accept_waveform(16000, audio)特征维度为64。这一数值与 C 推理端源码注释相互印证offline-transducer-nemo-model.cc 中明确写道 giga am uses 64即 GigaAM 使用 64 维特征而 parakeet-tdt-0.6b-v2 用 128 维、其余 NeMo 模型默认 80 维——推理端正是依据is_giga_am元数据动态选择特征维度。6.2 CTC 模型的 IO 协议test-onnx-ctc.py中display()打印的 ONNX 图结构脚本第 59-65 行注释Input : audio_signal (float) [batch, 64, T] # 特征矩阵 [C, T] length (int64) [batch] # 帧数 Output: logprobs (float) [batch, T, 34] # T T / subsampling_factor推理时需将[T, C]的特征转置为[1, C, T]并传入 int64 的帧长度x torch.from_numpy(x).t().unsqueeze(0) # [1, C, T] x_lens torch.tensor([x.shape[-1]], dtypetorch.int64) log_probs self.model.run([output_name], {input_name: x.numpy(), length_name: x_lens.numpy()})[0]6.3 RNNT 模型的 IO 协议test-onnx-rnnt.py打印的三段图结构脚本第 53-75 行注释encoder输入audio_signal [1, 64, T]与length (int64)输出outputs [1, 768, T]d_model768与encoded_lengthsdecoder预测网络输入targets (int32) [1, 1]、target_length (int32)、两组 LSTM 状态[1, 1, 320]输出outputs [1, 320, 1]与更新后的状态——即320 维、可迭代的 RNN 状态机joiner输入 encoder 输出[1, 768, 1]与 decoder 输出[1, 320, 1]输出[1, 1, 1, 513]vocab_size 含 blank。七、测试脚本验证导出的 ONNX 模型7.1 CTC 解码测试test-onnx-ctc.py 加载model.int8.onnx与tokens.txt用soundfile读取example.wav多声道时取第一通道非 16 kHz 时用librosa.resample重采样随后用 kaldi-native-fbank 计算 64 维 Fbank前向得到log_probs [1, T, 34]执行贪心 CTC 解码argmax取每帧最佳 token跳过 blank 并合并相邻重复 tokenblank len(id2token) - 1 prev -1 for i in ids: if i ! blank and i ! prev: ans.append(i) prev i最终把 token id 序列映射回俄语字符并拼接打印。7.2 RNNT 帧同步解码测试test-onnx-rnnt.py 实现的是帧同步frame-sync贪心 Transducer 解码流程更贴近 sherpa-onnx 的流式/离线推理逻辑在音频尾部拼接2 秒静音tail_padding np.zeros(sample_rate * 2)保证尾部 token 有足够帧触发 joiner 输出用全零初始化 decoder 的 LSTM 状态pred_rnn_layers × batch × pred_hidden先用 blank token 走一次 decoder 获得初始decoder_out对 encoder 输出的每一帧t将encoder_out[:, :, t:t1]与当前decoder_out送入 joinerargmax后若结果不是 blank则把新 token 追加进答案并用它更新 decoder 状态继续下一轮最后移除开头的 blank将 BPE token▁下划线前缀代表词边界还原为空格分隔的俄语文本text .join(tokens).replace(▁, ).strip()这套encoder 一次性前向 decoder 逐帧迭代的流程正是 sherpa-onnx 中 offline-transducer-nemo-model.cc 加载 RNNT 模型后的推理范式缩影。八、与 sherpa-onnx 推理端的集成导出脚本写入的元数据在推理端被显式读取offline-nemo-enc-dec-ctc-model.cc 读取vocab_size、subsampling_factor、normalize_type并通过SHERPA_ONNX_READ_META_DATA_WITH_DEFAULT(is_giga_am_, is_giga_am, 0)读取 GigaAM 标志offline-transducer-nemo-model.cc 对 RNNT 模型做同样处理并依据is_giga_am决定feat_dim_取 64见该文件第 321-324 行注释。is_giga_am的默认值为 0因此只有经过本目录脚本导出的模型才会携带该标志并触发 GigaAM 专用特征参数其余 NeMo 模型不受影响——这正是转换脚本决定推理行为的设计所在。在 Python API 侧导出的模型可直接通过OfflineRecognizer.from_nemo_ctc加载使用参见 offline-nemo-ctc-decode-files.pyrecognizer sherpa_onnx.OfflineRecognizer.from_nemo_ctc( modelmodel, # model.onnx 或 model.int8.onnx tokenstokens, # tokens.txt debugTrue, # 打印模型元数据便于核对 ) stream recognizer.create_stream() stream.accept_waveform(sample_rate, audio) # 任意采样率均可内部自动处理 recognizer.decode_stream(stream)from_nemo_ctc会根据 ONNX 内的元数据自动选择 CTC 解码逻辑RNNT 模型则对应OfflineRecognizer.from_transducer系列的 NeMo 加载路径。九、许可与注意事项模型许可GigaAM 模型附带GigaAM License_NC.pdfNon-Commercial 许可转换与部署前务必逐条核对许可条款原始 README 亦指向模型仓库的 LICENSE 文件见 scripts/nemo/GigaAM/README.md 末尾说明导出脚本会把许可信息写入 ONNX 元数据的license字段便于模型分发时追溯。版本对应关系v1 脚本依赖 NVIDIA NeMo 工具链 独立 checkpoint/config 文件v2/v3 依赖官方gigaamPython 包模型权重由包内下载机制管理。选择脚本时请与目标模型版本严格对应混用会导致配置与权重不匹配加载时使用strictFalse只能容忍少量键差异。量化产物INT8 量化仅覆盖权重动态量化encoder 是 RNNT 中计算量最大的部分因此优先量化 encoder若追求更高精度可继续使用 FP32 的model.onnx/encoder.onnx。特征对齐导出、测试、推理三端的 Fbank 参数16 kHz、64 维、hann 窗、0–8 kHz 频带必须保持一致任何一端改动都会破坏识别结果这也是is_giga_am元数据在 C 端被强制读取的原因。【免费下载链接】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),仅供参考