話者embedding

WeSpeaker ResNet34-LMを使用して256次元のL2正規化された話者ベクトルを抽出します。これらの埋め込みは話者の固有の声質特徴を捉え、識別、検証、音声検索に使用できます。

アーキテクチャ

WeSpeaker ResNet34-LMは、話者表現学習のためにトレーニングされた深い残差ネットワークです。

ステージ詳細
入力Conv2d (1から32チャネル)
ResNet34[3, 4, 6, 3] 残差ブロック
統計プーリング時間にわたる平均 + 標準偏差
プロジェクションLinear (5120から256)
出力L2正規化された256次元embedding

モデルサイズ:約6.6Mパラメーター、ディスク上約25 MB。

Mel特徴量

モデルはハミング窓で計算された80次元のmel周波数特徴量を使用します。log スケーリングは追加の正規化なしで単純なlog(max(mel, 1e-10))式を使用します。バッチ正規化は、推論効率のために変換時にConv2dレイヤーに融合されます。

CLIの使用法

# Extract speaker embedding
.build/release/speech embed-speaker voice.wav

# JSON output (includes the 256-dim vector)
.build/release/speech embed-speaker voice.wav --json

# Choose inference engine
.build/release/speech embed-speaker voice.wav --engine coreml

オプション

オプション説明
--engine推論エンジン:mlxまたはcoreml
--json完全なembeddingベクトルを含むJSON出力形式

ユースケース

話者検証

2つの音声サンプルを比較して、同じ話者によるものかどうかを判断します。両方から埋め込みを抽出し、コサイン類似度を計算します。類似度スコアが高いほど、同じ話者である確率が高くなります。

import SpeechVAD

let model = try await WeSpeakerModel.fromPretrained()

let samples1: [Float] = loadAudio("sample1.wav")
let samples2: [Float] = loadAudio("sample2.wav")
let embedding1 = model.embed(audio: samples1, sampleRate: 16000)
let embedding2 = model.embed(audio: samples2, sampleRate: 16000)

let similarity = WeSpeakerModel.cosineSimilarity(embedding1, embedding2)
print("Similarity: \(similarity)")  // > 0.7 typically same speaker

話者識別

未知の音声サンプルを登録済み話者embeddingのデータベースと照合します。最大のコサイン類似度を持つ登録済み話者が予測されるアイデンティティです。

音声検索

音声録音のコレクションを話者embeddingでインデックス付けし、新しい音声サンプルでクエリして、同じ話者からのすべての録音を見つけます。

重要

話者embeddingは、少なくとも2〜3秒のクリーンな音声で最高に機能します。非常に短いクリップやノイズの多い録音は、信頼性の低い埋め込みを生成する可能性があります。ノイズの多い音声については、最初に音声強調を適用することを検討してください。

モデルダウンロード

モデルバックエンドサイズ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 WeSpeakerModel.fromPretrained()

// Extract embedding from audio samples
let samples: [Float] = loadAudio("voice.wav")
let embedding = model.embed(audio: samples, sampleRate: 16000)
print("Embedding dimensions: \(embedding.count)")  // 256