说话人嵌入向量

使用 WeSpeaker ResNet34-LM 提取 256 维 L2 归一化的说话人向量。这些 embedding 捕获说话人独特的声学特征,可用于识别、验证和声音检索。

架构

WeSpeaker ResNet34-LM 是一个深度残差网络,用于说话人表示学习。

阶段细节
输入Conv2d(1 到 32 通道)
ResNet34[3, 4, 6, 3] 残差块
统计池化时间维度上的均值 + 标准差
投影Linear(5120 到 256)
输出L2 归一化的 256 维 embedding

模型大小:约 6.6M 参数,磁盘约 25 MB。

Mel 特征

模型使用由 Hamming 窗计算的 80 维 mel 频率特征。对数缩放使用简单的 log(max(mel, 1e-10)) 公式,无需额外归一化。为提高推理效率,batch normalization 在转换时就已融合到 Conv2d 层中。

CLI 使用

# 提取说话人 embedding
.build/release/audio embed-speaker voice.wav

# JSON 输出(包含 256 维向量)
.build/release/audio embed-speaker voice.wav --json

# 选择推理引擎
.build/release/audio embed-speaker voice.wav --engine coreml

选项

选项说明
--engine推理引擎:mlxcoreml
--json含完整 embedding 向量的 JSON 输出格式

使用场景

说话人验证

对比两段音频,判断是否来自同一个说话人。分别提取 embedding 并计算余弦相似度。相似度越高,属于同一说话人的概率越大。

import SpeechVAD

let model = try await WeSpeaker.loadFromHub()
let embedding1 = try await model.embed(audioFile: "sample1.wav")
let embedding2 = try await model.embed(audioFile: "sample2.wav")

let similarity = cosineSimilarity(embedding1, embedding2)
print("Similarity: \(similarity)")  // > 0.7 通常为同一说话人

说话人识别

将一段未知音频与已注册的说话人 embedding 数据库匹配。余弦相似度最高的已注册说话人即为预测身份。

声音检索

按说话人 embedding 为一组音频录音建立索引,然后用一段新音频查询,找出所有同一说话人的录音。

重要

说话人嵌入向量在至少 2-3 秒的干净语音上效果最佳。非常短的片段或嘈杂录音可能会得到不太可靠的 embedding。对于嘈杂音频,可考虑先应用语音增强

模型下载

模型后端大小HuggingFace
WeSpeaker-ResNet34-LMMLX~25 MBaufklarer/WeSpeaker-ResNet34-LM-MLX
WeSpeaker-ResNet34-LMCoreML~25 MBaufklarer/WeSpeaker-ResNet34-LM-CoreML

Swift API

import SpeechVAD

let model = try await WeSpeaker.loadFromHub()

// 从文件提取 embedding
let embedding = try await model.embed(audioFile: "voice.wav")
print("Embedding dimensions: \(embedding.count)")  // 256

// 从音频样本提取 embedding
let samples: [Float] = loadAudio("voice.wav")
let embedding = try await model.embed(samples: samples, sampleRate: 16000)