結論から
マイコン 1 個で日本語のニューラル音声合成が動きます。 クラウドも、パソコン も、API キーも要りません。
しかも、ここに出てくるものは全部オープンソースです。
sanoTTS-jp という 559 K パラメータの蒸留 TTS モデルを、M5Stack CoreS3 (ESP32-S3) のスタックチャン ファームウェアに組み込んで、喋らせて口も動かしてみました。
関連リポジトリ
| リポジトリ | 内容 |
|---|---|
| Ampixa/sanoTTS | SanoTTS のオリジナル実装。日本語には対応していません |
| ayutaz/sanoTTS-jp | SanoTTS の論文から 0 から実装されたもの。MIT ライセンス。TTS の重みはつくよみちゃんコーパス |
| nnn112358/SanoTTS-jp-M5StackCoreS3 | M5Stack CoreS3 (ESP32-S3)で動く sanoTTS-jp |
| nnn112358/StackChan-IDF-for-SanoTTS-jp | スタックチャンで動く sanoTTS-jp。 ← この記事で作ったもの |
| nnn112358/SanoTTS-jp-Tab5 | M5Stack Tab5(ESP32-P4)で動く sanoTTS-jp。 |
sanoTTS-jp のここがすごい
1. 重みが 559 KB しかない
sanoTTS-jp は arXiv:2608.21378 の日本語版にあたる蒸留モデルで、int8 量子化した重みが 559 キロバイト。これが全部です。
「マイコンで TTS」のオープンソースプロジェクトというと、これまでは
- 波形をつなぐ (単位選択・PSOLA) → 声は自然だが音声 DB が数百 MB
- フォルマント合成 → 軽いがロボット声
という選択肢でした。ニューラル TTS は「ラズパイから上」の世界だったのが、マイコンの土俵に降りてきたというのが一番の驚きです。
2. 音声が実時間より速く出る
上流の実測では、CoreS3 で定常 xRT 0.446 (1 秒の音声を 0.45 秒で合成) です。つまり合成しながら再生して間に合う!
速さの中身は、
- 重みを int8、活性化も int8 にした W8A8
- ESP32-S3 の整数 SIMD (PIE、
ee.vmulas.s8.accxなど) で内積を回す - ストリーミング推論 (発話全体をバッファせず、チャンクごとに出す)
という仕組みによるものです。
3. 漢字も端末内で読める
さらに、Open JTalk + 枝刈り辞書 (13.7 MB) を端末に載せる経路も用意されています。
辞書を ESP32 に焼けば、漢字かな交じり文をそのまま渡せます。
I (10983) jtts-sano: kanji g2p: 63 B → 11 morphemes → 86 ids (63 ms)
I (43952) saan_dict: 辞書 OK: 見出し語 355768 / エントリ 438750 / 行列 1377x1377
形態素解析 + アクセント付けが 63 ms。辞書は RAM に読まず flash から直接引きます。
スタックチャンに載せる
ここからは実装の話です。ベースは stackchan-idf
。既に formant / 単位連結 / HMM の 3 つの音声合成
エンジンを持っているので、4 つ目のエンジンとして sanoTTS を足す形にしました。
読み (かな or 漢字かな交じり)
→ G2P (かな中間表現 / Open JTalk + 辞書)
→ sanoTTS 推論 (W8A8 + PIE、arena 176 KB)
→ 22.05 kHz PCM をチャンクごとに再生
→ 包絡からアバターの口を駆動
使う側は HTTP に投げるだけです。
curl -X POST --data-binary "今日は良い天気ですね。" http://stackchan.local/api/jtts-say
AquesTalk ESP32 との違いは?
M5Stackで日本語を喋らせるなら、これまでは AquesTalk ESP32 がほぼ唯一の選択肢でした。私も長く使ってきました。違いは3つです。
1. 合成方式
AquesTalk は規則合成、sanoTTS-jp はニューラルTTS です。出力は 8 kHz と 22.05 kHz。電話の声と、録音した声くらいの差があります。sanoTTS-jpの声種は学習することでいくらでも増やせます。
2. ライセンス
AquesTalk はプロプライエタリです。評価版は「な行・ま行が『ヌ』になる」制限付きで、実用にはモジュールごとに使用ライセンスが要ります。販売するなら頒布ライセンスも別途必要です。ライブラリをリポジトリに置いて配ることはできません。
sanoTTS-jp はコードが MIT、重みも再配布できます(重みには帰属表示の義務と生成音声の用途制限があります。詳しくは後述)。だからファームウェアを配布もできます。
3. 新しいチップへの対応
AquesTalk ESP32 はバイナリ配布なので、対応チップはベンダーが提供するビルド次第です。ESP32-S3 までは用意されていますが、ESP32-P4 向けのバイナリはありません。自分でビルドし直すこともできないので、新しいチップが出ても待つしかありません。
sanoTTS-jp はソースが公開されているので、ESP-IDF が対応しているチップならビルドできます。ESP32-P4 でも動きますし、今後さらに新しいチップが出ても同じことです。ESP32はESP32P4XやESP32S31などなど、今後も新しいチップが増えてきているので、ここは実用上けっこう効いてきます。
| 項目 | sanoTTS-jp | AquesTalk ESP32 |
|---|---|---|
| ESP32-S3 | ○ | ○ |
| ESP32-P4 | ○ | ☓ |
| ライセンス | オープンソース | プロプライエタリ |
| 方式 | ニューラルTTS | 規則合成 |
| 声種 | ∞(無限、重みはpiper-plusの蒸留学習) | 女声1種(pico F4) |
| サイズ | 重み 559 KB | ROM 200 KB / RAM 21 KB |
| 漢字辞書 | 13.7 MB (任意) | 7 MB / small 2 MB |
まとめ
- sanoTTS-jp は、マイコン単体で日本語ニューラル TTS が動くところまで来ている
「ネットが無くても喋るスタックチャン」がやってきました。試したい方はどうぞ: https://github.com/nnn112358/StackChan-IDF-for-SanoTTS-jp
参考
- ayutaz/sanoTTS-jp — モデルと推論コア
- nnn112358/SanoTTS-jp-M5StackCoreS3 — CoreS3 単体で動かす移植
- ciniml/stackchan-idf — ベースにしたスタックチャン ファーム