资讯动态

NeMo Forced Aligner(NFA)实战指南:基于 CTC 模型的 Token / 词 / 语句级语音时间戳对齐

发布时间:2026/9/14 8:59:08 来源:尧图企业网站定制
NeMo Forced AlignerNFA实战指南基于 CTC 模型的 Token / 词 / 语句级语音时间戳对齐【免费下载链接】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/SpeechNFANeMo Forced Aligner是 NVIDIA NeMo 语音工具链中专门用于强制对齐的命令行工具给定音频与参考文本它利用 NeMo 的 CTC 类 ASR 模型生成 token 级、词级与语句级的精确时间戳同时可输出 CTM 对齐文件与 ASS 卡拉 OK 式高亮字幕。本指南将以 tools/nemo_forced_aligner/README.md 为主线结合仓库源码完整讲解 NFA 的安装、数据准备、全部配置参数、输出格式、长音频流式对齐、EOU 边界检测与多 GPU 扩展帮助你在语音数据集清洗、音画字幕、发音评测与 ASR 训练数据切分等场景中直接落地使用。NFA 是什么给语音配上精确时间轴强制对齐Forced Alignment解决的核心问题是在已知语音内容参考文本的前提下逐 token、逐词地找出每一段内容在音频中的起止时间。与直接 ASR 转写不同对齐任务不再猜测说了什么而是把已知说了什么精确映射到时间轴上。NFA 的核心能力如下均可在 README 中得到印证多粒度时间戳同时产出 token 级、word 级、segment语句级三种粒度的对齐结果两种文本来源既可提供人工参考文本reference text也可让 ASR 先转写再以转写结果作为对齐参考align_using_pred_textTrue开箱即用的模型直接使用 NeMo 的 CTC ASR 预训练 checkpoint官方支持 14 种语言也可以加载你自己训练的模型长音频友好配合流式buffered chunked streaming与 cache-aware 流式推理可处理 1 小时以上的长音频实际取决于硬件与所选 ASR 模型。从源码看NFA 的完整流水线位于 tools/nemo_forced_aligner/ 目录核心入口为align.py基础版与align_eou.pyEOU/多机多卡增强版核心对齐算法Viterbi 解码、批处理变量构造、时间戳落盘位于 nemo/collections/asr/parts/utils/aligner_utils.py其中add_t_start_end_to_utt_obj第 621 行、viterbi_decoding第 726 行、get_batch_variables第 868 行构成了对齐主流程的三个关键函数。快速开始三步跑通第一个对齐任务第 1 步安装 NeMo含 ASR 集合NFA 依赖 NeMo 的 ASR 集合与aligner_utils工具模块。若缺少该依赖align.py 会在导入时报出明确的安装指引需要nemo-toolkit[all]2.5.0或安装最新开发版。NFA 自身的依赖声明见 requirements.txt核心仅nemo-toolkit[all]prettyprinter与pytest用于测试。第 2 步准备 NeMo 风格 manifestNFA 的输入是一个 JSONL 格式的 manifest 文件每行一个 JSON 对象。基础字段{audio_filepath: /path/to/audio1.wav, text: the quick brown fox jumps over the lazy dog} {audio_filepath: /path/to/audio2.wav, text: pack my box with five dozen liquor jugs}从 align.py 的校验逻辑main函数开头的 validate 段可以总结出如下硬性约束每一行必须包含audio_filepath字段由is_entry_in_all_lines(cfg.manifest_filepath, audio_filepath)校验当align_using_pred_textFalse默认时每一行必须包含text字段当align_using_pred_textTrue时manifest 中不得包含pred_text字段否则会引发RuntimeError因为模型转写结果可能与现有pred_text不一致造成混淆。manifest 读取时 data_prep.py 的get_manifest_lines_batch还会做若干预处理去除 BOM 字符、合并多余空格、把换行符转为空格、把水平省略号\u2026统一替换为...避免输出文件恢复标点时出错并对相对路径做基于 manifest 所在目录的解析。第 3 步运行 align.pyREADME 给出的最小化命令如下python path_to_NeMo/tools/nemo_forced_aligner/align.py \ pretrained_namestt_en_fastconformer_hybrid_large_pc \ manifest_filepathpath to manifest of utterances you want to align \ output_dirpath to where your output files will be saved在本仓库中即python tools/nemo_forced_aligner/align.py \ pretrained_namestt_en_fastconformer_hybrid_large_pc \ manifest_filepath/data/audio/manifest.json \ output_dir/data/alignment_out命令通过 Hydra 解析配置hydra_runner(config_nameAlignmentConfig, schemaAlignmentConfig)pretrained_name指定的 CTC 模型会自动从 NGC 下载若使用本地模型则改用model_path指定.nemo文件路径且model_path的优先级高于pretrained_name源码中二者互斥校验两者同时为空或同时非空都会抛出ValueError。模型选择与设备配置NFA 支持的模型类型NFA 目前只能使用 CTC 类模型Transducer 模型不支持这在 align.py 中有双重保证模型加载后若实例为EncDecHybridRNNTCTCModelRNNTCTC 混合模型会调用model.change_decoding_strategy(decoder_typectc)切换到 CTC 解码路径最终类型检查要求模型必须是EncDecCTCModel或EncDecHybridRNNTCTCModel的实例否则抛出NotImplementedError。典型可用模型包括stt_en_fastconformer_hybrid_large_pcREADME 示例等 FastConformer 系列。FastConformer 是 Conformer 架构因此可以开启use_local_attention加速推理源码中会调用model.change_attention_model(self_attention_modelrel_pos_local_attn, att_context_size[64, 64])把全局注意力替换为上下文窗口 64×64 的局部注意力仅当模型支持时才生效对齐精度仍由模型本身决定一般用于降低长音频推理开销。设备相关参数同样值得注意transcribe_device用于生成 log-probs转写阶段的设备取值需能被torch.device()识别默认None时自动选择cuda可用时否则cpuviterbi_device用于 Viterbi 解码的设备规则同上。源码会在任一设备为 GPU 时提示若遇到 OOM可尝试把两个设备都设为 CPU。此外batch_size默认 1同时作用于 log-probs 生成与 Viterbi 解码两个阶段必须 ≥ 1。对齐参数全解从文本分段到输出控制align.py 中的AlignmentConfig数据类完整定义了 NFA 的全部配置项下表按源码中的分组逐项说明分组参数默认值说明必填pretrained_nameNone自动下载的 CTC 模型名NGC必填model_pathNone本地.nemo模型路径与pretrained_name二选一必填manifest_filepathNone待对齐 manifest 路径必填output_dirNone输出 CTM/ASS 文件与结果 manifest 的目录通用align_using_pred_textFalse用模型转写文本作为对齐参考通用transcribe_device/viterbi_deviceNone转写 / Viterbi 解码设备通用batch_size1log-probs 与解码的批大小通用use_local_attentionTrue对 Conformer 模型启用 64×64 局部注意力通用additional_segment_grouping_separator[., ?, !, ...]用于把整句文本拆成更小 segment 的分隔符通用audio_filepath_parts_in_utt_id1用音频路径的末 N 段生成 CTM 中的 utt_id流式use_buffered_chunked_streamingFalse分块流式推理长音频流式chunk_len_in_secs1.6每个 chunk 的长度秒流式total_buffer_in_secs4.0chunk 左右 padding 的总缓冲长度秒流式chunk_batch_size32分块推理的批大小流式simulate_cache_aware_streamingFalse使用 cache-aware 流式获取 logits输出save_output_file_formats[ctm, ass]要保存的输出文件类型列表输出ctm_file_config—CTM 输出配置见下输出ass_file_config—ASS 字幕输出配置见下文本分段segment 边界的由来additional_segment_grouping_separator控制文本如何被拆分为语句segment。默认按句号、问号、感叹号与省略号拆句若设为空列表或None则整段文本视为单个 segment。源码对取值有限制不能是空字符串或单个空格会抛ValueError。同时 align.py 会打印一条行为变更警告自 NeMo 2.5.0 起分隔符在拆句后会被保留在 segment 文本中旧版本会移除这一变化直接影响对齐输出的文本还原。utt_id 生成规则audio_filepath_parts_in_utt_id决定 CTM/ASS 文件命名所用的 utt_id。源码 docstring 给出了三个示例假设音频路径为/a/b/c/d/e 1.wav取 1 段 →e1路径中的空格会被替换为短横线避免破坏 CTM 的空格分隔格式取 2 段 →d_e1取 3 段 →c_d_e1。CTM 文件配置CTMFileConfigdataclass class CTMFileConfig: remove_blank_tokens: bool False # 是否从 token 级 CTM 中移除 blank token minimum_timestamp_duration: float 0 # 时间戳最小时长秒remove_blank_tokens对应移除b见 constants.py 中的BLANK_TOKEN bminimum_timestamp_duration用于把过短的 token/词/segment 时间戳从中心向两侧外扩到最小时长源码提示这样可能造成时间戳重叠make_ctm_files.py 中按 token 中点向两侧各扩minimum_timestamp_duration/2并 clamp 到音频起止边界。ASS 字幕配置ASSFileConfigdataclass class ASSFileConfig: fontsize: int 20 vertical_alignment: str center # top / center / bottom resegment_text_to_fill_space: bool False # 按屏幕可容纳字符数重新分句 max_lines_per_segment: int 2 text_already_spoken_rgb: List[int] [49, 46, 61] # 深灰已说完 text_being_spoken_rgb: List[int] [57, 171, 9] # 深绿正在说 text_not_yet_spoken_rgb: List[int] [194, 193, 199] # 浅灰未说到vertical_alignment必须是top/center/bottom之一映射到 ASS 的 Alignment 值 8/5/2分别对应屏幕上/中/下、居中对齐三个 RGB 颜色列表各必须恰好包含 3 个元素源码有显式校验用于卡拉 OK 式三色高亮已说文本深灰、正在说的词/token 深绿、未说文本浅灰resegment_text_to_fill_spaceTrue时make_ass_files.py 会依据播放分辨率PlayResX384、PlayResY288与字号估算每行/每屏可容纳的字符数假设字符宽约为字高的 0.6 倍、行距 1.15 倍把长 segment 重切为不超过max_lines_per_segment行的小段。输出产物详解CTM、ASS 与结果 manifest输出目录结构运行完成后output_dir下会生成output_dir/ ├── ctm/ │ ├── tokens/ # 每个 utt 一个 utt_id.ctm │ ├── words/ │ └── segments/ ├── ass/ │ ├── tokens/ # token 级高亮字幕 │ └── words/ # 词级高亮字幕 └── manifest名_with_output_file_paths.json # 关联各输出的结果 manifestCTM 格式make_ctm_files.py 按 tokens / words / segments 三个层级分别落盘。每行遵循标准 CTM 五列格式由get_ctm_line生成utt_id 通道(恒为1) 起始时间 时长 文本例如e1 1 0.320 0.180 the e1 1 0.500 0.240 quick实现细节文本中的空格会被替换为spaceSPACE_TOKEN见 constants.py避免给 CTM 文件引入额外空格字段若remove_blank_tokensTrue则跳过bblank token当参考文本为空或 token 数远超音频时长导致无对齐结果时segments_and_tokens为空会跳过该 utt 的文件生成。ASS 字幕格式make_ass_files.py 生成标准 ASS v4.00 字幕ScriptType: v4.00包含[Script Info]、[V4 Styles]、[Events]三个区块样式基于 Arial、可配置字号与垂直位置。字幕事件覆盖三个阶段语音开始前的整句未说浅灰字幕、逐词/逐 token 的三色高亮滚动词间空隙 1ms 时插入不带高亮的过渡字幕、语音结束后的整句已说深灰字幕结束时间外扩到ceil(audio_dur)1秒以适配视频生成时 MP4 比音频略长的情况。token 级字幕会把 BPE 子词的▁与space还原为真实空格。结果 manifestmake_output_manifest.py 的write_manifest_out_line把每条对齐结果写回 JSONL字段包括audio_filepath、text参考文本、pred_text若使用转写文本、以及各级输出文件路径tokens_level_ctm_filepath、words_level_ctm_filepath、segments_level_ctm_filepath、words_level_ass_filepath、tokens_level_ass_filepath。长音频与大文件分块流式与 cache-aware 流式对齐对 1 小时以上的长音频NFA 提供两条流式路径use_buffered_chunked_streamingTrue基于FrameBatchASR见 nemo/collections/asr/parts/utils/streaming_utils.py把音频切成chunk_len_in_secs默认 1.6s的块配合total_buffer_in_secs默认 4.0s即 chunk 加左右 padding 的总缓冲做带上下文的分块推理。源码还做了两处预处理改动dither0.0、pad_to0并校验模型必须使用per_feature归一化。当前限制分块流式推理不支持 batch 推理即使batch_size 1也会逐条处理但chunk_batch_size可让单个音频内部的多个 chunk 并行推理。simulate_cache_aware_streamingTrue使用 cache-aware 流式推理获取 logits与 NeMo 的 cache-aware streaming ASR 管线同一套实现适合超长音频的低内存对齐。两条路径均通过get_batch_variables透传给对齐主流程aligner_utils.py 第 868 行生成的 log-probs 仍走同一套 Viterbi 解码。EOU 对齐与多机多卡扩展align_eou.pyalign_eou.py 是 NFA 面向语句起止SOU/EOU检测与大规模数据处理的增强版入口相比align.py新增了以下能力SOU/EOU 时间戳输出对齐完成后脚本会读取segments_level_ctm_filepath取所有 segment 时间戳的最小起始时间作为sou_time、最大结束时间作为eou_time写回输入 manifest 并保存为新的对齐 manifest{audio_filepath: ..., text: ..., sou_time: 0.32, eou_time: 4.18}未指定output_manifest_filepath时结果保存在输入 manifest 同目录下命名为manifest名-aligned.json。output_dir默认.tmp配合remove_tmp_dirTrue可在对齐完成后自动清理中间 CTM/ASS 文件仅保留 SOU/EOU 结果。目录批量处理manifest_filepath可以是文件也可以是目录指向目录时默认通过Path.glob(*.json)收集所有 manifest或用manifest_pattern自定义 glob 模式如*.jsonl。注意批量处理多个 manifest 时output_manifest_filepath必须为None否则报错且若保留中间文件每个 manifest 会被分配到独立子目录。多机多卡数据并行通过num_nodes、num_gpus、node_idx、gpu_idx四个参数把 manifest 列表按节点间取模 → 节点内 GPU 间取模的方式分片见get_manifests_for_this_rank每个 rank 只处理自己分到的 manifest互不重叠适合大规模语料库并行对齐。文本清洗clean_textTrue默认时会在对齐前对文本做规范化转小写、Unicode NFKD 归一化并去除重音unicode_to_ascii、移除标点、把各种引号类字符统一为空格或撇号确保与模型 tokenizer 的输入习惯一致。底层原理CTC log-probs 到时间戳的 Viterbi 路径理解 NFA 的工作原理有助于正确使用参数。整个对齐流程可归纳为五步源码路径align.py → aligner_utils.py特征与文本编码get_batch_variables第 868 行对每个音频提取特征送入 CTC 模型得到帧级 log-probs 序列log_probs_batch同时把参考文本按 tokenizer 切分为 token 序列y_batch对齐网格构造以帧数 T × token 数 U构造对齐网格期间additional_segment_grouping_separator决定 segment 边界blank tokenb被允许插入 token 之间以吸收时长伸缩Viterbi 解码viterbi_decoding第 726 行在网格上寻找最优路径等价于 CTC 对齐的最优解得到每个 token 对应的帧区间时间戳换算add_t_start_end_to_utt_obj第 621 行用output_timestep_duration首个 batch 计算出的模型输出时间步长即每帧对应的秒数把帧索引换算为秒级起止时间并逐层组装 Segment → Word → Token 层级结构多格式落盘CTMtokens/words/segments、ASStokens/words与结果 manifest 依次写出。这里也解释了为何 NFA 只支持 CTCCTC 的每帧一个概率分布 blank 机制天然支持帧与 token 的单调对齐Transducer 模型由于联合网络的存在其对齐空间无法用同样简洁的 Viterbi 网格求解。测试与验证对齐结果的可信度保障仓库为 NFA 提供了单元测试用于验证核心逻辑的正确性tests/test_restore_token_case.py参数化测试restore_token_case函数验证从参考文本恢复 BPE 子词大小写如HEY![▁he, y, !]→[▁HE, Y, !]在各种边界输入重音符号m²、多余▁前缀等下均正确test_add_t_start_end_to_utt_obj.py与test_get_utt_obj.py分别验证时间戳写入与 utterance 对象构造逻辑。这些测试可以在安装依赖后通过pytest tools/nemo_forced_aligner/tests/运行用于在修改或二次开发 NFA 时守护对齐核心逻辑。另外仓库还提供了端到端的入门教程 NeMo_Forced_Aligner_Tutorial.ipynb包含从 manifest 准备到结果可视化的完整演示适合作为上手的配套材料。常见问题与使用建议模型二选一pretrained_name与model_path只能设置其一否则align.py直接抛ValueErrormanifest 必填字段默认模式下每条必须含audio_filepath与text缺一不可转写模式align_using_pred_textTrue下则禁止出现pred_text字段OOM 处理若使用 GPU 出现显存不足优先把transcribe_device与viterbi_device都设为cpu或调小batch_size长音频场景再用chunk_batch_size控制分块推理吞吐长音频优先流式对齐 1 小时以上音频时建议开启use_buffered_chunked_streaming需模型为per_feature归一化或simulate_cache_aware_streaming普通离线推理在长音频上容易遇到显存瓶颈时间戳重叠提示设置ctm_file_config.minimum_timestamp_duration会从中心外扩过短的时间戳可能导致相邻 token/词时间戳重叠仅在对齐结果用于粗粒度标注如字幕分句时使用中文等多语言NFA 的可用语言范围取决于所选 CTC 模型的训练语种FastConformer 系列覆盖 14 语言README 中已有说明中文可选用对应语种的 checkpoint 并按需调整additional_segment_grouping_separator为中文标点。总结NFA 把已知文本 → 精确时间戳这一语音处理刚需封装成了一条可配置、可扩展的流水线align.py提供开箱即用的 token/词/segment 三级对齐与 CTM/ASS 双格式输出align_eou.py进一步补充 SOU/EOU 边界检测、目录批量处理与多机多卡并行。其底层基于 CTC 模型的帧级 log-probs 与 Viterbi 解码源码与测试完整地呈现在 tools/nemo_forced_aligner/ 与 aligner_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),仅供参考

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

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

免费获取报价