ガイド

Rust でオフラインのテキスト読み上げ

Rust には OS の音声エンジンをラップしたクレートがあり、アクセシビリティには十分ですが、声はロボット的でプラットフォームごとに違います。文字数課金のクラウド SDK もあります。どこでも同じ自然な声が必要なゲーム、ボット、コマンドラインツールには、どちらも理想的ではありません。

このガイドでは、無料の SuperClonica エンジンをローカルの HTTP サーバーとして使い、Rust から呼び出す方法を紹介します。自然な声、手元に残る WAV ファイル、reqwest で数行。

Rust から話す方法

スクリーンリーダー的な出力なら OS の声で十分。製品やゲームの声ならエンジンを。

  • OS の声をラップするクレート:オフラインで軽いが、ロボット的で Windows、macOS、Linux で違う。
  • クラウド 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 の中身です。

Rust から呼び出す

reqwest クレートの blocking 機能を使えば、Result を返す関数の中でリクエストは数行です:let voice = std::fs::read_to_string("voice.json")?; let body = format!(r#"{{"text": "Rust からこんにちは!", "lang": "ja", "seed": 7, "voice": {voice}}}"#); let wav = reqwest::blocking::Client::new().post("http://localhost:8000/synthesize").header("Content-Type", "application/json").body(body).send()?.bytes()?; std::fs::write("hello.wav", wav)?; 非同期コードでは reqwest の非同期クライアントを同じように使います。標準の声なら、ファイルの代わりに "voice": "F1" を送ります。同じテキスト、声、seed なら常に同じ音声になるので、繰り返すフレーズのファイルはキャッシュしましょう。大きなリクエストは serde_json で整理できます。

本番運用のコツ

reqwest のクライアントはひとつを使い回し、タイムアウトを設定しましょう。ポート 8000 をそのままインターネットに公開しないでください。SUPERCLONICA_API_KEY を設定して Bearer トークンとして送るか、プライベートネットワーク内に置きます。同時リクエストが多いなら SUPERCLONICA_LANES でモデルのコピーを増やし、自分のハードウェアで計測してください。私たちのテストでは短いフレーズが RTX 5070 Ti で 0.12 秒、CPU 4スレッドで 0.43 秒でした。