声纹识别项目说明

项目概述

该项目基于PaddlePaddle框架实现了高效的声纹识别系统,支持声纹注册、识别和对比功能。通过ECAPA-TDNN模型提取声纹特征,使用余弦相似度计算特征相似度,从而实现说话人识别。

模型架构

  • 骨干网络:ECAPA-TDNN(增强通道注意力、传播和聚合的TDNN)
  • 特征提取:通过AttentiveStatisticsPooling(ASP)池化层生成192维特征向量
  • 损失函数:AAMLoss(加性角度间隔损失)+ 余弦相似度对比

安装依赖

# 创建虚拟环境
conda create -n voice_recognition python=3.8
conda activate voice_recognition

# 安装PaddlePaddle
pip install paddlepaddle-gpu==2.4.2.post102 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html

# 安装其他依赖
pip install soundfile librosa matplotlib visualdl pyaudio paddleaudio

数据准备

  1. 创建dataset目录,结构如下:
dataset/
├── train_list.txt      # 训练数据列表
├── test_list.txt       # 测试数据列表
├── enroll_list.txt     # 注册数据列表
└── noise/              # 噪声数据
  1. 数据格式示例(train_list.txt):
/path/to/audio1.wav  speaker1
/path/to/audio2.wav  speaker1
/path/to/audio3.wav  speaker2

训练模型

# 单卡训练
python train.py

# 多卡训练
python -m paddle.distributed.launch --gpus '0,1' train.py

训练参数说明

  • 配置文件configs/ecapa_tdnn.yml
  • 关键参数
  • model_conf:模型参数(嵌入维度、池化方式等)
  • loss_conf:损失函数参数(角度间隔、缩放因子等)
  • optimizer_conf:优化器参数(学习率、衰减策略等)

模型评估

python eval.py

评估指标

  • EER(等错误率):模型区分说话人和非说话人的能力
  • MinDCF(最小检测成本函数):综合考虑误报和漏报成本

声纹对比

python infer_contrast.py --audio_path1=audio/a_1.wav --audio_path2=audio/b_2.wav

核心功能

  • 计算两个音频文件的特征相似度
  • 通过阈值判断是否为同一说话人
  • 支持命令行和GUI界面两种操作模式

声纹识别

python infer_recognition.py

核心功能

  • 注册:将音频录入声纹库并保存特征
  • 识别:将测试音频与声纹库比对并返回结果
  • 管理:支持用户增删和语音实时识别

关键代码解析

特征提取

def extract_feature(wav_path, sample_rate=16000):
    """音频特征提取函数"""
    audio, _ = librosa.load(wav_path, sr=sample_rate)
    # 预处理
    if len(audio) < sample_rate:
        audio = np.pad(audio, (0, sample_rate - len(audio)), mode='constant')

    # 特征提取
    stft = librosa.stft(audio, n_fft=512, hop_length=160, win_length=400)
    spec = np.abs(stft)
    mel_basis = librosa.filters.mel(sr=sample_rate, n_fft=512, n_mels=80)
    mel_spec = np.dot(mel_basis, spec)
    log_mel_spec = np.log(mel_spec + 1e-6)

    return log_mel_spec.T  # 返回特征矩阵

模型前向计算

def forward(self, x):
    """模型前向传播"""
    x = self.conv1(x)
    x = self.bn1(x)
    x = self.relu(x)

    for block in self.blocks:
        x = block(x)

    x = self.avg_pool(x)
    x = self.fc(x)
    x = self.tanh(x)

    return x

相似度计算

def similarity_score(feat1, feat2):
    """计算特征相似度"""
    feat1 = feat1.flatten()
    feat2 = feat2.flatten()
    norm1 = np.linalg.norm(feat1)
    norm2 = np.linalg.norm(feat2)
    if norm1 == 0 or norm2 == 0:
        return 0.0
    return np.dot(feat1, feat2) / (norm1 * norm2)

模型推理

声纹注册

def register_audio_to_db(audio_path, user_name):
    """将音频注册到声纹库"""
    feature = extract_feature(audio_path)
    feature = feature.reshape(1, 80, 32)  # 调整维度适配模型输入

    # 模型推理
    with paddle.no_grad():
        feat = model(feature)

    # 保存特征到数据库
    if not os.path.exists("audio_db"):
        os.makedirs("audio_db")
    save_path = f"audio_db/{user_name}.npy"
    np.save(save_path, feat.numpy())
    print(f"已注册用户:{user_name}")

声纹识别

def recognize_speaker(audio_path):
    """识别说话人"""
    feature = extract_feature(audio_path)
    feature = feature.reshape(1, 80, 32)

    with paddle.no_grad():
        query_feat = model(feature)

    max_score = 0.0
    best_user = "unknown"

    # 遍历声纹库
    for user in os.listdir("audio_db"):
        if user.endswith(".npy"):
            db_feat = np.load(f"audio_db/{user}")
            score = similarity_score(query_feat.numpy(), db_feat)
            if score > max_score:
                max_score = score
                best_user = user[:-4]

    return best_user, max_score

性能指标

  • 训练集:准确率 > 95%
  • 测试集:EER < 5%
  • 模型大小:~8MB
  • 推理速度:单音频 < 100ms

可视化监控

visualdl --logdir=log --host=0.0.0.0

扩展功能

  1. 实时声纹识别:修改infer_recognition_gui.py支持实时录音
  2. API服务:使用Flask/FastAPI封装识别接口
  3. 多模态融合:结合文本、图像特征提升识别鲁棒性

项目特点

  • 高性能:ECAPA-TDNN模型实现高精度特征提取
  • 易部署:支持CPU/GPU多平台部署
  • 可扩展:支持多种模型和数据集

参考资料

  1. PaddleSpeech
  2. ECAPA-TDNN论文
  3. PaddleAudio

通过以上步骤,您可以快速搭建一个完整的声纹识别系统,实现从数据准备、模型训练到最终应用的全流程。如需进一步优化,可尝试调整模型参数、增加数据增强或使用预训练模型进行迁移学习。

Xiaoye