如何用 NeMo Sortformer 完成多说话人音轨的说话人分离
2026/9/14 7:24:06 网站建设 项目流程

如何用 NeMo Sortformer 完成多说话人音轨的说话人分离

【免费下载链接】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

如果你有一段多人对话或会议的录音,需要知道“谁在什么时候说话”(who spoke when),而不是把它拆成 VAD、说话人嵌入提取、聚类三个模块自己拼装,NeMo Speech 提供的端到端模型 Sortformer 可以直接完成这件事:输入音频,输出按说话人切分的时间段。NeMo 提供了三个预训练 Sortformer 检查点,全部支持最多 4 个说话人:

模型类型适用场景
nvidia/diar_sortformer_4spk-v1Offline离线批处理分离
nvidia/diar_streaming_sortformer_4spk-v2Streaming流式实时分离
nvidia/diar_streaming_sortformer_4spk-v2.1Streaming流式,对会议场景语音鲁棒性更好

下面给出一条从加载模型到批量出结果的完整路径:先写三行 Python 代码验证模型能跑,再用仓库自带的推理脚本处理多条音轨,最后用 RTTM 输出和 DER 指标核对结果。

选择哪种 Sortformer 模型

选择依据以 模型文档 和 README 为准:

  • 离线批处理:直接用diar_sortformer_4spk-v1,它是离线版本,一条模型同时覆盖分离任务。
  • 实时/流式:用 streaming 版本。streaming 模型按小块重叠音频处理,用 Arrival-Order Speaker Cache(AOSC)保存之前出现过的说话人声学嵌入,保证同一个人跨块保持同一标签。
  • 用 streaming 模型做离线分离:文档明确说明 online 版本可以通过设置足够长的 chunk size 用于离线分离(见 models.rst),此时需要手动设置下面几段代码中的sortformer_modules参数。

三个模型都限制为最多 4 个说话人(4spk),超过这个数的音轨不在预训练模型的支持范围内。

最短路径:三行代码分离一条音频

前提:已安装 NeMo(见 安装文档 中 “installing NeMo” 一节)。from_pretrained会按 HuggingFace 模型名下载检查点,先登录:

pip install -U "huggingface_hub[cli]" huggingface-cli login

离线模型(README 中的示例,/path/to/audio.wav替换为你的音频路径):

from nemo.collections.asr.models import SortformerEncLabelModel diar_model = SortformerEncLabelModel.from_pretrained("nvidia/diar_sortformer_4spk-v1") diar_model.eval() predicted_segments = diar_model.diarize(audio="/path/to/audio.wav", batch_size=1)

streaming 模型:在调用diarize之前需要设置四个流式推理参数(下面示例用 v2.1,参数取自我文 README 中的官方示例):

from nemo.collections.asr.models import SortformerEncLabelModel diar_model = SortformerEncLabelModel.from_pretrained("nvidia/diar_streaming_sortformer_4spk-v2.1") diar_model.eval() diar_model.sortformer_modules.chunk_len = 340 diar_model.sortformer_modules.chunk_right_context = 40 diar_model.sortformer_modules.fifo_len = 40 diar_model.sortformer_modules.spkcache_update_period = 300 predicted_segments = diar_model.diarize(audio="/path/to/audio.wav", batch_size=1)

返回值predicted_segments就是模型为输入音频预测出的说话人分离时间段。streaming 版本的文档性能表列出了 0.32s 到 30.4s 多档延迟下的 DER,说明不同流式参数组合对应不同延迟档位;上表参数组是文档给出的可用配置,不自行换算其与延迟档位的对应关系。

批量处理多条音轨:manifest + 推理脚本

单条音频验证通过后,批量任务用仓库脚本 e2e_diarize_speech.py。它读取 JSON-lines manifest,对每条音频跑分离推理,可选地输出 RTTM 并计算 DER。

1. 准备 manifest 文件

每行一个 JSON 对象,audio_filepath为必填字段,其余可选(格式来自 datasets 文档):

{"audio_filepath": "/path/to/abcd.wav", "offset": 0, "duration": null, "label": "infer", "text": "-", "num_speakers": null, "rttm_filepath": "/path/to/rttm/abcd.rttm"}

其中rttm_filepath指向该音频的参考 RTTM 标注文件,是后面计算 DER 的依据。不想手写的话,用仓库脚本从路径清单生成 manifest(--paths2audio_files--manifest_filepath必填,音频与 RTTM 文件按相同基础文件名配对,如abcd01.wav对应abcd01.rttm):

python scripts/speaker_tasks/pathfiles_to_diarize_manifest.py \ --paths2audio_files /path/to/audio_file_path_list.txt \ --paths2rttm_files /path/to/rttm_file_path_list.txt \ --manifest_filepath /path/to/manifest_output/input_manifest.json

两个路径清单文件每行一个绝对路径,例如audio_file_path_list.txt

/path/to/abcd01.wav /path/to/abcd02.wav

长录音不需要预先物理切短:数据加载器只读取 manifest 条目中offsetduration指定的时间段,对同一音频可建多个不同时间窗的条目(见 datasets 文档 的 Long-Form Audio 一节)。

2. 运行推理

以离线模型为例(/path/to/...均替换为你自己的实际路径):

python examples/speaker_tasks/diarization/neural_diarizer/e2e_diarize_speech.py \ batch_size=1 \ model_path=/path/to/diar_sortformer_4spk-v1.nemo \ dataset_manifest=/path/to/diarization_manifest.json \ out_rttm_dir=/path/to/rttm_output

关键参数说明:

  • batch_size=1:文档明确建议用 1 以获得最长推理窗口和最高精度。
  • model_path:本地.nemo(或.ckpt)文件。注意 README 称此处也可传 HuggingFace 模型名,但脚本源码中model_path不以.nemo/.ckpt结尾时会直接抛出ValueError,两条文档不一致,按脚本实现以本地检查点文件为准。
  • out_rttm_dir:推理得到的预测 RTTM 会写入该目录(仅在不跳过 DER 分支时生效,即不传no_der=True)。
  • postprocessing_yaml:可选。默认情况下脚本跳过 post-processing、只做二值化;若要复现模型卡上报告的 DER 分数,需要传入 post-processing 配置。仓库自带两套优化好的参数(在 post_processing 目录 下):
python examples/speaker_tasks/diarization/neural_diarizer/e2e_diarize_speech.py \ batch_size=1 \ model_path=/path/to/diar_sortformer_4spk-v1.nemo \ postprocessing_yaml=examples/speaker_tasks/diarization/conf/post_processing/sortformer_diar_4spk-v1_callhome-part1.yaml \ dataset_manifest=/path/to/diarization_manifest.json

注意这两套参数是按域优化出来的:*_dihard3-dev.yaml在 DIHARD3 开发集上优化,*_callhome-part1.yaml对应通话语音,换域使用时不要假定其中任意一套都是全局最优。以离线 v1 的 DIHARD3 参数为例(sortformer_diar_4spk-v1_dihard3-dev.yaml):

parameters: onset: 0.64 # 检测语音段开始的阈值 offset: 0.74 # 检测语音段结束的阈值 pad_onset: 0.06 # 每个语音段开头增加的长度 pad_offset: 0.0 # 每个语音段结尾增加的长度 min_duration_on: 0.1 # 短于该时长的语音段被移除 min_duration_off: 0.15 # 短于该时长的静音被移除
  • no_der:默认False,manifest 里带rttm_filepath时脚本会计算 DER;若只做推理不评估,可传no_der=True跳过 DER 计算。

用 streaming 检查点跑脚本model_path换成 streaming 模型的.nemo文件即可,脚本检测到 streaming 模式后会自动应用流式参数,并允许用同名 Hydra 参数覆盖,例如:

python examples/speaker_tasks/diarization/neural_diarizer/e2e_diarize_speech.py \ batch_size=1 \ model_path=/path/to/diar_streaming_sortformer_4spk-v2.nemo \ dataset_manifest=/path/to/diarization_manifest.json \ chunk_len=340 \ chunk_right_context=40 \ fifo_len=40 \ spkcache_update_period=300

这组值与上文 Python 路径中 README 示例一致;流式场景还可用async_streamingasync_pad_to_max等脚本参数调整(见脚本头部 DiarizationConfig 的定义)。

验证分离结果

结果核对分两层:

  1. 看输出文件out_rttm_dir下会生成每条音频对应的预测 RTTM(SPEAKER <会话> <通道> <起始> <时长> ...逐行时间戳),可以直接检查说话人时间段是否符合预期。
  2. 看 DER 分数:脚本日志会输出Running offline diarization evaluation...Evaluating the model on {N} audio segments...,随后打印按collar(默认 0.25 秒)计算的 Diarization Error Rate。manifest 中未提供 RTTM 的文件无法参与 DER 评分,因此需要评估时就务必带上rttm_filepath

DER 的合理量级可对照官方模型卡数据(README,均为含重叠语音的官方评测,仅供参考基准而非你的必得结果):

模型数据集CollarDER (无后处理)DER (有后处理)
diar_sortformer_4spk-v1DIHARD3-Eval (≤4spk)0.0s16.2814.76
diar_sortformer_4spk-v1CALLHOME-part2 (2spk)0.25s6.495.85
diar_sortformer_4spk-v1CH1090.25s6.276.86
diar_streaming_sortformer_4spk-v2DIHARD III Eval (≤4spk)0.0s13.45(30.4s 延迟)

限制与边界

  • 说话人数上限 4:三个预训练模型都只覆盖最多 4 个说话人,更多说话人的场景文档没有提供预训练方案。
  • 文件名一致性:用pathfiles_to_diarize_manifest.py生成 manifest 时,音频、RTTM(及可选的 txt/uem/ctm)必须共享唯一的基础文件名,只有扩展名不同。
  • 离线与流式是两种使用形态,不要混在同一条操作链里:本文的 Python 三行路径和脚本路径都默认离线批处理;streaming 参数(chunk_len等)只在加载 streaming 检查点时才有意义。
  • post-processing 参数是域相关的dihard3-devcallhome-part1两套 yaml 分别在不同域的数据上优化,不要跨域照搬后仍期望模型卡级别的 DER。

下一步

如果预训练模型在你的目标域上不够用,仓库文档给出了 Sortformer 的继续训练入口 sortformer_diar_train.py(Hydra 配置加manifest_filepath等参数即可启动训练);post-processing 参数也可以用脚本的launch_pp_optim=True选项交给 Optuna 在你的验证集上搜索。这两条都是独立任务,需要时按 results 文档 与脚本参数说明另行执行。

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询