XTTSv2 による Text-to-Speech を試す

text-generation-webui や SillyTavern のようなチャットUIでは、TTS(Text-to-Speech)による音声チャット用の拡張機能も利用することができます。

ただ、いろいろと触っているうちに物足りなくなり、Pythonで簡単な音声チャットアプリのDIYを始めました。素人なのでAIに頼りながらのコーディングです。

今のところ、TTSにはgTTS(Google TTS)ライブラリを使っています。手軽で英語も聞き取りやすいので重宝していますが、そのうちTTSもローカルで動かしたい願望があります。

主なText-to-Speechモデル

  • 以下のページで、オープンなTTSモデルの一覧がまとめられています。

github.com

  • 多すぎてよく分からないのが正直なところです。この中では「TorToiSe」「VITS」「XTTS」あたりが評判がよさそうです。
  • XTTS は SillyTavern のTTS拡張機能の一つとしても利用されていて「日本語も含む多言語対応」+「Voice Cloning対応」という点で魅力的です。
    • SillyTavern でXTTSv2を試したところ、なかなかリアルで良さそうです。PythonAPIとし扱うための手順を確認してみました。

XTTS-API-Server

  • 上記のRepoではGoogle Colabも掲載されているので、ひとまずColabで試します。個人的に修正した点は以下の2点です。
    • "Select Model Version" = "v2.0.3" のままだとエラーになったので、"main"に修正。
    • そのまま実行するとCPUモードになってしまうので、最後の「!python -m xtts_api_server {deepspeed_flag} -hs {host} -t {tunnel_url} -ms {Model_source} -v {Model_version} 」に「-d cuda」フラグを追加し、GPUで実行。
  • インストールと起動にけっこう時間がかかりますが、無事にcloudflare経由でAPIが起動しました。

  • ひとまず female_calm_wav というサンプル音源からCloneして使いました。当然 Cloneする音源は自分で用意したものも使えると思います。

PythonAPIを試す

  • 自分のPythonコードに組み込むため、いつも通りAIに投げてコードを書いてもらいます。
    • Mistral-medium がけっこう賢いと聞いたので、Poe.com 経由で Mistral-medium を使ってみました。

  • 最初に返ってきたコードは Playsound ライブラリがうまく動きませんでした。音声部を Pygame に修正してもらいます。

import requests
import json
import pygame
from io import BytesIO

# Set up the request parameters
url = "https://ion-because-continue-means.trycloudflare.com/tts_to_audio/"
headers = {"Content-Type": "application/json"}
data = {
    "text": "Hello. This is a test.",
    "speaker_wav": "female_calm",
    "language": "en"
}

# Make the POST request
response = requests.post(url, headers=headers, data=json.dumps(data))

# Check the response status code
if response.status_code == 200:
    # Decode the audio data from the response
    audio_data = response.content
    audio_stream = BytesIO(audio_data)

    # Set up the Pygame mixer
    pygame.mixer.init()
    pygame.mixer.music.load(audio_stream)
    pygame.mixer.music.play()

    # Wait for the audio to finish playing
    while pygame.mixer.music.get_busy():
        pygame.time.Clock().tick(10)
else:
    # Print the error message
    print("Error:", response.status_code, response.text)

  • とりあえずこれでPythonAPIが使えるようになりました。
  • Colab 経由なのでちょっと遅い(V100 GPU で1センテンスにつき1-3秒程度)ですが、ローカルにそれなりのGPU環境があればいい感じで動かせそうです。
  • 日本語でもけっこう自然な音声でした。日本語用途でもけっこういいかもしれません(肝心のローカルLLMの日本語性能は今一歩ですが)。