初めに
以下の記事で Resemblyzerを使って似ている歌声を探してみました。今回は 別のモデルを使ってみます
開発環境
環境構築
uv venv .venv -p 3.12 .venv/Scripts/activate # Windowsの場合 uv pip install speechbrain torch torchaudio librosa numpy scikit-learn gdown uv pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu121 --forc
音声データの取得
以下の記事を参考にしてください。
流れは以下になります 1. youtube等から音源の取得 2. uvr等でボーカルのみを抽出
speaker-emb-ja-ecapa-tdnnを使って音声類似度比較を行う
以下を実行して似ているボーカルを探します
import torchaudio from pathlib import Path import numpy as np from sklearn.metrics.pairwise import cosine_similarity import torch import torch.nn.functional as F def get_embedding_speechbrain(audio_path_str, model): """指定された音声ファイルからECAPA-TDNNを使って埋め込みを抽出する""" fpath = Path(audio_path_str) if not fpath.exists(): print(f"エラー: 音声ファイルが見つかりません - {fpath}") return None try: wave, sr = torchaudio.load(fpath) # モデルのサンプルレートにリサンプリング if sr != model.sample_rate: wave = torchaudio.transforms.Resample(sr, model.sample_rate)(wave) # 埋め込み抽出 with torch.no_grad(): emb = model.extract_embedding(wave) emb = F.normalize(torch.FloatTensor(emb), p=2, dim=1).detach().cpu() return emb.squeeze().numpy() except Exception as e: print(f"エラー: {fpath} の処理中にエラーが発生しました: {e}") import traceback traceback.print_exc() return None def main(): try: print("ECAPA-TDNNモデルをロード中... (初回は時間がかかることがあります)") model = torch.hub.load("k-washi/speaker-emb-ja-ecapa-tdnn", "ecapatdnn_ja_l512_va", trust_repo=True, pretrained=True) # モデルを推論モードに設定 model.model.eval() print("モデルのロード完了。") except Exception as e: print(f"モデルの初期化に失敗しました: {e}") print("モデル名が正しいか、インターネット接続、torchのバージョンなどを確認してください。") import traceback traceback.print_exc() return # --- 音声ファイルのパスを指定 --- target_audio_path = Path("vocal_target.wav") candidate_audio_paths = [ Path("data/vocal_test.wav") ] print(f"ターゲット音声: {target_audio_path}") print("候補音声リスト:") for p in candidate_audio_paths: print(f"- {p}") print("-" * 30) # ターゲット音声の埋め込みを抽出 target_embedding = get_embedding_speechbrain(target_audio_path, model) if target_embedding is None: print("ターゲット音声の埋め込みが抽出できませんでした。処理を終了します。") return # 候補音声の埋め込みを抽出し、類似度を計算 similarities = [] for cand_path in candidate_audio_paths: print(f"\n候補音声 {cand_path} の処理中...") cand_embedding = get_embedding_speechbrain(cand_path, model) if cand_embedding is not None: similarity = cosine_similarity(target_embedding.reshape(1, -1), cand_embedding.reshape(1, -1))[0][0] similarities.append((str(cand_path), similarity)) print(f" 類似度: {similarity:.4f}") else: print(f" {cand_path} の埋め込み抽出に失敗しました。") similarities.sort(key=lambda x: x[1], reverse=True) print("\n--- 類似度ランキング (k-washi/speaker-emb-ja-ecapa-tdnn) ---") for path_str, score in similarities: print(f"{path_str}: {score:.4f}") if similarities: print(f"\n最も近いと思われる音声: {similarities[0][0]} (類似度: {similarities[0][1]:.4f})") else: print("\n類似度を計算できる候補がありませんでした。") if __name__ == "__main__": main()
実行すると以下になります
最も近いと思われる音声: data\vocal_target.wav (類似度: 0.8525)