用 FunASR 做说话人分离:一次调用输出「谁在何时说了什么」
做会议纪要、客服质检、访谈整理时,你不只想知道说了什么,还想知道每句话是谁说的。这件事叫说话人分离(Speaker Diarization)。
常见做法是把两个工具拼起来:pyannote.audio 负责切分说话人 + Whisper 负责转写,再手动把时间轴对齐。这套流程要申请 HuggingFace 授权、装一堆依赖、自己写对齐逻辑,而且对中文不算友好。
用 FunASR,一次 generate() 调用就够了。VAD、语音识别、标点、说话人嵌入(CAM++)被串成一条流水线,直接返回每一句的说话人编号、时间戳和文本。
安装
pip install -U funasr modelscope
完整代码
from funasr import AutoModel
# One model handle = VAD + ASR + punctuation + speaker embedding (CAM++)
model = AutoModel(
model="paraformer-zh", # or "iic/SenseVoiceSmall"
vad_model="fsmn-vad",
punc_model="ct-punc",
spk_model="cam++", # speaker diarization
)
res = model.generate(input="meeting.wav", batch_size_s=300)
for s in res[0]["sentence_info"]:
print(f'[{s["start"]/1000:.1f}s-{s["end"]/1000:.1f}s] '
f'speaker {s["spk"]}: {s["sentence"]}')
输出长这样(示例)
[0.0s-3.2s] speaker 0: 大家好,今天的会议主要讨论第三季度的产品规划。
[3.5s-7.1s] speaker 1: 我先同步一下进度,核心功能已经完成了百分之八十。
[7.4s-9.9s] speaker 2: 测试这边可能还需要两周时间。
[10.2s-13.6s] speaker 0: 好的,那我们把上线时间往后调一周。
每个 sentence_info 元素包含四个字段:
| 字段 | 含义 |
|---|---|
spk | 说话人编号,CAM++ 自动聚类得到,无需事先指定人数 |
start / end | 该句的起止时间(毫秒) |
sentence | 该句文本(已加标点) |
实测效果
我们在一段 227 秒的多人会议录音上实测:FunASR 自动切分出 77 个句子、区分出 11 个不同说话人,全程不需要预先告诉它有几个人。整条流水线只用一次 generate() 调用、一个 Python 依赖。
为什么用 FunASR 而不是 pyannote + Whisper
- 一个调用,不用对齐:转写和说话人标签天然对齐,不必自己拼时间轴。
- 不需要 HuggingFace 授权:pyannote 的说话人模型是 gated 的,要申请、要 token;FunASR 模型公开可下载。
- 中文更准:Paraformer / SenseVoice 在中文上 CER 显著低于 Whisper(实测对比)。
- CPU 也能跑:没有 GPU 也能离线出结果。
进阶
- 把
model="paraformer-zh"换成"iic/SenseVoiceSmall"即可用 SenseVoice(还自带情感/事件标签)。 - 遍历
sentence_info即可导出 SRT 字幕或按说话人聚合成会议纪要。
FunASR 是通义实验室开源的工业级语音识别工具包,中文场景又快又准。
在 GitHub 上 Star FunASR ★