晴耕雨読

working in the fields on fine days and reading books on rainy days

[Python] Irodori-TTSの音声生成速度とGPU

Irodori-TTSは、日本語のテキストから音声を生成するモデルです。 v4.1-Smallでは、声の説明文(caption)だけでも生成でき、参照音声を渡して話者の特徴を指定することもできます。 この記事では、会話形式の解説動画用に数十行のセリフを合成した結果をもとに、CPUとGPUでの速度の違いを説明します。 計測した範囲では、合成はGPUで行うと速くなりました。 同じ条件で比べると、M1のMPS(GPU)での合成はCPUより約1.8倍速く、条件は揃っていないもののRTX 3060ではさらに速い結果でした。

この記事で分かることは次のとおりです。

  • 導入から1行の音声を生成するまでの手順
  • CPUとGPUの速度差と、GPUの速さを活かす使い方
  • 台本全体の所要時間の見積もり方

また、記事の最後に補足として、複数のセリフを同じ声で生成するために参照音声を固定した結果も紹介します。

この記事の実測値は2026年9月に得たものです。 主にApple M1搭載のMac(macOS 26.6.2、PyTorch 2.10.0)でv4.1-Smallを動かし、一部をWindows 11とRTX 3060でも確認しました。 速度は機器、入力文、参照音声、推論設定によって変わるため、数値は目安として読んでください。

導入と音声生成

検証時と同じコードを使えるよう、Irodori-TTSを特定のコミットに固定します。 macOSではuv sync --extra cpuで依存パッケージを導入しました。 このcpuは依存パッケージの選択名で、推論をCPUに限定する指定ではありません。 この方法で導入したPyTorchでもMPS(Apple SiliconのGPU)を使えました。

git clone https://github.com/Aratako/Irodori-TTS.git
cd Irodori-TTS
git checkout --detach 89f9d8fbd4d51ea019867ee1197725ede1df13c5
uv sync --extra cpu

次のコマンドは、クローンしたIrodori-TTSディレクトリで実行し、声の説明文だけから1行のWAVを作ります。 参照音声を使わない場合は--no-refを指定します。 --seedは生成に使う乱数を決める値で、固定すると同じ結果を得やすくなります。

mkdir -p outputs
uv run --no-sync python infer.py \
  --hf-checkpoint Aratako/Irodori-TTS-v4.1-Small \
  --text "次は動画編集について。" \
  --caption "落ち着いた女性の声。明瞭に話す。" \
  --no-ref \
  --seed 1234 \
  --model-device mps --codec-device mps \
  --output-wav outputs/sample.wav

出力は48kHzのWAVです。 初回はHugging Faceからモデル(約2.9GB)と音声コーデック(約414MB)をダウンロードします。 WindowsでNVIDIA GPUを使う場合は、uv sync --extra cu128で導入し、--model-deviceと--codec-deviceをcudaに変更します。

CPUとGPUの合成速度

GPUでどれだけ速くなるかを確かめるため、短文「次は動画編集について。」を、seed 1000、FP32、40ステップの同じ条件で、M1のCPUとMPS(GPU)でそれぞれ合成しました。

Apple M1での計測(各1回) CPU MPS
合成時間 17.28秒 9.79秒
モデルのロードを含む初回音声までの時間 25.88秒 25.61秒

合成時間は、MPSの方がCPUより約43%短く、約1.8倍の速さでした。 しかし、ロードを含めた初回音声までの時間はほぼ同じです。 初回音声までの時間から合成時間を引くと、ロードなど合成以外にかかった時間はCPUが約8.6秒、MPSが約15.8秒で、MPSの方が長くなりました。 1行だけを生成する場合は、合成で縮めた時間がこの差でほぼ打ち消されます。 合成以外の時間はプロセスの起動ごとにかかるため、モデルを一度ロードし、同じプロセスで複数行を続けて合成すると、行数が増えるほどGPUでの短縮分が積み上がります。

NVIDIA GPUでは、さらに速い結果が出ました。 Windows 11とRTX 3060では、別の台本を合成して約2秒/行でした。 M1のMPSで8行を続けて合成したときは平均19.89秒/行だったので、約10倍の差です(M1の計測の詳細は次節で示します)。 入力した台本が異なるため厳密な比較ではありませんが、差の大きさから見て、NVIDIA GPUを使える環境では長い台本をそちらで生成すると待ち時間を大きく減らせる見込みがあります。

台本全体の所要時間の見積もり

1行ごとにinfer.pyを起動すると、そのたびにモデルを読み込みます。 そのため、台本全体の所要時間を見積もるときは、モデルのロードと音声合成の時間を分けて考える必要があります。 M1のMPSでモデルを一度だけロードし、参照音声なし、FP32、40ステップで8行を続けて合成した結果は次のとおりです。

Apple M1、MPSでの計測 結果
モデルのロード 15.1秒
8行の平均合成時間 19.89秒/行
8行の平均RTF 3.25

RTFは、合成時間を生成された音声の長さで割った値です。 RTFが3.25なら、音声1秒の生成に約3.25秒かかったことになります。 たとえば3分半の音声なら、MPSを使っても合成だけで10分以上かかる計算です。 ただし8行だけの平均なので、台本の文の長さによって前後します。

ステップ数と合成時間の関係

同じ文の合成時間は、40ステップで17.34秒、8ステップで8.11秒でした。 ステップ数を80%減らしても、所要時間の減少は約53%にとどまります。 音声長の予測、潜在表現からのデコード、電子透かしの付与など、ステップ数に依存しない処理が残るためです。 なお、この試験では音質を比較していないため、速度だけを理由に8ステップを勧めることはできません。

まとめ

Irodori-TTSで台本を音声にするときは、合成をGPUで行うと待ち時間を減らせます。 M1のMPSでもCPUより約1.8倍速く、NVIDIA GPUを使える環境ではさらに短くなる見込みがあります。 ただし、MPSはロードなど合成以外の時間がCPUより長いため、モデルは一度だけロードして複数行を続けて合成します。 所要時間はロードと合成を分けて見積もり、M1のMPSではRTF約3を目安にします。

(補足) captionだけで話者の声を揃えられるか

速度の話からは外れますが、会話動画用にセリフを合成するなかで、声の揃え方についても分かったことがあったので補足します。

同じ声の説明文とseedを使っても、読み上げる文が変わると声の高さが大きく変わる場合がありました。 明るい声を指定して3文を生成したところ、基本周波数(声の高さ)の中央値が200.0Hzから381.0Hzまで開きました。 会話動画では、同じ人物の声が文ごとに変わって聞こえてしまいます。

そこで、同じモデルで生成した約6秒の音声を参照音声として指定し、3文を生成し直しました。

条件 3文の基本周波数の中央値
説明文のみ 200.0Hz、271.2Hz、381.0Hz
説明文と約6秒の参照音声 263.7Hz、268.2Hz、296.3Hz

参照音声を固定すると、高さのばらつきが小さくなりました。

参照音声を使うには、--no-refを--ref-wav path/to/reference.wavに置き換えます。 --captionは併用できます。

ただし、3文だけの計測であり、基本周波数だけで同じ声かを判定することもできません。 また、参照音声と合成後の声の高さは一致するとは限らず、試した候補では参照音声より約16%低いものから約15%高いものまでありました。 参照音声を選ぶときは、実際に使うcaptionと複数の文で合成し、同じ人物に聞こえるかを耳で確認する必要があります。

参照音声の利用条件

参照音声を使う場合は、録音の利用条件と、声の持ち主の同意を確認してください。 Irodori-TTSのモデルカードでも、本人の明示的な同意なしに声を複製することは禁止されています。 自分で生成した音声を参照にする場合も、その音声を作ったサービスの利用条件は別途確認が必要です。

参照資料