pyannote 是一个专门用于 音频处理、说话人识别和说话人分割(speaker diarization) 的开源 Python 库,它在学术和工业界广泛用于会议分析、电话通话分析、播客处理等场景。它本身并不是单独的模型,而是一个 框架/工具集合,可以调用各种预训练模型来完成音频的分析任务。
下面我帮你梳理一下它的主要功能和特点:
1. 核心功能
说话人分割(Speaker Segmentation / Voice Activity Detection, VAD)
- 判断音频中哪些部分有人说话,哪些是静音。
输出时间段,例如:
0.0s - 1.5s : speech 1.5s - 2.0s : silence 2.0s - 3.2s : speech
说话人嵌入(Speaker Embedding)
- 将每一段语音转化为向量,用于区分不同说话人。
- 向量相似度高 → 很可能是同一个人。
说话人聚类 / 识别(Speaker Diarization)
- 自动识别音频中“谁在什么时候说话”。
输出示例:
SPEAKER_00: 0.0s - 1.5s SPEAKER_01: 1.5s - 2.8s SPEAKER_00: 2.8s - 4.0s
音频切片 / 活动检测
- 对长音频进行切片处理,方便后续模型分析。
多说话人环境支持
- 能够处理多人同时说话的复杂场景。
2. 特点
- 基于 PyTorch,支持 GPU 加速。
- 高度模块化,可以只用 VAD、只用嵌入,或者全流程。
- 兼容 Hugging Face 模型,可以直接加载预训练说话人模型。
- 开源和活跃维护,社区支持丰富。
3. 基本使用示例
假设你要对一个音频文件做说话人分割:
from pyannote.audio import Pipeline
# 加载预训练说话人分割 pipeline
pipeline = Pipeline.from_pretrained("pyannote/speaker-diarization")
# 处理音频文件
diarization = pipeline("audio.wav")
# 输出分割结果
for turn, _, speaker in diarization.itertracks(yield_label=True):
print(f"{turn.start:.1f}s - {turn.end:.1f}s: {speaker}")
输出类似:
0.0s - 2.5s: SPEAKER_00
2.5s - 5.0s: SPEAKER_01
实战
import torch
import soundfile as sf
from pyannote.audio import Pipeline
# -----------------------------
# 1. 配置 Hugging Face Token(必须)
# -----------------------------
# 请确保已运行:huggingface-cli login
# 并输入您的 Hugging Face Access Token(在 https://huggingface.co/settings/tokens 创建)
# -----------------------------
# 2. 读取音频文件(避开 torchcodec 问题)
# -----------------------------
audio_file = "vad_example.wav" # 请根据实际情况修改路径
waveform, sample_rate = sf.read(audio_file)
# 转换为 torch.Tensor,float32,shape 为 (channel, time)
waveform = torch.tensor(waveform, dtype=torch.float32)
if waveform.ndim == 1: # 单声道
waveform = waveform.unsqueeze(0)
else: # 多声道(soundfile 默认返回 (time, channel))
waveform = waveform.T
# -----------------------------
# 3. 加载预训练的说话人分割 pipeline(兼容新版本)
# -----------------------------
pipeline = Pipeline.from_pretrained(
"pyannote/speaker-diarization-3.1",
token=True # 使用已登录的 token
)
# -----------------------------
# 4. 执行说话人分割
# -----------------------------
diarization = pipeline({"waveform": waveform, "sample_rate": sample_rate})
# -----------------------------
# 5. 输出结果(适配新版本 DiarizeOutput)
# -----------------------------
print("说话人分割结果:")
for turn, speaker in diarization.speaker_diarization:
print(f"{turn.start:.2f}s - {turn.end:.2f}s | {speaker}")
