NeMo 流式语音推理实战:asr_streaming_infer.py 通用流式推理指南
【免费下载链接】SpeechA scalable generative AI framework built for researchers and developers working on Large Language Models, Multimodal, and Speech AI (Automatic Speech Recognition and Text-to-Speech)项目地址: https://gitcode.com/GitHub_Trending/nem/Speech
本文以 NeMo 开源仓库中 examples/asr/asr_streaming_inference/ 的asr_streaming_infer.py脚本及其配套配置为核心,系统讲解如何使用 NeMo 在本地完成 buffered(CTC/RNNT/TDT)与 cache-aware(CTC/RNNT)两类流式 ASR 推理,并进一步集成逆文本正则化(ITN)、句末检测(EoU)、流式语音翻译、词级/段级输出与 WER/BLEU/RTFx/LAAL 指标评估。读完本文,你将能基于仓库内的真实配置与源码调用链,从零跑通单文件、目录与 manifest 三种输入形态的流式转写任务。
一、脚本定位:一套脚本覆盖多种流式推理范式
asr_streaming_infer.py是 NeMo 仓库中面向"通用流式推理(Universal Streaming Inference)"的本地推理入口脚本。根据 README.md 的定义,它同时支持:
- buffered 流式推理:适用于 CTC、RNNT、TDT 解码的 ASR 模型;
- cache-aware 流式推理:适用于 CTC、RNNT 解码的 ASR 模型,核心特征是跨 chunk 复用注意力缓存(cache),避免重复计算历史帧。
输入形态支持三种:单个音频文件、音频文件目录、manifest 文件。脚本内部通过PipelineBuilder根据pipeline_type字段自动路由到对应的流水线实现(详见下文"源码级工作流"一节)。
除转写外,脚本还集成以下能力(README 明确列出的五项):
| 能力 | 说明 |
|---|---|
| 逆文本正则化(ITN) | 将 ASR 原始输出(如 "one hundred twenty five dollars")还原为书面格式("$125"),由enable_itn开关控制 |
| 句末检测(EoU) | 基于endpointing配置判断语音停顿边界,输出语句级切分结果 |
| 流式语音翻译(ST) | 在转写基础上调用 vLLM 支撑的 LLM 完成流式翻译,需要预先安装 vLLM,由enable_nmt开关控制 |
| 词级输出 | asr_output_granularity=word时输出带时间戳的词级结果 |
| 段级输出 | asr_output_granularity=segment时输出段级结果(默认) |
所有相关配置集中在仓库的 examples/asr/conf/asr_streaming_inference/ 目录,共五个 YAML 文件:
examples/asr/conf/asr_streaming_inference/ ├── buffered_ctc.yaml # buffered + CTC 解码(默认模型 parakeet-ctc-1.1b) ├── buffered_rnnt.yaml # buffered + RNNT 解码(默认模型 parakeet-unified-en-0.6b) ├── buffered_salm.yaml # buffered + SALM 解码(默认模型 canary-qwen-2.5b) ├── cache_aware_ctc.yaml # cache-aware + CTC 解码(默认模型 fastconformer hybrid streaming) └── cache_aware_rnnt.yaml # cache-aware + RNNT 解码(默认模型 nemotron-speech-streaming-en-0.6b)二、运行环境与输入数据准备
2.1 依赖与前置条件
- 本脚本基于 Hydra 配置系统驱动(
@hydra.main(version_base=None)),启动时通过--config-path与--config-name指定配置目录与文件名; - 使用流式语音翻译(NMT)功能时,必须安装 vLLM 并保证
nmt.device指向可用的 CUDA 设备(配置注释明确cpu不受支持); - ITN 依赖
nemo_text_processing(其底层依赖 pynini)。源码中对该库做了容错处理:若导入失败仅打印警告并继续运行,不影响纯 ASR 推理(见 asr_streaming_infer.py)。
2.2 输入音频约束
源码 docstring(asr_streaming_infer.py)明确要求:
输入音频必须是16 kHz、单声道(mono)WAV 文件。
manifest 场景下,脚本通过prepare_audio_data读取条目并按键(如audio_filepath、text)组织数据,支持后续按时长排序以优化批处理。源码中已通过sort_by_duration=True启用按时长排序(见 asr_streaming_infer.py)。
三、命令行用法与核心参数
脚本的通用调用方式(源码 docstring 与配置注释共同给出)为:
python asr_streaming_infer.py \ --config-path=../conf/asr_streaming_inference/ \ --config-name=buffered_ctc.yaml \ audio_file=<音频文件 | 音频目录 | manifest 文件路径> \ output_filename=<输出 json 文件路径> \ lang=en \ enable_itn=False \ enable_nmt=False \ asr_output_granularity=segment若从仓库根目录运行,可写作:
python examples/asr/asr_streaming_inference/asr_streaming_infer.py \ --config-path=examples/asr/conf/asr_streaming_inference/ \ --config-name=buffered_ctc.yaml \ audio_file=path/to/audio.wav \ output_filename=output.json \ lang=en3.1 运行时参数(CLI 可覆盖)
以下参数在配置文件中预置默认值,运行时可通过命令行覆盖(五个 YAML 中一致定义):
| 参数 | 默认值 | 说明 |
|---|---|---|
audio_file | null | 音频文件、目录或 manifest JSON 路径 |
output_filename | null | 输出转写 JSON 文件路径 |
output_dir | null | 保存带时间对齐输出的目录 |
enable_itn | false | 是否应用逆文本正则化 |
enable_nmt | false | 是否应用神经机器翻译(流式翻译) |
asr_output_granularity | segment | 输出粒度:word或segment |
cache_dir | null | 缓存目录(如 ITN 生成的.far文件) |
lang | null | ASR 模型的语言代码 |
return_tail_result | false | 是否返回右侧 padding 缓冲区内遗留的尾部标签 |
calculate_wer | true | 是否计算 WER(需 manifest 提供标注) |
calculate_bleu | true | 是否计算 BLEU(翻译场景,需 manifest 提供参考答案) |
warmup_steps | 0 | 计算 RTFx/LAAL 前的预热步数 |
run_steps | 1 | 正式运行步数(用于 RTFx/LAAL 测量取平均) |
注意:
run_steps必须 ≥ 1,否则脚本直接抛出ValueError("run_steps must be at least 1");且 RTFx 测量建议warmup_steps > 0,脚本在warmup_steps=0时会打印相应警告(见 asr_streaming_infer.py)。
3.2 输出 JSON 结构
转写结果写入输出文件,单条记录的固定结构为(源码 docstring 定义):
{"audio_filepath": "path/to/audio/file", "text": "transcription of the audio file", "json_filepath": "path/to/json/file"}词级/段级对齐结果则写入单独的 JSON 文件(由output_dir控制落盘位置,见 asr_streaming_infer.py)。
四、配置详解:五个 YAML 逐个拆解
所有配置文件共享统一的区块结构:asr、itn、nmt、confidence、endpointing、streaming、pipeline settings、runtime arguments、metrics。差异集中在asr、streaming与pipeline_type/asr_decoding_type。
4.1 公共区块:ASR 模型与精度
以 buffered_ctc.yaml 为例:
asr: model_name: nvidia/parakeet-ctc-1.1b # 预训练模型名(NGC/HuggingFace)或本地 .nemo 文件路径 device: cuda # 推理设备:'cuda' 或 'cpu' device_id: 0 # GPU 设备 ID compute_dtype: bfloat16 # 'bfloat16'(Ampere+)、'float16'(旧 GPU)或 'float32' use_amp: false # 是否启用自动混合精度各配置文件的默认模型:
| 配置 | 默认模型 | 解码类型 |
|---|---|---|
| buffered_ctc.yaml | nvidia/parakeet-ctc-1.1b | ctc |
| buffered_rnnt.yaml | nvidia/parakeet-unified-en-0.6b | rnnt |
| buffered_salm.yaml | nvidia/canary-qwen-2.5b | salm |
| cache_aware_ctc.yaml | stt_en_fastconformer_hybrid_large_streaming_multi | ctc |
| cache_aware_rnnt.yaml | nvidia/nemotron-speech-streaming-en-0.6b | rnnt |
在 RNNT 类配置(buffered_rnnt.yaml 与 cache_aware_rnnt.yaml)中,还额外提供decoding与per_stream_biasing_defaults两个深化选项:
decoding.strategy:greedy_batch(默认)或malsd_batch(cache-aware 下仅支持 MALSD 束搜索,配置注释明确说明);decoding.greedy:可启用 CUDA graph 解码器(use_cuda_graph_decoder)、逐流偏置(enable_per_stream_biasing)、帧级置信度保留(preserve_frame_confidence)与max_symbols上限;- n-gram LM 融合:
ngram_lm_model指定构建好的.nemoNGPU-LM 模型路径,ngram_lm_alpha控制语言模型权重(默认 0.0 表示关闭); - 短语增强(phrase boosting):
boosting_tree.model_path指定 boosting tree 模型;key_phrases_file提供每行一个短语的列表文件;key_phrases_list直接给出行内短语列表;key_phrase_items_list支持带自定义字段(如语言标签)的短语,CLI 形式如[{phrase:"word1",lang:en},{phrase:"frase dos",lang:es}];source_lang用于聚合分词器场景; per_stream_biasing_defaults.boosting_model_cfg:bpe_mode可选default/bpe_dropout/var_bpe/case_insensitive(推荐case_insensitive或default),var_bpe_scoring_temp默认 10.0(对 case_insensitive/var_bpe 模式的保守值,防止过度偏置;小规模偏置表配合束搜索时 0.1~2.0 效果更佳)。
cache_aware_rnnt.yaml 还额外支持asr.use_cuda_graphs:开启后可为 cache-aware 编码器流式步骤启用 CUDA graphs(要求use_amp=false)。
4.2 公共区块:ITN 配置
五个配置中itn区块完全一致:
itn: input_case: lower_cased # 输入文本大小写:'lower_cased' 或 'cased' whitelist: null # ITN 处理的自定义白名单 overwrite_cache: false # 是否覆盖已有缓存文件 max_number_of_permutations_per_split: 729 # 每个文本分片允许的最大排列数 left_padding_size: 4 # ITN 上下文左侧 padding 大小(#spans) batch_size: 32 # ITN 推理批大小 n_jobs: 16 # ITN 处理并行任务数4.3 公共区块:流式翻译(NMT)配置
nmt: model_name: "utter-project/EuroLLM-1.7B-Instruct" # vLLM 支持的模型名 source_language: "English" # 源语言 target_language: "Russian" # 目标语言 waitk: -1 # 允许的最大延迟(词数);-1 禁用,仅用当前/前次翻译的最长公共前缀 device: cuda # 翻译设备,仅支持 cuda device_id: 1 # 翻译使用的 GPU ID(可与 ASR 分卡) batch_size: 16 # 翻译批大小;-1 表示与 ASR 批大小一致 llm_params: dtype: "auto" # 计算精度 seed: 42 # 采样随机种子 gpu_memory_utilization: 0.85 # vLLM 允许占用的 GPU 显存比例 max_model_len: 4096 # 模型最大 token 长度 sampling_params: max_tokens: 100 # LLM 最大生成 token 数 temperature: 0.0 # 采样温度,翻译默认 0(贪心) top_p: 0.9 # 核采样累积概率阈值 seed: 42要点:翻译与 ASR 可分配不同 GPU(asr.device_id与nmt.device_id独立设置);waitk参数直接决定流式翻译的"追随延迟"策略——设置为 -1 时采用最长公共前缀策略,每次只输出与上次结果公共前缀一致的内容,保证流式下译文不"回退"。
4.4 公共区块:置信度估计
confidence: exclude_blank: true # 计算置信度时排除 blank token aggregation: mean # 跨时间步聚合方式 method_cfg: name: entropy # 方法:'max_prob' 或 'entropy' entropy_type: tsallis alpha: 0.5 entropy_norm: exp4.5 公共区块:句末检测(EoU)
endpointing: stop_history_eou: 800 # 评估 EoU 的时间窗口(毫秒) residue_tokens_at_end: 2 # 用于 EoU 判定的尾部残留 token 数4.6 流式配置:buffered 与 cache-aware 的关键差异
buffered 系列(以 buffered_ctc.yaml 为例):
streaming: sample_rate: 16000 # 音频采样率(Hz) batch_size: 256 # 每批音频帧数 left_padding_size: 1.6 # 左侧 padding 时长(秒) right_padding_size: 1.6 # 右侧 padding 时长(秒) chunk_size: 4.8 # 音频块大小(秒) word_boundary_tolerance: 4 # 词边界容差 request_type: feature_buffer # 请求类型:frame 或 feature_buffer padding_mode: right # padding 模式:left 或 rightbuffered_rnnt.yaml 在此基础上多出stateful: true(是否启用有状态处理);buffered_salm.yaml 则是 SALM 解码专属的滑动窗口式配置:
streaming: sample_rate: 16000 batch_size: 256 buffer_size: 8.0 # 缓冲时长(秒) chunk_size: 4.0 # 每个音频块时长(秒) overlap_size: 4.0 # 块间重叠时长(秒) merging_strategy: lcsubstr # 合并策略:lcs 或 lcsubstr request_type: frame max_new_tokens: 64 # 单次最大生成新 token 数cache-aware 系列(以 cache_aware_rnnt.yaml 为例):
streaming: sample_rate: 16000 batch_size: 64 word_boundary_tolerance: 4 att_context_size: [70,13] # 注意力上下文大小,可选 [70,13],[70,6],[70,1],[70,0] use_cache: true # 是否启用流式缓存 use_feat_cache: true # 是否缓存 mel 特征;false 则重算缓冲区内全部 mel 特征 chunk_size_in_secs: null # 每个流式步骤加载的音频时长;null 使用默认值(1+lookahead 帧) request_type: frame num_slots: 256 # 上下文管理器槽位数,必须 >= batch_sizecache-aware 与 buffered 的本质差异:cache-aware 通过use_cache/use_feat_cache跨 chunk 复用注意力缓存与 mel 特征缓存,att_context_size控制每步看到的上下文范围,从而在低延迟下避免重复前向计算;chunk_size_in_secs控制每步送入的音频量(如 FastConformer 常见 0.08s 级步长)。
att_context_size取值与模型相关,配置注释特别指出:[70,*] 适用于英文nemotron-speech-streaming-en-0.6b;多语言提示条件模型(如nvidia/nemotron-3.5-asr-streaming-0.6b)则应使用 [56,*] 系列([56,13],[56,6],[56,3],[56,1],[56,0])。
4.7 管道设置与指标配置
matmul_precision: high # 矩阵乘法精度:highest / high / medium log_level: 20 # 日志级别:0/10/20/30/40/50 pipeline_type: buffered # 管道类型:buffered 或 cache_aware asr_decoding_type: ctc # 解码方式:ctc / rnnt / salmmetrics区块按asr与nmt分组,控制 WER/BLEU 计算前的文本规范化行为:
metrics: asr: gt_text_attr_name: text # 标注文本的字段名 clean_groundtruth_text: false langid: en # 文本规范化语言,目前仅支持 "en" use_cer: false # 是否使用 CER 代替 WER ignore_capitalization: true # 忽略大小写 ignore_punctuation: true # 忽略标点 strip_punc_space: false nmt: gt_text_attr_name: answer # 翻译参考答案字段名(如 "answer") ignore_capitalization: false ignore_punctuation: false strip_punc_space: false五、源码级工作流:脚本到底做了什么
阅读 asr_streaming_infer.py 与 pipeline_builder.py,可以还原出完整的执行链路:
- 数据准备:
prepare_audio_data(cfg.audio_file, per_stream_biasing_defaults=..., sort_by_duration=True)读取输入(文件/目录/manifest),解析流级偏置选项并按时长排序;若为 manifest,日志打印其字段键列表; - 构建流水线:
PipelineBuilder.build_pipeline(cfg)首先校验并设置log_level与matmul_precision(合法值分别是 0/10/20/30/40/50 与 highest/high/medium,非法值直接抛错),然后通过PipelineType.from_str(cfg.pipeline_type)路由:BUFFERED→BufferedPipelineBuilderCACHE_AWARE→CacheAwarePipelineBuilder- 其他值 → 抛出
ValueError
- 预热与计时:按
warmup_steps + run_steps循环执行pipeline.run(...),使用SimpleTimer在指定 device 上计时,仅统计正式运行步; - RTFx 计算:
RTFx = 音频总时长 / 平均执行时长(data_dur / exec_dur),日志输出形如RTFx: 12.34 (100.00s / 8.10s); - LAAL 计算:
calculate_asr_laal计算 ASR 的 LAAL(最长允许音频延迟),calculate_translation_laal计算翻译 LAAL,单位毫秒; - 结果落盘:
dump_output将转写按audio_filepath/text/json_filepath结构写出; - 评估:
evaluate_pipeline(cfg.output_filename, cfg)依据metrics配置计算 WER(必要时 CER)与 BLEU。
关键调用链汇总:
asr_streaming_infer.py (hydra 入口) └─ nemo.collections.asr.inference.factory.pipeline_builder.PipelineBuilder.build_pipeline ├─ BufferedPipelineBuilder.build (pipeline_type=buffered) └─ CacheAwarePipelineBuilder.build (pipeline_type=cache_aware) └─ pipeline.run → 计算 RTFx / LAAL → dump_output → evaluate_pipeline这一设计意味着:换用不同的解码类型(CTC/RNNT/TDT/SALM)与流式范式时,无需改动脚本代码,只需切换--config-name与pipeline_type/asr_decoding_type。
六、可验证的测试与更多示例
仓库提供了与本文档直接对应的功能测试,可用于验证上述用法并观察完整命令:
- tests/functional_tests/L2_Speech_Transcription_Streaming_Inference.sh:流式转写功能测试,演示了该脚本的实际命令行调用方式与参数覆盖写法;
- tests/functional_tests/L2_Speech_Transcription_Speech_to_Text_Inference_Boost_GT.sh:验证短语增强(boosting)与转写加速场景的测试;
- 教程 tutorials/asr/Streaming_ASR_Pipelines.ipynb:以 Notebook 形式讲解流式 ASR 流水线的端到端使用;
- 若需 cache-aware 编码器 CUDA graphs,源码提示在命令行追加
asr.use_cuda_graphs=true即可(见 asr_streaming_infer.py)。
此外,模型训练侧对应的流式架构配置(如 FastConformer cache-aware 训练配置)位于 examples/asr/conf/fastconformer/cache_aware_streaming/,可作为理解att_context_size、chunk 等参数来源的补充参考。
七、常见问题与调参建议
- 输入格式:务必使用 16 kHz 单声道 WAV;否则需先行重采样/转码,可参考仓库中 examples/asr/transcribe_speech.py 等其他入口脚本的音频读取方式;
- RTFx 测量:首次运行建议
warmup_steps=2左右以预热 CUDA kernel 与缓存,再以run_steps取均值,避免首步计时偏慢导致 RTFx 虚低; - 翻译显存不足:降低
nmt.llm_params.gpu_memory_utilization(如 0.5)或减小max_model_len/max_tokens;也可将nmt.device_id指向独立 GPU 与 ASR 分卡; - cache-aware 下开启 CUDA graphs:注意
asr.use_cuda_graphs=true要求use_amp=false(见 cache_aware_rnnt.yaml 注释); - WER/BLEU 计算依赖标注:只有输入为 manifest 且包含
metrics.asr.gt_text_attr_name(默认text)/metrics.nmt.gt_text_attr_name(默认answer)字段时,指标才会被计算; - 流式翻译延迟控制:
nmt.waitk设置为 -1 时采用最长公共前缀策略,适合对译文稳定性要求高的场景;若追求更紧凑的追随延迟,可按词数设定waitk值。
通过本文介绍的单脚本多范式设计,开发者可以用同一套代码路径快速在 buffered 与 cache-aware 两种流式推理之间切换,并在转写基础上按需叠加 ITN、EoU 检测、流式翻译与细粒度对齐输出,是 NeMo ASR 流式落地的实用起点。
【免费下载链接】SpeechA scalable generative AI framework built for researchers and developers working on Large Language Models, Multimodal, and Speech AI (Automatic Speech Recognition and Text-to-Speech)项目地址: https://gitcode.com/GitHub_Trending/nem/Speech
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考