3 步跑通 WhisperLiveKit Sortformer 实时说话人区分
2026/8/24 22:18:15 网站建设 项目流程

3 步跑通 WhisperLiveKit Sortformer 实时说话人区分

【免费下载链接】WhisperLiveKitReal-time, local speech-to-text with streaming ASR, speaker diarization, translation, and OpenAI/Deepgram-compatible APIs.项目地址: https://gitcode.com/GitHub_Trending/wh/WhisperLiveKit

周二下午的产品评审会,五个人围着桌子抢话,会后你只拿到一份不分归属的文字稿,想确认"那句话是谁说的"只能回去翻录音。WhisperLiveKit 的 Sortformer 说话人区分功能把这件事变成实时的:转录流里每一行都带一个说话人编号,边说边出标签。

Sortformer 在解决什么问题

Sortformer(默认模型nvidia/diar_streaming_sortformer_4spk-v2)本质上做的是逐帧说话人分类:把音频流切成 1 秒的块,对每一帧输出 4 个说话人的概率,并在块与块之间维护一个"说话人缓存",让同一个人整场会议保持同一个编号。这和"录完一整段再全局聚类"的离线做法是两条路线。

维度传统做法本方案做法
处理方式整段音频离线批处理流式,每 1 秒音频走一次推理
标签延迟录音结束后数分钟边说边出标签
说话人编号全局聚类,长音频中 ID 可能漂移188 帧增量说话人缓存,会话内编号稳定
运行门槛常依赖 HF 账号下载模型NeMo 本地加载,离线可用,最多 4 人

顺带一提,它输出的是匿名编号(speaker 1、speaker 2),不关心这个人叫什么——名字映射需要你自己在外层做。

一条音频块如何变成说话人标签

按数据流拆成 4 个阶段,对应 sortformer_backend.py 里的实际代码路径:

  1. 音频累积分块:16 kHz PCM 经 WebSocket 进来,缓冲满 1 秒(chunk_len 10 帧 × 下采样 10)才发出一个块;静默期用insert_silence补偿全局时间偏移,保证区分时间轴和转录时间轴始终对齐。
  2. Mel 特征提取AudioToMelSpectrogramPreprocessor(25 ms 窗、128 维 Mel)把音频块转成频谱图,再拼接上一块末尾的 99 帧(约 0.99 秒)作为左上下文,块与块之间不留信息断层。
  3. 流式推理forward_streaming_step逐块前向,流式状态里带着 188 帧的说话人缓存(spkcache)和最近语音的 FIFO 队列,输出逐帧 4 分类概率;缓存每 144 帧刷新一次。
  4. 片段合并与 token 对齐:逐帧取 argmax,把相邻同说话人帧合并成SpeakerSegment(start, end)tokens_alignment再让每个转录 token 按最大时间重叠匹配到某个片段,得到一个 1 起编号的说话人,前端输出"编号 + 文本"的行。

图中区分模块与 ASR、翻译流水线并行运行,它的片段输出只被下游对齐模块消费,不参与文本生成本身——这也解释了为什么关掉转录仍能单独拿到区分结果。

本地跑通实时说话人区分

🚀 最短可运行路径分 3 步:

1️⃣克隆并装依赖git clone https://gitcode.com/GitHub_Trending/wh/WhisperLiveKit,进入目录后uv sync --extra cu129 --extra diarization-sortformer。完成后启动服务不会抛缺 NeMo 的 SystemExit(GPU 环境加 cu129 extra,纯 CPU 只装 diarization-sortformer)。

2️⃣启动服务uv run wlk --model small --diarization --language en。完成后 8000 端口出 Web UI(Docker 用户直接docker compose up --build wlk-gpu-sortformer)。

3️⃣录音验证:打开 localhost:8000,让两个人交替说几句。你会看到每行文本带上 speaker 1 / speaker 2 标签,交替时编号切换,且标签跟着人走而不是跟着句子走。

不同说话人的文本行用不同颜色区分,行首编号与录音里实际的语音交接点一一对应。

Sortformer 参数怎么调

这些参数目前写死在_load_model里,没有暴露成 CLI 参数;想调就得改 sortformer_backend.py,或者用--sortformer-model-path指向自己改过配置的.nemo文件。

⚙️参数名默认值可调范围调大 / 调小的后果
chunk_len10 帧(约 1 秒/次推理)5–15调大减少推理次数、省算力,但标签出得慢;调小实时性更好
chunk_left_context10(代码实际拼接约 99 帧 Mel)5–15调大边界判断更稳,单次推理计算量上升
spkcache_len188150–250调大说话人记忆更长、长对话编号更稳;调小易换号
spkcache_update_period144100–200调小缓存更新更勤、更准但更耗算力;调大长对话易串号

如果只调一个:追低延迟先动 chunk_len,追长对话编号稳定先动 spkcache_len。

说话人区分延迟和混淆怎么办

现象:启动即 SystemExit,提示 "Sortformer diarization requires NeMo"。原因是只装了基础包,没装区分依赖。处理:uv sync --extra diarization-sortformer,或pip install "whisperlivekit[diarization-sortformer]"

现象:首次运行长时间无输出,像卡死。原因是在从 Hugging Face 拉取diar_streaming_sortformer_4spk-v2模型。处理:内网/离线环境提前下载.nemo文件,用--sortformer-model-path指向本地路径。

现象:超过 4 个人时编号混乱、互相抢标签。原因是模型按最多 4 说话人训练(4spk),说话人缓存也只保留 188 帧的历史。处理:场景控制在 4 人以内;超长会议里偶发换号属于该架构的已知边界,不是配置错误。

这个功能适合什么场景

适合:2–4 人会议、访谈、播客录制这类需要实时"谁说了什么"的流式转文字带说话人标签场景,且环境能本地跑 NeMo(GPU 优先)。

不适合:4 人以上的大场;需要识别"具体是谁"的场景(只能拿到匿名编号);以及纯 CPU 且负载重的机器——每 1 秒一次的推理在低算力下容易追不上实时。


编号和文本从同一条流水线出来,这是 Sortformer 说话区分的核心价值:先试试把 spkcache_len 提到 250 再录 30 分钟会议,看编号还稳不稳。

【免费下载链接】WhisperLiveKitReal-time, local speech-to-text with streaming ASR, speaker diarization, translation, and OpenAI/Deepgram-compatible APIs.项目地址: https://gitcode.com/GitHub_Trending/wh/WhisperLiveKit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询