M5Stack Core S3などで、音声認識ライブラリESP-SRを使う

tl;dr

  • ESP-SRはESP32でウェイクアップワードと命令認識が使えるEspressif社のライブラリです
  • ESP-SRに"Hi! StackChan"というウェイクアップワードが含まれており、スタックチャン製作に活用できます
  • M5UnifiedでESP-SRが使えるようにライブラリを作りました

すぐに使いたい人はこの記事を読まずに、以下のライブラリのページを見て、導入手順を読んで導入してみてください。

github.com

経緯

過去にスマホから家電を操作できるスマートホームを作っていましたが、お家の中で気軽に使えるAIエージェントが欲しくなりました。 M5Stack公式スタックチャンが発売されるにあたり、スタックチャンをスマートホームAIエージェントにしたら面白くて便利そうと思いました。 そのために、ESP32上で動作するウェイクアップワード技術を調べていたところ、EspressifからESP32向けの音声認識エンジンESP-SRを見つけました。

スタックチャンで利用したM5Stack CoreS3は、ESP32-S3を搭載したコアモジュールです。 Core2からマイクが搭載されるようになりましたが、CoreS3から本体に載るようになり、マイクを利用しやすくなりました。 なお、CoreS3には、CoreS3、CoreS3 SE、CoreS3 Liteの3種類がありますが、どれにもマイクが搭載されています。 私はCoreS3 SEを使いました。

M5Stack CoreS3 SEwww.switch-science.com

ESP-SRとは

ESP-SRとは、Espressif社が提供しているESP32上で動作する音声認識ライブラリです。Espressif社がAIプロダクト開発に便利なように提供してくれているようです。

github.com

ノイズキャンセルなどの機能を持っており、結構しっかりと作られています。

  • エコーキャンセル
  • ノイズキャンセル
  • 音声アクティビティ検出
  • 自動ゲイン制御
  • ウェイクワード検出エンジン
  • 音声コマンド検出エンジン

ウェイクアップワード検出の利用には、任意のウェイクアップワードを認識するわけではなく、モデルが必要です。 リポジトリのREADMEにありますが、「Hi,ESP」など多数のモデルが公開されています。 その中に「Hi, Stack Chan」が含まれています。

スタックチャン製作にはこれを使わない手はないと思い、試してみました。

なお、ESP-SRのウェイクアップワード自体はESP32-S3以外のESP32でも動作しますが、ESP32のArduinoライブラリにESP32-S3、ESP32-P4でのみ有効になるように作られています。私のテストではESP32-S3である、CoreS3、Atom S3R+Atomic Echo Base、Atom EchoS3Rでのみ動作しました。

モデルファイル

ESP-SRでは、srmodels.binというモデルファイルを作成し、それをmodelsパーティションに入れ、それを読み込んで動作します。 モデルファイルは、esp32-arduinoにも含まれていますが、こちらは「Hi,ESP」と英語コマンドのモデルが入っていました。 「Hi,Stack Chan」を動かしたい場合、srmodels.binを作る必要があります。

このファイルを作成する方法は、以下のリポジトリに記載してあります。 こちらを参照してください。

github.com

esp32-arduinoにはESP-SR用のパーティションファイルが作られています。 このパーティションファイルを使うと適用できます。

github.com

パーティションにsrmodels.binを書き込むには以下のように、ファームウェアアップロードに追加でコマンドを実行する必要があります。

esptool.py --chip esp32s3 --port "/dev/cu.usbmodem114401" --baud 1500000 write_flash 0xd10000 "srmodels.bin"

ArduinoのESP-SRライブラリを使おうとしたが、よく分からなかった

esp32-arduinoに付属するESP-SRライブラリを使おうとしました。 このライブラリでは、I2Sを操作する部分もライブラリに含まれていました。

私の場合、I2Sを操作する部分はM5Unifiedの機能を使いたいと思っていました。 それと組み合わせる方法が、私にはできませんでした。

M5Unifiedのマイクから得たバイナリを渡すように変更

esp32-arduinoに含まれるESP-SRライブラリを変更し、ESP-SRライブラリからはI2Sを操作せず、音声データのバイナリだけを渡すようにすれば、I2Sの制御で競合せずに動くのではないかと思いました。

M5UnifiedではM5.Mic.record()でint16_tの配列データの形でデータが手に入ります。

#define AUDIO_SAMPLE_SIZE 256

void loop() {
  M5.update();

  // 音声の取得
  static int16_t audio_buf[AUDIO_SAMPLE_SIZE * 2];
  bool ok = M5.Mic.record(audio_buf, AUDIO_SAMPLE_SIZE, 16000, true);
}

その方法で実装し、試行錯誤したところ、無事動くようになりました。

最後にハマっていたのは、ESP-SR側のモノラル指定の仕方のあたりでした。

英語のコマンドも動きました。

英語のコマンドは以下のように、命令を作っておくと、検出してくれます。

static const sr_cmd_t sr_commands[] = {
    {0, "Turn on the light", "TkN nN jc LiT"},
    {0, "Switch on the light", "SWgp nN jc LiT"},
    {1, "Turn off the light", "TkN eF jc LiT"},
    {1, "Switch off the light", "SWgp eF jc LiT"},
    {1, "Go dark", "Gb DnRK"},
    {2, "Start fan", "STnRT FaN"},
    {3, "Stop fan", "STnP FaN"},
};

配列の3つ目の要素であるphonemeは、以下のpythonスクリプトで生成できるようです。

github.com

ライブラリ化

M5Unifiedで動いた実装を、他でも使えるようにライブラリ化しました。

github.com

このライブラリでは、PlatformIOと、Arduino IDEでの利用方法を載せています。 日本語用のドキュメントも用意したので、使ってみたい方はこちらを参照して使ってみてください。

github.com

なお、PlatformIOを使う場合、PlatformIO公式のESP32 Platform はesp32-arduinoの更新が2系で止まっているため、3系がメンテナンスされているpioarduino/platform-espressif32 を使う必要がありました。設定方法はライブラリのドキュメントに記載しています。

Atom S3R+Atomic Echo Base、Atom EchoS3Rでも動作確認した

M5Stack CoreS3で動作を確認しましたが、同じくPSRAM付きのESP32-S3を搭載したAtom S3R+Atomic Echo Baseの組み合わせと、Atom EchoS3Rでも動作を確認しました。

Atom Echo S3R - スマートスピーカー開発キットwww.switch-science.com

ATOMS3R AI Chatbotキット(8 MB PSRAM)www.switch-science.com

ただし、AtomS3RはFLASHが8MBと、CoreS3の16MBの半分しかありません。 ESP-SR用のパーティションはFLASH 16MB用しか提供されておらず、自作しました。

github.com

イベント会場で使ってみた

第三回スイッチサイエンス大感謝祭というイベントに参加し、その時にESP-SRの機能を付けたスタックチャンを見せていました。 ある程度騒がしい会場でしたが、ウェイクアップワードは動作していました。

ぜひ使ってみてください

ぜひ音声で認識するスタックチャンを作ってみたいならば、便利なので使っていきましょう!

2026年4月に開催される技術書典20では、スタックチャンでスマートホーム音声AIエージェントを作った技術についての解説、製作記となる本を作ろうと思います。現在鋭意製作&執筆中です。

techbookfest.org