引子
上篇文章我们介绍了 FunASR 实时语音识别,今天来玩另一个阿里开源的好东西——3D-Speaker。
3D-Speaker 是阿里巴巴通义实验室开源的说话人识别与分割(Speaker Diarization)工具包,可以实现:
- 🎤 声纹识别:判断两段音频是不是同一个人
- 👥 说话人分割:分辨一段音频里有几个说话人、谁在什么时候说话
- 🌐 语种识别:判断音频说的是什么语言
- 🎬 多模态识别:结合视频画面进一步提升准确率
非常适合做会议记录、语音助手身份验证、音频检索等场景。
环境准备
系统依赖
1 2 3 4 5 6 7 8 9 10
| sudo apt update sudo apt install -y \ git \ wget \ ffmpeg \ cmake \ build-essential \ libsndfile1 \ pkg-config
|
Python 环境(推荐 conda)
1 2 3 4 5 6 7
| wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh
conda create -n 3D-Speaker python=3.8 conda activate 3D-Speaker
|
CUDA(可选,有 GPU 加速更快)
1 2 3 4 5 6 7 8 9 10 11
| nvidia-smi
wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run sudo sh cuda_11.8.0_520.61.05_linux.run
echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc source ~/.bashrc
|
安装 3D-Speaker
方式一:源码安装(推荐开发者)
1 2 3 4 5 6 7 8 9
| git clone https://github.com/modelscope/3D-Speaker.git cd 3D-Speaker
pip install -r requirements.txt
pip install modelscope
|
⚠️ 注意:requirements.txt 要求 numpy<1.24,如果你之前装过 numpy,需要先卸载重装。
1 2
| pip uninstall numpy pip install 'numpy>=1.20.0,<1.24'
|
方式二:仅安装 ModelScope(最简部署)
如果你只想用预训练模型做推理,不需要训练,可以只装必要的包:
1 2 3 4 5 6 7
| conda create -n 3D-Speaker python=3.8 conda activate 3D-Speaker
pip install torch torchaudio pip install modelscope pip install scikit-learn==1.0.2 pip install soundfile scipy tqdm pyyaml
|
快速体验:使用预训练模型
3D-Speaker 在 ModelScope 上提供了大量预训练模型,可以直接下载使用。
方案一:Python SDK 推理(最简单)
1. 说话人验证(判断两段音频是否为同一人)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| from modelscope.hub.snapshot_download import snapshot_download from modelscope.pipelines import pipeline import soundfile as sf import numpy as np
model_dir = snapshot_download('iic/speech_campplus_sv_zh-cn_16k-common')
sv_pipeline = pipeline( tasks='speaker-verification', model=model_dir, )
audio1 = 'audio/person1.wav' audio2 = 'audio/person1_another.wav'
result = sv_pipeline(audio1) embedding1 = result['spk_embedding']
result = sv_pipeline(audio2) embedding2 = result['spk_embedding']
from sklearn.metrics.pairwise import cosine_similarity similarity = cosine_similarity([embedding1], [embedding2])[0][0]
print(f"相似度: {similarity:.4f}") print(f"是否为同一人: {similarity > 0.5}")
|
2. 批量说话人验证
1 2 3 4 5 6 7 8
|
python speakerlab/bin/infer_sv_batch.py \ --model_id iic/speech_campplus_sv_zh-cn_16k-common \ --wavs /path/to/wav.scp
|
3. 说话人分割(diarization)
1 2 3 4 5 6 7 8 9 10
| pip install pyannote.audio
model_dir = snapshot_download('iic/speech_diarization_sond-unified')
python speakerlab/bin/infer_diarization.py \ --wav /path/to/meeting.wav \ --out_dir ./diarization_output
|
带 overlap 检测(需要 HuggingFace token):
1 2 3 4 5 6 7
| export HF_ACCESS_TOKEN=your_huggingface_token
python speakerlab/bin/infer_diarization.py \ --wav /path/to/meeting.wav \ --out_dir ./output \ --include_overlap \ --hf_access_token $HF_ACCESS_TOKEN
|
方案二:直接用 Python 推理脚本
项目提供了封装好的脚本,不需要写代码:
1 2 3 4 5 6 7 8
| python speakerlab/bin/infer_sv.py \ --model_id iic/speech_campplus_sv_zh-cn_16k-common
python speakerlab/bin/infer_sv_batch.py \ --model_id iic/speech_campplus_sv_zh-cn_16k-common \ --wavs ./wav.scp
|
训练自己的模型
如果预训练模型不满足需求,可以在自己数据上微调。
准备训练数据
3D-Speaker 支持多个数据集格式,以 3D-Speaker 数据集为例:
1 2 3
| cd egs/3dspeaker/sv-cam++/ bash run.sh --stage 0 --stop_stage 0
|
开始训练
1 2 3 4 5 6 7 8
| cd egs/3dspeaker/sv-cam++/
bash run.sh
cd ../sv-eres2netv2/ bash run.sh
|
训练会在 exp/ 目录下生成模型checkpoint。
ONNX 部署方案(生产环境推荐)
对于生产环境,ONNX 部署更轻量,不需要安装 PyTorch。
导出 ONNX 模型
1 2 3 4 5 6 7 8
| pip install onnx onnxruntime
python speakerlab/bin/export_speaker_embedding_onnx.py \ --experiment_path /path/to/model \ --model_id iic/speech_eres2net_sv_zh-cn_16k-common \ --target_onnx_file ./model.onnx
|
编译 ONNX Runtime
1 2 3 4 5 6 7 8
| sudo apt install cmake build-essential
cd runtime/onnxruntime/ mkdir build && cd build cmake .. make
|
编译完成后,build/bin/ 下会有三个可执行文件:
| 文件 | 说明 |
|---|
extract_speaker_embedding | 提取说话人向量 |
make_fbank_feature | 提取 FBank 特征 |
read_and_describe_wav | 读取并处理 WAV |
使用编译后的二进制文件
1 2 3 4 5 6 7 8 9 10
|
./extract_speaker_embedding \ /path/to/fbank_config.json \ /path/to/model.onnx \ /path/to/wav.scp \ ./embedding.scp \ ./embeddings/
|
Docker 部署
3D-Speaker 没有提供官方 Docker 镜像,但可以用自定义 Dockerfile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04
ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y \ python3.8 python3-pip ffmpeg libsndfile1 git
WORKDIR /app
RUN pip3 install torch torchaudio --index-url https://download.pytorch.org/whl/cu118
COPY . /app/3D-Speaker WORKDIR /app/3D-Speaker RUN pip3 install -r requirements.txt RUN pip3 install modelscope
CMD ["bash"]
|
构建并运行:
1 2 3 4 5 6 7
| docker build -t 3d-speaker:latest .
docker run --gpus all -it \ -v $PWD:/workspace \ 3d-speaker:latest
|
完整使用示例
示例 1:会议录音分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from modelscope.pipelines import pipeline from modelscope.hub.snapshot_download import snapshot_download
print("下载模型中...") model_dir = snapshot_download('iic/speech_campplus_sv_zh-cn_16k-common')
sv_pipeline = pipeline(tasks='speaker-verification', model=model_dir)
meeting_audio = 'meeting.wav' result = sv_pipeline(meeting_audio) print(f"说话人数量估计: {len(result)}")
|
示例 2:声纹注册与识别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| from modelscope.pipelines import pipeline from modelscope.hub.snapshot_download import snapshot_download import numpy as np
known_speakers = { '张三': 'audio/zhangsan.wav', '李四': 'audio/lisi.wav', '王五': 'audio/wangwu.wav', }
model_dir = snapshot_download('iic/speech_campplus_sv_zh-cn_16k-common') sv_pipeline = pipeline(tasks='speaker-verification', model=model_dir)
print("注册声纹中...") embeddings = {} for name, path in known_speakers.items(): result = sv_pipeline(path) embeddings[name] = result['spk_embedding'] print(f" {name} 注册完成")
unknown_audio = 'audio/unknown.wav' result = sv_pipeline(unknown_audio) unknown_embedding = result['spk_embedding']
from sklearn.metrics.pairwise import cosine_similarity best_match = None best_score = -1
for name, emb in embeddings.items(): score = cosine_similarity([unknown_embedding], [emb])[0][0] print(f"{name}: {score:.4f}") if score > best_score: best_score = score best_match = name
threshold = 0.5 if best_score > threshold: print(f"\n识别结果: {best_match} (相似度: {best_score:.4f})") else: print(f"\n未识别到已知说话人 (最高相似度: {best_score:.4f})")
|
常见问题
Q: 报错 numpy.dtype 大小不匹配?
1 2 3
| pip uninstall numpy pip install 'numpy>=1.20.0,<1.24'
|
Q: ModelScope 下载模型很慢?
1 2 3 4
| import modelscope modelscope.set_cache_dir('/path/to/fast/disk')
modelscope.use_hub('cn-hub')
|
Q: 内存不足(CUDA OOM)?
1 2 3 4 5 6
| sv_pipeline = pipeline( tasks='speaker-verification', model=model_dir, kwargs={'batch_size': 1} )
|
Q: 如何处理非 16kHz 的音频?
1 2
| ffmpeg -i input.wav -ar 16000 -ac 1 output.wav
|
总结
3D-Speaker 提供了完整的说话人识别解决方案:
- ✅ 上手简单:ModelScope 直接下载预训练模型,几行代码就能跑
- ✅ 性能优秀:中文场景 EER 低至 0.52%(VoxCeleb)
- ✅ 功能全面:验证、分割、语种识别全覆盖
- ✅ 部署灵活:Python / ONNX / Docker 多种选择
结合 FunASR 做语音识别,可以实现完整的语音交互分析系统——先识别内容(ASR),再判断是谁在说话(Speaker Verification)。
参考资料