# 音声クローニングの基礎知識 ## 基本的な音声クローニングの流れ 1. **入力音声の受領** - ユーザーが提供する参照音声ファイル(例: WAV, FLAC)を受け取り、メタデータ(サンプルレート、チャンネル数、録音環境など)を確認する。 2. **前処理** - 参照音声をターゲットサンプルレートへリサンプリングし、正規化・ノイズ抑制・無音トリミングを行ってモデルが扱いやすい波形に整形する。 3. **話者特徴抽出** - Encodec や speaker encoder で参照音声から話者埋め込み/離散コードを算出し、後段のモデルが個性を再現できるようにする。 4. **テキスト準備** - 合成したい文章が未提供なら ASR で参照音声から文字起こしし、言語識別・正規化・句読点付与などを行う。ユーザー入力テキストがある場合も同様にクレンジングする。 5. **テキストトークナイズ** - 文章を G2P(音素化)や BPE などでトークン列へ変換し、音響モデルが扱う形式に揃える。 6. **条件付き音響推論** - テキストトークンと話者特徴を条件として音響モデル(例: VALLE, VALL-E-X)が合成音声の中間表現(音声コード列やメルスペクトログラム)を生成する。 7. **ボコーダ復号** - Vocos や HiFi-GAN などのボコーダで中間表現を時間波形へ復元し、ターゲットサンプルレートの音声として出力する。 8. **後処理と書き出し** - 音量調整、ポストフィルタ、フェード処理などを行い、最終的な音声ファイル(例: WAV, MP3)として保存またはストリーム配信する。 ```mermaid graph TB A["参照音声ファイル
入力: Waveform
出力: Waveform"] --> B["前処理
入力: Waveform
出力: 正規化済み Waveform"] B --> C["話者特徴抽出
入力: 正規化 Waveform
出力: 話者埋め込み/離散コード"] B --> D["ASR/テキスト準備
入力: 正規化 Waveform、または事前設定済みのユーザ音声スクリプト
出力: クレンジング済みテキスト"] D --> E["音素化/トークナイズ
入力: クレンジング済みテキスト
出力: テキストトークン列"] C --> F E --> F["音響モデル推論 (VALLE 等)
入力: テキストトークン + 話者コード
出力: 中間音声表現"] F --> G["ボコーダ復号 (Vocos 等)
入力: 中間音声表現
出力: 合成 Waveform"] G --> H[後処理・書き出し
入力: 合成 Waveform
出力: 最終音声ファイル] ``` - Waveform: 時間を横軸、振幅(音圧/電圧など)を縦軸に取った信号の連続波形表現。録音された生の音声データ(PCM)は通常この形で扱われる。 ## 事前学習済みモデルのファインチューニング 1. **データセットの準備**: 参照話者の音声と対応テキストをペアで収集し、前処理・音素化・トークン化を行う。短時間・高品質なデータでも効果は出るが、発話バリエーションが多いほど安定する。 2. **特徴抽出の再計算**: 既存の `AudioTokenizer` や speaker encoder を用いて、ファインチューニング用データにも話者コード/埋め込みを付与する。音声が複数話者なら話者ラベルも管理する。 3. **学習設定の調整**: 低学習率、凍結したい層の指定、勾配クリッピング、早期終了など、オーバーフィットを防ぐハイパーパラメータを設定する。 4. **ファインチューニング実行**: 事前学習済み重みをロードしたモデルへ新データで追加学習し、定期的に検証セットで品質を確認する。必要に応じて音声評価(MOS、WER)や聴感チェックを行う。 5. **モデル保存と検証**: ベストなエポックのチェックポイントを保存し、推論パイプラインで問題ないか(速度、品質、安定性)を確認する。 最小限の PyTorch 例は以下のとおり。 ```python import torch from torch.utils.data import DataLoader model = load_vallex().to(device) model.load_state_dict(torch.load("pretrained.pt")) optimizer = torch.optim.AdamW(model.parameters(), lr=1e-5) criterion = torch.nn.functional.cross_entropy loader = DataLoader(finetune_dataset, batch_size=4, shuffle=True) model.train() for epoch in range(num_epochs): for batch in loader: text_tokens, audio_prompt_codes, target_codes = batch outputs = model( text_tokens.to(device), text_tokens_lens=text_tokens.lens.to(device), audio_prompts=audio_prompt_codes.to(device), ) loss = criterion(outputs.view(-1, outputs.size(-1)), target_codes.view(-1)) optimizer.zero_grad() loss.backward() optimizer.step() torch.save(model.state_dict(), f"finetuned-epoch{epoch}.pt") ``` 上記は概念的な骨組みであり、実際にはコラテーション、勾配累積、AMP、検証ループなどを組み合わせて品質と安定性を確保する。 ## Q&A ### 話者特徴抽出とは何か?話者埋め込みとは何か? 話者特徴抽出は、参照音声から話者固有の音質や発声スタイルなどを数値化し、音声合成モデルが「誰の声か」を理解できるようにする工程です。得られる数値表現を話者埋め込みと呼び、固定長ベクトルや離散コードとしてモデルへ条件付けに利用します。 ### 音素化とはなにか? 音素化(Phonemization)は、テキストを言語学的な最小音の並び(音素列)へ変換する処理です。英語なら G2P(Grapheme-to-Phoneme)モデルなどを用いて単語の綴りから発音記号を推定し、音質合成モデルにとって扱いやすいトークン列を作ります。 - 日本語例:「おはようございます」 → /o o ha joː go za i ma sɯ/ - 英語例:「Good morning」 → /ɡʊd mɔːrnɪŋ/ ### PCM とはなにか? PCM(Pulse Code Modulation)は、アナログ音声波形を一定間隔でサンプリングし、それぞれの振幅値を量子化してディジタル値として表現する方式です。一般的な WAV ファイルなどで採用され、非圧縮または可逆圧縮の音声データとして扱われます。