
NeMo ASRVAD 推理管线实战指南基于 VAD 分段语音识别的完整流程与源码解析【免费下载链接】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本文以 NVIDIA NeMo 仓库当前项目根目录/data/web/disk1/git_repo/GitHub_Trending/nem/Speech中 examples/asr/asr_vad/README.md 为骨架结合 speech_to_text_with_vad.py 及 VAD 工具库源码系统讲解 ASRVAD 联合推理管线的输入输出格式、命令参数、Frame-VAD / Segment-VAD 两种模式、基于 RTTM 的非语音段特征处理策略以及每个关键参数在底层代码中的实际作用。读完本文你将能直接上手运行先语音活动检测、后语音识别的完整推理流程也能独立配置 VAD 后处理参数以获得理想的语音分段效果。一、管线概览ASR 与 VAD 如何协同工作speech_to_text_with_vad.py提供了一条完整的ASRVAD 推理管线同时支持三种运行模式ASR VAD 联合推理先用 VAD 模型检测语音/非语音区间再仅对语音部分进行 ASR 转写默认模式仅 ASR跳过 VAD直接对整段音频做语音识别仅 VAD只做语音活动检测输出语音分段结果不进行转写。从源码主函数 main() 可以看出整条管线按顺序执行三个核心阶段prepare_inference_manifest(cfg)规范化输入清单manifest 或音频目录extract_audio_features(...)使用 VAD 模型的 preprocessor 提取并缓存音频特征.pt 文件若配置了vad_model执行run_vad_inference(...)生成语音分段RTTM若配置了asr_model执行run_asr_inference(...)基于分段结果完成转写并计算 WER/CER。这三个阶段依次执行中间产物特征文件、VAD 预测、RTTM都会被写入输出目录因此重复运行同一任务时如果中间结果已存在程序会自动跳过已完成的阶段详见下文断点续跑说明。二、输入格式Manifest 与音频目录两种方式管线支持两种输入形式由InferenceConfig中的manifest_filepath与audio_dir两个字段控制源码见 InferenceConfig输入方式配置参数说明Manifest 清单manifest_filepath/PATH/TO/MANIFEST.json每行一个 JSON 字典的清单文件字段要求严格音频目录audio_dir/PATH/TO/AUDIOSaudio_typewav自动扫描目录下所有指定类型的音频文件audio_type默认为wav2.1 Manifest 必备字段Manifest 是 NeMo 生态通用的 JSON Lines 格式每一行必须是一个合法的 Python 字典其中[audio_filepath, offset, duration]三个字段为必需项{audio_filepath: /path/to/audio_file1, offset: 0, duration: 10000} {audio_filepath: /path/to/audio_file2, offset: 0, duration: 10000}各字段含义audio_filepath音频文件的绝对路径或相对路径程序会自动尝试基于 manifest 所在目录解析offset从音频的哪个时间点秒开始处理duration要处理的音频时长秒。注意示例中写的是10000即处理从offset开始长达 10000 秒的音频实际会被音频总长度截断等效于处理整段音频。2.2 提供文本标注以计算 WER如果希望管线在转写完成后自动计算WER词错误率需要在 manifest 中额外提供text字段作为 ground truth{audio_filepath: /path/to/audio_file1, offset: 0, duration: 10000, text: hello world} {audio_filepath: /path/to/audio_file2, offset: 0, duration: 10000, text: hello world}当 manifest 中不存在text字段时run_asr_inference会统计生成的字数/词数并打印存在text时则调用word_error_rate同时计算并打印 WER 与 CER源码见 run_asr_inference----------------------------------------- WER0.0432, CER0.0125 -----------------------------------------2.3 音频目录输入的内部处理当audio_dir不为空且未提供manifest_filepath时prepare_inference_manifest 会递归扫描目录下所有*.{audio_type}文件为每个文件生成{audio_filepath: ..., duration: 1000000, offset: 0}条目并自动写入输出目录下的temp_manifest_input.json。同时该函数还会对 manifest 中的相对路径做归一化若audio_filepath长度小于 255、不是绝对路径且相对 manifest 所在目录可找到文件则自动拼接为绝对路径并统一补上labelinfer、text-两个字段。三、输出VAD 预测、RTTM 分段与转写清单输出写入output_dir默认./outputs主要内容包括产物路径/命名说明音频特征outputs/features/*.pt每段音频提取的 log-mel 特征torch tensor帧级 VAD 预测outputs/vad_frame_pred/*.frame每行一个 speech 概率值对应一个 VAD 帧语音分段RTTMoutputs/vad_rttm-{postprocessing 参数拼接}/*.rttm每个语音段的起止时间与时长转写结果清单outputs/{原清单名}-{ASR模型名}-{tag}.json每行在原条目基础上追加pred_text、feature_file、rttm_file中间清单temp_manifest_input.json、temp_manifest_input_feature.json、temp_manifest_{seg}_*.json各阶段传递的临时数据其中 RTTM 分段目录名会把后处理参数拼进目录名如vad_rttm-onset0.3offset0.3pad_onset0.2...源码见 run_vad_inference便于对比不同后处理参数的效果。四、快速上手运行 ASRVAD 推理以默认设置运行 ASRVAD 联合推理在examples/asr/asr_vad目录下执行python speech_to_text_with_vad.py \ manifest_filepath/PATH/TO/MANIFEST.json \ vad_modelvad_multilingual_frame_marblenet \ asr_modelstt_en_conformer_ctc_large \ vad_config../conf/vad/frame_vad_infer_postprocess.yaml参数说明manifest_filepath输入清单路径必填除非使用audio_dirvad_modelVAD 模型名。可传.nemo本地模型路径、.ckpt检查点路径或 NGC 上的预训练模型名如vad_multilingual_frame_marblenet。init_frame_vad_model会按上述顺序依次尝试加载见 vad_utils.pyasr_modelASR 模型名同样支持.nemo/.ckpt/ NGC 预训练名三种来源见 init_asr_modelvad_configVAD 后处理 YAML 配置文件路径见下文第六节。提示若使用音频目录输入将manifest_filepath替换为audio_dir/PATH/TO/AUDIOS audio_typewav即可audio_type默认值就是wav。4.1 仅使用 ASR关闭 VAD设置vad_modelNone且use_rttmFalse管线将跳过 VAD 阶段直接对整段音频转写python speech_to_text_with_vad.py \ manifest_filepath/PATH/TO/MANIFEST.json \ asr_modelstt_en_conformer_ctc_large \ vad_modelNone \ use_rttmFalse4.2 仅使用 VAD不转写设置asr_modelNone同时指定vad_model与vad_config管线只输出语音分段python speech_to_text_with_vad.py \ manifest_filepath/PATH/TO/MANIFEST.json \ vad_modelvad_multilingual_frame_marblenet \ asr_modelNone \ vad_config../conf/vad/frame_vad_infer_postprocess.yaml4.3 开启性能剖析设置profilingTrue可启用 PyTorch Profiler对 CPU/CUDA 各阶段耗时、显存占用进行记录并在结束后打印按cuda_time_total排序的前 15 行统计表源码见 main。注意profiling 会显著拖慢程序运行速度仅建议在性能排查时临时开启。五、基于 RTTM 的非语音段特征处理VAD 阶段会把检测出的语音分段写入 RTTM 文件ASR 阶段可以选择用这些分段信息屏蔽非语音区域的特征避免模型对静音/噪声段产生无效输出。相关参数如下5.1 use_rttm 与 rttm_modeuse_rttmTrue/False是否启用 RTTM 特征处理默认Truerttm_modeRTTM 的使用方式仅可为mask或dropmask用 RTTM 分段信息掩蔽非语音段的特征把特征值替换为feat_mask_val特征序列长度保持不变drop直接丢弃非语音段的特征仅保留语音段特征送入 ASR特征序列变短。源码中这两个参数被透传给feature_to_text_dataset.get_bpe_dataset / get_char_dataset见 feature_to_text_dataset.py 与 run_asr_inference由数据集的use_rttm、rttm_mode、feat_mask_val、frame_unit_time_secs等字段控制实际的特征裁剪/掩蔽逻辑。5.2 实践建议drop 模式要留足 padding文档与代码均建议当rttm_modedrop时应使用更大的pad_onset和pad_offset在 VAD 配置的postprocessing中设置以避免 VAD 边界误差导致语音特征被误删。因为 drop 模式是硬性裁剪边界上的轻微误差会直接丢掉有效语音。5.3 feat_mask_val掩蔽值设置feat_mask_val可指定掩蔽时使用的具体特征值。默认feat_mask_valNone此时程序自动选择默认值normalizepost_norm时使用-16.530零 log-mel 谱特征值即log(1e-7)量级的静音特征——README 中写作 -16.530脚本 docstring 中写作 -16.635二者是同一概念的不同精度表述实际以运行时打印的feat_mask_val为准normalizepre_norm时使用0与 SpecAugment 的掩蔽值一致即特征归一化前的 0 值。5.4 normalize掩蔽与归一化的先后顺序normalize决定特征归一化与掩蔽的先后关系normalizepre_norm先归一化、后掩蔽normalizepost_norm先掩蔽、后归一化默认值。配套参数normalize_type默认per_feature决定计算均值/方差的方式normalize_audio_db默认None可设置为数值以在特征提取前对音频做 RMS DB 归一化这两个参数同样会传入特征提取与 ASR 数据集的配置中。六、Frame-VAD 与 Segment-VAD 两种模式VAD 模型分为两类由vad_type参数选择默认frame源码在 run_vad_inference 中据此分别调用init_frame_vad_model加载EncDecFrameClassificationModel或init_vad_model加载EncDecClassificationModel。6.1 Frame-VAD帧级 VADpython speech_to_text_with_vad.py \ manifest_filepath/PATH/TO/MANIFEST.json \ vad_modelvad_multilingual_frame_marblenet \ asr_modelstt_en_conformer_ctc_large \ vad_config../conf/vad/frame_vad_infer_postprocess.yaml对每个20ms音频帧输出一个 speech/non-speech 预测对应的 frame_vad_infer_postprocess.yaml 中shift_length_in_sec: 0.0220ms 帧长与window_length_in_sec: 0.0帧级 VAD 必须为 0无需滑窗上下文是预训练 Frame-VAD 模型如vad_multilingual_frame_marblenet的固定约束不可随意改动帧级预测结果保存为.frame文件每行一个概率值generate_vad_frame_pred中逐行写入见 speech_to_text_with_vad.py。6.2 Segment-VAD分段级 VADpython speech_to_text_with_vad.py \ manifest_filepath/PATH/TO/MANIFEST.json \ vad_modelvad_multilingual_marblenet \ asr_modelstt_en_conformer_ctc_large \ vad_typesegment \ vad_config../conf/vad/vad_inference_postprocessing.yaml将音频切分为重叠的短分段对每个分段独立做 VAD 分类最后把各分段的预测拼接成完整语音分段表分段大小与步长由 VAD 配置中的window_length_in_sec与shift_length_in_sec控制对应的 vad_inference_postprocessing.yaml 中默认值分别为0.63 秒和0.08 秒0.08s 步长用于更快的推理Segment-VAD 可配合重叠平滑smoothing设为median或meanoverlap0.875对重叠分段的预测做多数表决/平均提升边界稳定性——该逻辑由generate_overlap_vad_seq实现见 vad_utils.py。注意smoothing与overlap在 Frame-VAD 配置中已标记为 Deprecated仅对 Segment-VAD 有意义。七、VAD 后处理配置详解两份配置文件的vad.parameters.postprocessing字段控制帧级概率 → 语音分段的转换核心参数如下Frame-VAD 与 Segment-VAD 配置中默认值略有差异参数Frame-VAD 默认值Segment-VAD 默认值作用onset0.30.5语音开始判定阈值概率超过该值认为进入语音offset0.30.3语音结束判定阈值概率低于该值认为语音结束pad_onset0.20.2每个语音段前额外填充的时长秒防止切掉语音起始pad_offset0.20.2每个语音段后额外填充的时长秒min_duration_on0.20.5小于该时长的语音段将被删除短语音滤波min_duration_off0.20.5小于该时长的非语音间隙将被合并到语音段filter_speech_firstTrueTrue滤波执行顺序先滤语音段还是先合并间隙底层转换由generate_vad_segment_table调用binarization阈值二值化与filtering短段滤波/间隙合并完成见 vad_utils.py 与generate_vad_segment_table_per_tensor最终按 RTTM 格式写出SPEAKER NA 1 0.3200 0.5600 NA NA speech NA NAFrame-VAD 配置中另有两个与长音频处理相关的字段prepare_manifest.auto_split: true自动按split_duration切分超长音频避免 CUDA 显存溢出prepare_manifest.split_duration: 400单条最长秒数若仍显存不足可调小。八、断点续跑与临时数据整个管线以产物是否已存在作为阶段跳过的依据具备天然的断点续跑能力若outputs/features/temp_manifest_input_feature.json已存在特征提取阶段直接跳过extract_audio_features若outputs/vad_frame_pred目录已存在帧级预测阶段直接跳过若outputs/vad_rttm-{参数拼接}目录已存在分段生成阶段直接跳过。因此若需调整后处理参数如onset/pad_onset或更换 ASR 解码方式不必重跑特征提取与 VAD 预测——只需删除对应阶段的输出目录或修改配置后重跑管线会复用已有中间产物。所有临时文件都落在output_dir默认./outputs中不会污染输入数据。九、进阶参数InferenceConfig 全字段速查除前述参数外InferenceConfig数据类speech_to_text_with_vad.py还提供以下可直接在命令行覆盖的选项参数默认值说明batch_size1ASR 批大小。注意特征提取与 VAD 仅支持单样本/批内部强制 batch1num_workers8DataLoader 工作进程数sample_rate16000音频采样率frame_unit_time_secs0.01单帧时长秒须与 ASR 配置中的window_stride一致通常 10msaudio_typewavaudio_dir模式下扫描的音频扩展名output_dir./outputs输出目录可覆盖output_filename自动生成转写结果清单文件名默认按模型名处理方式拼装pred_name_postfixNone自定义输出文件名后缀compute_langsFalse置 True 时输出语言 ID 信息需模型支持ctc_decodingCTCDecodingConfig()CTC 解码策略配置rnnt_decodingRNNTDecodingConfig(fused_batch_size-1)RNNT 解码策略配置解码策略的自动选择逻辑值得注意见 run_asr_inference若传入额外参数decoder_typernnt/ctc按 Hybrid 模型处理分别调用rnnt_decoder_predictions_tensor或ctc_decoder_predictions_tensor否则若模型具有joint属性RNNT 模型走 RNNT 解码否则按 CTC 模型处理并自动从asr_model.decoder.vocabulary读取字符表。十、运行前置条件环境需安装本项目 NeMopip install nemo_toolkit[asr]或从仓库源码安装参见 README.md并保证 CUDA 环境可用代码会自动回退到 CPU但推理会明显变慢模型下载vad_model/asr_model传 NGC 预训练模型名时程序首次运行会自动下载模型权重需保持网络连通也可预先将模型导出为.nemo文件传入本地路径离线使用音频格式默认要求 16kHz 单声道音频若采样率不一致需先重采样或在 manifest 中按实际时长正确填写offset/duration运行位置示例脚本与配置采用相对路径../conf/vad/...建议在examples/asr/asr_vad目录下执行或将vad_config改为绝对路径。总结speech_to_text_with_vad.py是 NeMo 中VAD 前置过滤 ASR 精准转写的标准参考实现一条命令即可在整段长音频上自动完成语音活动检测、语音分段RTTM、分段转写与 WER/CER 评估。理解 Frame-VAD 与 Segment-VAD 的差异、mask/drop两种 RTTM 处理策略以及postprocessing各阈值对分段质量的影响是把它应用到生产场景电话录音转写、会议语音、长音频批处理的关键。建议以本仓库的 asr_vad 示例、frame_vad_infer_postprocess.yaml 与 vad_inference_postprocessing.yaml 为起点结合 vad_utils.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创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考