Java でオフラインのテキスト読み上げ
Java の標準ライブラリーに音声合成が入ることはなかったため、プロジェクトは FreeTTS や MaryTTS のような古いエンジン(ニューラルの声と比べるとロボット的)か、文字数で課金しすべてのテキストを見るクラウド SDK に頼ってきました。
このガイドでは現代的な代替案を紹介します。無料の SuperClonica エンジンをローカルの HTTP サーバーとして動かし、Java 11 以降に組み込みの HttpClient で呼び出します。自然な声、手元に残る WAV ファイル、リクエストごとの料金なしを、どのプラットフォームでも。
Java から話す方法
エンジンは JVM の中では動きません。Java のコードはほかのサービスと同じように HTTP でやり取りします。
- FreeTTS と MaryTTS:純粋な Java でオフラインだが、ニューラルの声と比べるとロボット的。
- クラウド SDK:自然な声だが、アカウント、キー、文字数課金、そしてテキストは相手のサーバーへ。
- SuperClonica:自然な声、キャラクターの声、独自の声を使えるローカル HTTP サーバー。Docker が動けばどこでもオフラインで。
- 31言語を話します。中国語はまだ対応していません。
声を無料で聴く
コードを書く前に、どれかの声のページで30〜100文字のフレーズを入力し、言語を選んで生成ボタンを押しましょう。数秒で、アプリに持たせられる声を聴けます。アカウントは不要です。
音声サーバーを起動
NVIDIA のグラフィックカードがあれば cuda イメージで速くなりますが、必須ではありません。
- どのCPUでもサーバーを起動:docker run -d -p 8000:8000 -v superclonica-models:/models superclonica/superclonica:cpu。
- 初回起動で Supertonic 3 モデル(約385 MB)をボリュームにダウンロードします。準備ができたかは GET /health でわかります。
- POST /synthesize は text、voice、lang、seed、normalize を含む JSON を受け取り、16ビットモノラルの WAV を返します。
- voice は標準名 M1〜M5、F1〜F5、または声のファイルの JSON の中身です。
Java から呼び出す
java.net.http、java.net.URI、java.nio.file を使えば、Java 11 以降ではリクエストは数行です:var voice = Files.readString(Path.of("voice.json")); var json = "{\"text\": \"Java からこんにちは!\", \"lang\": \"ja\", \"seed\": 7, \"voice\": " + voice + "}"; var request = HttpRequest.newBuilder(URI.create("http://localhost:8000/synthesize")).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(json)).build(); HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofFile(Path.of("hello.wav"))); レスポンスはそのまま WAV ファイルに書き込まれます。標準の声なら、ファイルの中身の代わりに "voice": "F1" を送ります。同じテキスト、声、seed なら常に同じ音声になるので、繰り返すフレーズのファイルはキャッシュしましょう。大きなプロジェクトでは Jackson などの JSON ライブラリーを使うとリクエストを整理できます。
本番運用のコツ
HttpClient はひとつを使い回し、リクエストにタイムアウトを設定しましょう。ポート 8000 をそのままインターネットに公開しないでください。SUPERCLONICA_API_KEY を設定して Bearer トークンとして送るか、プライベートネットワーク内に置きます。同時リクエストが多いなら SUPERCLONICA_LANES でモデルのコピーを増やし、自分のハードウェアで計測してください。私たちのテストでは短いフレーズが RTX 5070 Ti で 0.12 秒、CPU 4スレッドで 0.43 秒でした。