基于 FunASR 1.2.7 为 SenseVoice 引擎增加了说话人分离(Speaker Diarization)功能,可以自动识别音频中的不同说话人并为每个语音段分配说话人标签。
你提出的方案完全可行,而且思路非常正确!
- 使用 FunASR 分割说话人音频
- 用 SenseVoice 对每个片段做语音识别
- 汇总整体结果
- ✅ 使用 SenseVoice 的 VAD 检测语音段
- ✅ 使用 FunASR 的说话人特征提取模型(
damo/speech_campplus_sv_zh-cn_16k-common) - ✅ 使用聚类算法(Agglomerative Clustering)自动识别说话人数量
- ✅ 用 SenseVoice 对每个语音段进行识别
- ✅ 合并结果并分配说话人标签
优势:
- 🚀 更高效:VAD + 特征提取 + 聚类,一次性完成
- 🎯 更准确:基于深度学习的说话人特征向量(embedding)
- 🔧 更灵活:自动识别说话人数量,无需预先指定
- 📦 完全集成:无需手动分割音频文件
-
SenseVoice 模型 (
iic/SenseVoiceSmall)- 多语言语音识别
- VAD 语音活动检测
- 情感识别
-
说话人特征提取模型 (
damo/speech_campplus_sv_zh-cn_16k-common)- 提取说话人特征向量(192/512 维)
- 支持中文和多语言
-
聚类算法 (Agglomerative Clustering)
- 自动识别说话人数量
- 基于特征相似度分组
- 无需预先指定聚类数
音频输入 (meeting.mp3)
↓
[1] VAD 语音活动检测
↓ (检测到 45 个语音段)
[2] 说话人特征提取
↓ (提取每个语音段的 512 维特征向量)
[3] 层次聚类分析
↓ (自动识别出 3 位说话人)
[4] 语音识别
↓ (使用 SenseVoice 识别每个语音段)
[5] 结果合并
↓
输出 (带说话人标签的转写文本)
主要修改:
class SenseVoiceEngine:
# 新增:说话人分离模型
_sd_model = None
def __init__(self, ..., enable_speaker_diarization=True):
"""新增参数:enable_speaker_diarization"""
self.enable_speaker_diarization = enable_speaker_diarization
def _load_speaker_diarization_model(self):
"""加载说话人特征提取模型"""
self._sd_model = AutoModel(
model="damo/speech_campplus_sv_zh-cn_16k-common",
device=self.device,
)
def parse(self, ..., **kwargs):
"""支持说话人分离的语音识别"""
if enable_sd and sd_model is not None:
# 使用说话人分离模式
parsed_result = self._parse_with_speaker_diarization(...)
else:
# 基础识别模式
result = model.generate(...)
def _parse_with_speaker_diarization(self, ...):
"""说话人分离模式的核心实现"""
# 1. VAD 检测
# 2. 特征提取
# 3. 聚类分析
# 4. 分配说话人标签
def _assign_speakers_to_segments(self, ...):
"""为语音段分配说话人标签"""
# 使用聚类算法识别说话人
clustering = AgglomerativeClustering(
n_clusters=None,
distance_threshold=0.5,
linkage="average",
)- funasr>=1.1.0
+ funasr>=1.2.7 # 支持说话人分离
+ soundfile>=0.12.0 # 音频文件 I/O
+ scikit-learn>=1.3.0 # 聚类算法- ✅
backend/audio_engines/SPEAKER_DIARIZATION.md- 详细技术文档 - ✅
backend/audio_engines/QUICKSTART_SPEAKER_DIARIZATION.md- 快速开始指南 - ✅
backend/audio_engines/test_speaker_diarization.py- 测试脚本 - ✅ 更新
backend/audio_engines/README.md
from audio_engines import SenseVoiceEngine
# 初始化引擎(默认启用说话人分离)
engine = SenseVoiceEngine(
device="cuda:0",
enable_speaker_diarization=True
)
# 处理音频
result = engine.parse(
audio_path="meeting.mp3",
output_path="./output",
language="auto"
)
# 查看结果
metadata = result['json_data']['metadata']
print(f"检测到 {metadata['speaker_count']} 位说话人")
print(f"说话人列表: {metadata['speakers']}")
# 查看每个分段的说话人
for seg in result['json_data']['content']['segments']:
print(f"[{seg['speaker']}] {seg['text']}")说话人分离功能已自动集成,无需额外配置:
# 提交音频任务
curl -X POST http://localhost:8000/api/v1/tasks \
-F "file=@meeting.mp3" \
-F "backend=sensevoice" \
-H "Authorization: Bearer YOUR_TOKEN"# 测试说话人分离
python backend/audio_engines/test_speaker_diarization.py --audio test.mp3
# 对比测试(启用 vs 禁用)
python backend/audio_engines/test_speaker_diarization.py --audio test.mp3 --no-diarization{
"metadata": {
"language": "zh",
"speakers": ["SPEAKER_00", "SPEAKER_01", "SPEAKER_02"],
"speaker_count": 3,
"speaker_diarization_enabled": true
},
"content": {
"segments": [
{
"id": 0,
"text": "大家好,今天我们讨论项目进展",
"start": 0.0,
"end": 3.5,
"speaker": "SPEAKER_00",
"emotion": "NEUTRAL",
"language": "zh"
}
]
}
}# 语音转写:meeting.mp3
**语言**: 🇨🇳 中文
**说话人数**: 3
**说话人**: SPEAKER_00, SPEAKER_01, SPEAKER_02
## 分段转写
**SPEAKER_00**:
[00:00] 大家好,今天我们讨论项目进展
**SPEAKER_01**:
[00:03] 好的,我先汇报一下我们组的情况-
自动识别说话人数量
- 无需预先指定
- 基于层次聚类算法
- 可调整距离阈值
-
高精度说话人分离
- 基于深度学习特征提取
- 512 维说话人特征向量
- 余弦相似度度量
-
完全集成
- 无需手动分割音频
- 一次性完成识别和分离
- 统一的输出格式
-
灵活配置
- 可启用/禁用说话人分离
- 可调整聚类参数
- 支持 GPU 加速
如果说话人识别不准确,可以调整聚类参数:
# 在 sensevoice_engine.py 中修改
clustering = AgglomerativeClustering(
distance_threshold=0.5, # 降低 → 更多说话人
# 提高 → 更少说话人
)建议范围:0.3 - 0.7
# 跳过过短的语音段
if len(audio_segment) < sr * 0.5: # 最小 0.5 秒
continuefunasr>=1.2.7 # FunASR 框架
soundfile>=0.12.0 # 音频文件 I/O
scikit-learn>=1.3.0 # 聚类算法
numpy>=1.26.0 # 数值计算ffmpeg # 音频处理A: 调整 distance_threshold 参数(0.3-0.7)
A:
- 使用 GPU:
device="cuda:0" - 禁用说话人分离:
enable_speaker_diarization=False
A: 检查:
- 音频质量(采样率、信噪比)
- 说话人分离模型是否正确加载
- 查看日志中的详细错误信息
你的方案思路非常正确!我们基于 FunASR 1.2.7 实现了完整的说话人分离功能,并进行了以下优化:
- ✅ 使用 VAD + 特征提取 + 聚类,一次性完成
- ✅ 自动识别说话人数量,无需预先指定
- ✅ 完全集成到 SenseVoice 引擎,无需手动分割
- ✅ 统一的输出格式(JSON + Markdown)
- ✅ 支持 GPU 加速,性能优秀
- 📦 安装依赖:
pip install funasr>=1.2.7 soundfile scikit-learn - 🧪 运行测试:
python backend/audio_engines/test_speaker_diarization.py --audio test.mp3 - 📖 阅读文档:
backend/audio_engines/SPEAKER_DIARIZATION.md - 🚀 集成使用:已自动集成到 MinerU Server
- ✅
backend/audio_engines/sensevoice_engine.py- 核心实现 - ✅
backend/requirements.txt- 依赖更新 - ✅
backend/audio_engines/SPEAKER_DIARIZATION.md- 详细文档 - ✅
backend/audio_engines/QUICKSTART_SPEAKER_DIARIZATION.md- 快速开始 - ✅
backend/audio_engines/test_speaker_diarization.py- 测试脚本 - ✅
backend/audio_engines/README.md- 更新说明 - ✅
SPEAKER_DIARIZATION_IMPLEMENTATION.md- 实现总结(本文档)
实现完成! 🎉
你的方案完全可行,我已经基于 FunASR 1.2.7 实现了完整的说话人分离功能。现在可以开始测试和使用了!