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 说话人区分模块能在直播会话中把每句话实时标记到具体发言人。适合做会议记录、访谈整理、带说话人标签字幕的开发者。
什么时候需要实时说话人区分
- 多人会议直播录制:转写行自带说话人编号与起止时间戳,会后不用回听录音猜"这句是谁说的"
- 实时字幕场景:字幕流直接携带"谁在说",观众体验和信息密度同时提升
- 访谈/对话量化分析:从输出的 JSON 里按
speaker字段聚合,就能统计各参与者的发言轮次与时长占比 - 后端服务集成:WebSocket 输出的行对象带
speaker/start/end字段(speaker为 -2 表示静音段),可直接落库
从零跑起来:环境、最小命令与验证
环境准备与最小安装命令
pip install "whisperlivekit[diarization-sortformer]"这条命令把主包和 NeMo(NVIDIA 的语音工具包,Sortformer 模型就来自它)一起装好;GPU 机器可改用uv sync --extra cu129 --extra diarization-sortformer。成功标志:启动后日志出现 "Using CUDA for Sortformer model"(无 GPU 时显示 CPU)。
最小可运行命令
wlk serve --model medium --diarization --language en服务在 8000 端口启动网页转写界面,首次运行会自动下载默认的 4 人模型nvidia/diar_streaming_sortformer_4spk-v2,所以第一次启动会比以后慢。
如何验证说话人区分生效
打开http://localhost:8000,先说一句话、再换一个人的声音说一句:如果两行转写带上不同说话人编号和时间区间,说明 diarization(说话人区分,即判断"谁在说")已经生效。没有浏览器的话,用wlk listen --diarization在终端验证,日志里出现 "SortformerDiarization initialized successfully" 且定稿行持续打印即为正常。
上图是开启说话人区分后的演示页面:每行转写前面都有说话人编号、时间戳,法语行还附带了实时翻译,静音段以 -2 行独立显示。
原理一张图说清:Sortformer 的双缓存流式机制
把模型想象成一个管"花名册"的接待员:它按约 1 秒一个音频块处理,每块先算出一组"声音指纹"(说话人特征向量),然后查两本账——长期账本(speaker cache)记着会话开始以来所有发言人存下的指纹,短期账本(FIFO 队列)只留最近几块的指纹。新块到来时,拿它的指纹和两本账做匹配,判定当前该记到哪个发言人名下;编号按说话人出场顺序分配,之后保持稳定。这就是为什么开了两小时的会,"Speaker 1" 始终指向同一个人,而不用把整段录音读完再事后归人。
架构图左上角的 diarization engine 区块展示了这条链路:音频先转梅尔频谱,再由 Sortformer 编码器产出特征,经 Speaker Cache(说话人缓存)与 Transformer 编码器输出说话人序列,最后与转写引擎的输出做对齐。
Sortformer 说话人区分参数调优对照
| 参数 | 作用 | 什么时候调 |
|---|---|---|
--diarization | 总开关,不加则输出里没有说话人字段 | 需要说话人标签时必加 |
--sortformer-max-speakers | 声明本次会话最多 1–4 个说话人,保留按出场顺序的前 N 个声道 | 人数已知时(如双人访谈设 2),可抑制空声道干扰 |
--sortformer-model-path | 指向本地.nemo文件、只含一个.nemo的目录,或模型 ID | 离线推理、内网部署,或默认 4spk 模型不适配时 |
--diarization-backend | sortformer(默认,流式)或diart | 需要 Diart 时注意它受 Python 3.11/3.12 限制 |
--pause-segmentation-seconds | 静音超过该秒数(默认 5)时产生一个稳定行边界 | 想按停顿切分发言、避免单行过长时 |
🔑--sortformer-max-speakers是"声明"而非"估计":如果实际说话人超过声明值,后来的说话人会被并入已保留的标签,所以拿不准就别设。
一个真实场景:用 Python 接口处理双人对讲
假设你要把双人对讲流接入自己的系统,音频自己以 16kHz float PCM 读取:
from whisperlivekit.diarization.sortformer_backend import ( SortformerDiarization, SortformerDiarizationOnline, ) shared = SortformerDiarization() # 权重只加载一次 online = SortformerDiarizationOnline(shared_model=shared, max_speakers=2) for chunk in read_pcm_chunks_16k(): # 持续读取 16 kHz 浮点 PCM online.insert_audio_chunk(chunk) for seg in await online.diarize(): print(f"speaker {seg.speaker}: {seg.start:.2f}-{seg.end:.2f}s")为什么这么写:SortformerDiarization持有模型权重,可被多个会话复用;SortformerDiarizationOnline是带流式状态的会话实例,每开一路音频建一个新的。这里设max_speakers=2是因为场景明确只有两人,第三、四声道就不参与判定了。输出是一行行speaker(0 起编号)加起止时间的片段,满一个约 1 秒的音频块就会推进一次。
踩坑速查:报错与效果不达预期
Q:启动报SystemExit: Sortformer diarization requires NeMoA:缺了 diarization-sortformer 附加依赖。按上面的安装命令重装,或用uv sync --extra diarization-sortformer重建环境。
Q:两人声音相近被混在一起,或第三人被标成 Speaker 1A:多半是--sortformer-max-speakers设小了。它是上限声明,超过声明的说话人会被并入保留标签,拿不准就保持默认。
Q:文字已经出来但一直没说话人编号,缓冲区反复刷新A:正常现象。区分引擎跑在转写后面,未对齐的文本先放在buffer_diarization里,追上后会一次性落进说话人行,不会丢字。
Q:静音被"归"到了某个说话人名下?A:静音是speaker: -2、text 为空的特殊行,按speaker字段过滤即可,别按文本匹配。
Q:CPU 上跑不动A:Sortformer 支持 CPU 但明显偏慢,建议 GPU;也可以直接用docker compose up --build wlk-gpu-sortformer一条命令起整套环境。
延伸阅读
- Sortformer 后端源码:双缓存流式状态、说话人片段的生成逻辑都在这里
- 转写与区分对齐原则:讲每个 ASR 词如何按"最大重叠"归给某个说话人,以及区分滞后时文本如何缓存
- API 文档:WebSocket 全部字段的定义,包括静音行的约定
排查归因类问题(某句话为什么记到了错误的人头上)时,先看对齐文档里的时间戳匹配规则,比调模型参数更快见效。
【免费下载链接】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),仅供参考