pyannote.audio 说话人识别实战:5 分钟给会议录音自动标注说话人,完整教程
【免费下载链接】pyannote-audioNeural building blocks for speaker diarization: speech activity detection, speaker change detection, overlapped speech detection, speaker embedding项目地址: https://gitcode.com/GitHub_Trending/py/pyannote-audio
标注 10 小时会议录音里"每句话是谁说的",手动听下来可能要一整天。pyannote.audio 是这套流程的自动化答案:它是一个基于 PyTorch 的开源说话人日志(speaker diarization)工具包,输入一段音频,输出每个说话人的发声时间段,帮你把会议录音自动标注成"说话人 × 时间轴"的结构化结果。
这篇教程带你从零跑通:装环境、跑通第一个例子、看懂三个核心类、学会选型和排坑,最后用说话人嵌入(embedding)做跨录音的说话人匹配。
从会议质检场景认识 pyannote.audio
设想你是客服质检或播客后期:手上有一批几十分钟的录音,需要按说话人拆分段落,再交给标注工具或下游流程。人工听写慢、贵、还不稳定。
说话人日志要同时解决三件事:哪段时间有人声(语音活动检测)、什么时候换了人(说话人变化检测)、有没有两人抢话(重叠语音检测)。pyannote.audio 把这三件事打包成预训练好的 pipeline,你只需要一行代码调用;它还能进一步微调到你的数据上。
边界也说清楚:它输出的是"匿名"说话人编号(speaker_0、speaker_1),不负责判断"这是张经理"。把编号对应到真实身份,是后面"进阶组合"里说话人嵌入要解决的问题。
五分钟跑通第一个说话人识别
安装 pyannote.audio 与 ffmpeg
pyannote.audio 的音频解码依赖 ffmpeg,先确认它已安装(ffmpeg -version能输出版本号即可),然后任选一种方式装包:
# 推荐:uv 安装更快 uv add pyannote.audio # 或者传统 pip pip install pyannote.audio拿到 Hugging Face 访问令牌
预训练权重托管在 Hugging Face 上,使用前有固定两步:打开pyannote/speaker-diarization-community-1的模型页接受用户协议,再到hf.co/settings/tokens创建一个访问令牌。下面是模型仓库的 Files 页,核心就是那个pytorch_model.bin:
最小可运行示例
把令牌设成环境变量后,下面这段就是完整流程。ProgressHook会在终端打印进度,不用自己轮询:
import os import torch from pyannote.audio import Pipeline from pyannote.audio.pipelines.utils.hook import ProgressHook pipeline = Pipeline.from_pretrained( "pyannote/speaker-diarization-community-1", token=os.environ["HF_TOKEN"], ) if torch.cuda.is_available(): pipeline.to(torch.device("cuda")) with ProgressHook() as hook: diarization = pipeline("meeting.wav", hook=hook) for turn, speaker in diarization.speaker_diarization: print(f"{turn.start:7.1f}s - {turn.end:7.1f}s {speaker}")终端会打出这样的行:0.2s - 1.5s speaker_0、1.8s - 3.9s speaker_1……跑通它,说明你手上已经有一条可用的会议录音自动标注产线了。
核心能力拆解:Pipeline、Inference、Audio 三个类
pyannote.audio 的对外 API 集中在src/pyannote/audio/__init__.py里,核心就四个对象:Audio、Model、Inference、Pipeline。日常用得最多的是下面三个。
Pipeline:端到端说话人日志管道
Pipeline.from_pretrained加载一条已经调好超参的完整流程。它接受num_speakers(确切说话人数)、min_speakers/max_speakers(人数区间)这类参数,用来把聚类约束到你的业务先验上。以客服双录为例,人数就是 2,直接告诉模型:
output = pipeline("call.wav", num_speakers=2) # 人数未知时给个区间,上限能压住噪声导致的"幽灵说话人" output = pipeline("meeting.wav", min_speakers=2, max_speakers=8)这条管道的聚类、聚合逻辑在src/pyannote/audio/pipelines/speaker_diarization.py,超参想自己调可以读源码。
Inference:加载单个模型做推理
Pipeline 是"一条龙",Inference 是"单件工具":加载一个预训练模型,自己控制窗口策略。window="whole"表示整段音频作为一个窗口送入,适合声纹嵌入这类全局任务:
from pyannote.audio import Inference embedding = Inference( "pyannote/embedding", window="whole", token=os.environ["HF_TOKEN"], ) # 每段语音得到一个定长向量(声纹特征) vector = embedding("speaker_clip.wav")Audio:音频解码与重采样
音频的读取交给Audio,它基于 ffmpeg 解码,wav、mp3、m4a 都能处理,还可以指定目标采样率:
from pyannote.audio import Audio audio = Audio(sample_rate=16000, mono=True) waveform, sample_rate = audio("meeting.wav") print(waveform.shape) # (1, num_samples)模型本身是神经网络块,放在src/pyannote/audio/models/下(segmentation 分割模型、embedding 嵌入模型、separation 分离模型)。想替换或新增模型结构,可以从这里入手。
模型选型:三个版本怎么挑
pyannote 官方提供三代管道。下表摘自仓库 README 的 Benchmark(数字为 AMI 会议数据集的 Diarization Error Rate,越低越好):
| 版本 | 部署位置 | AMI 错误率 | 定位与适用场景 |
|---|---|---|---|
| legacy(3.1) | 本地 | 18.8% | 老项目兼容,新项目不建议再用 |
| community-1 | 本地 | 17.0% | 免费开源自部署,隐私敏感场景首选 |
| precision-2 | pyannoteAI 云服务 | 12.9% | 精度和速度更高,商业项目首选 |
怎么选,看三条:
- 数据能不能出机器:会议录音、医疗访谈这类敏感数据,选 community-1 本地推理;
- 精度是否卡脖子:precision-2 在 AMI 上把错误率从 17.0% 压到 12.9%,值得为精度付费就上云服务;
- 是否要微调:只有 community-1 这类开源管道能拿下来在你的数据上继续训练,precision-2 是托管服务。
建议先用 community-1 把整条流程跑顺,再评估是否升级。
高频坑与实战技巧
输入音频规格:单声道、16 kHz 最省心
模型内部按 16 kHz 单声道处理。多声道、高采样率文件能被自动转换,但转换会引入额外开销,且某些格式转换可能失真。批量生产环境里,预处理成 16 kHz 单声道 wav 是最稳的做法,前面Audio(sample_rate=16000, mono=True)一行就能完成。
说话人数参数:先验能省一半误报
默认情况下管道要自己估计人数。只要业务上知道人数(客服双录是 2、圆桌访谈不超过 6),用num_speakers或min_speakers/max_speakers显式约束,聚类稳定性明显提升。人多的会议把max_speakers设大些,人少的对话把区间收紧,都能减少"幽灵说话人"。
长音频:直接整段传入,别手动切
一个常见误区是把两小时的录音自己切成 5 分钟片段分别跑,再合并结果。问题在于:每段独立聚类,speaker_0 在不同片段里可能不是同一个人,合并逻辑会很难写。
正确做法是把整段文件直接传给 pipeline,内部切块和全局聚类它都做了。如果显存吃紧,调小批量而不是自己切文件:
pipeline = Pipeline.from_pretrained( "pyannote/speaker-diarization-community-1", token=os.environ["HF_TOKEN"], ) # 显存不足时调小批量 pipeline.segmentation_batch_size = 1 pipeline.embedding_batch_size = 1再配合pipeline.to(torch.device("cuda"))把推理搬上 GPU,长音频的处理速度会显著改善。
进阶组合:说话人嵌入与结果导出
跨录音匹配同一个说话人
diarization 输出的编号只在单文件内有效。要把"这两段录音里是同一个张经理"自动化,靠的是说话人嵌入:对每个说话人的语音段提取一个定长向量,不同文件里同一个人的向量距离更近。
from pyannote.audio import Inference from pyannote.audio.pipelines.utils.hook import ProgressHook embedding = Inference("pyannote/embedding", window="whole", token=os.environ["HF_TOKEN"]) diarization = pipeline("meeting.wav") vectors = {} for turn, speaker in diarization.speaker_diarization: # 取每个说话人足够长的片段提取向量 if turn.duration > 2.0: vectors[speaker] = embedding("meeting.wav", uri=turn)向量存成库之后,新录音进来逐段比对,就能跨文件识别"已知说话人"。想继续深入,embedding 模型的结构在src/pyannote/audio/models/embedding/。
输出 RTTM 与可视化
结果有两种常见去向:写进 RTTM 文件交给标注工具或评测脚本,或者直接画出来肉眼检查:
diarization.write("diarization.rttm", file="meeting.wav") import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(12, 3)) ax.plot(diarization) plt.show()write()一行产出标准 RTTM 文本;plot()返回 matplotlib 图对象,可以直接嵌进你的 Jupyter 或报告里。人工审核界面长这样,黄色和青色色块分别是两个说话人的区间:
行动清单
- 今天:按"五分钟跑通"一节装好环境,用一段 10 分钟的真实会议录音跑出第一张 RTTM;
- 本周:在 2~3 段录音上对比
num_speakers和min/max_speakers的效果差异,找到你场景的合理参数; - 有空:读一遍
src/pyannote/audio/pipelines/speaker_diarization.py的 docstring,理解管道每一步在做什么,为后续微调打基础。
打开终端,跑通你的第一段说话人分析。
【免费下载链接】pyannote-audioNeural building blocks for speaker diarization: speech activity detection, speaker change detection, overlapped speech detection, speaker embedding项目地址: https://gitcode.com/GitHub_Trending/py/pyannote-audio
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考