本リポジトリの現行実装を素早く把握するためのメモです。詳細仕様は docs/websocket_protocols_ja.md と docs/rest_api_ja.md を参照してください。
- CoreS3 側は
firmware/、Python サーバー側はstackchan_server/。 - 音声 uplink は
AudioPcm、音声 downlink はAudioWav(実体は raw PCM)。 - サーバーは FastAPI を公開し、WebSocket と REST API の両方を持つ。
- サーボ制御が追加済みで、WebSocket プロトコルには
ServoCmd/ServoDoneEvtがある。
- ファームウェア状態:
Idle,Listening,Thinking,Speaking,Disconnected - サーバーから指示できるのは
StateCmdの0..3(Idle〜Speaking) Disconnectedはファームウェア内部状態で、WebSocket 切断時に入るWakeWordEvtを受けるか、REST API の wakeword 擬似発火で talk session が始まる
- 共通ヘッダ:
WsHeader(<B B B H H>, packed, little-endian) kind1=AudioPcm2=AudioWav3=StateCmd4=WakeWordEvt5=StateEvt6=SpeakDoneEvt7=ServoCmd8=ServoDoneEvt
messageType1=START2=DATA3=END
AudioPcm- PCM16LE / 16kHz / 1ch
START -> DATA* -> ENDDATAは 2000 samples(4000 bytes, 約 125ms)ごと- 無音 3 秒で自動終了
AudioWav- 名前に反して WAV コンテナではなく PCM ストリーム
STARTpayload は<uint32 sample_rate><uint16 channels>DATAchunk は既定 4096 bytes- 約 2 秒セグメントで送信し、2 本目は約 1 秒後に先行開始
ServoCmd- payload:
<uint8 count><commands...> - op:
0=Sleep,1=MoveX,2=MoveY - 新規コマンド受信時は実行中シーケンスを置き換える
- payload:
GET /healthWS /ws/stackchanGET /v1/stackchanGET /v1/stackchan/{stackchan_ip}POST /v1/stackchan/{stackchan_ip}/wakewordPOST /v1/stackchan/{stackchan_ip}/speak
- 接続ごとに
WsProxyを作成 websocket.client.hostを StackChan の識別子として使う- 同一 IP の再接続時は既存接続を置き換える
listen()はListening指示後、音声 uplink 完了を待つspeak()は TTS downlink 送信後、SpeakDoneEvtを待つmove_servo()/wait_servo_complete()を公開
- 既定 STT:
GoogleCloudSpeechToText(ストリーミング認識) - 既定 TTS:
VoiceVoxSpeechSynthesizer example_apps/echo.py/echo_with_move.pyはSTACKCHAN_WHISPER_MODELがあるとwhisper.cppを使うDEBUG_RECODING=1のときのみ録音 WAV と TTS WAV をstackchan_server/recordings/に保存する- 実装上この変数名は typo のまま
src/main.cpp- Wi-Fi 接続後、
/ws/stackchanに接続 AudioWav,StateCmd,ServoCmdを受信処理- 通信が 60 秒止まると
Thinking/SpeakingからIdleに戻す
- Wi-Fi 接続後、
src/listening.cpp- マイク読み取り 256 サンプル単位
- 2 秒リングバッファ
- 無音 3 秒で停止
src/speaking.cpp- 3 本バッファで TTS セグメント受信
END後にM5.Speaker.playRaw()で再生- 再生完了時に
SpeakDoneEvt
src/servo.cppServoCmdを非同期実行MoveX,MoveY,Sleepを順次処理- 完了時に
ServoDoneEvt
src/display.cppIdle=濃いグレー,Listening=青,Thinking=オレンジ,Speaking=緑,Disconnected=赤
example_apps/echo.py: 音声をそのまま復唱example_apps/echo_with_move.py: 復唱 + サーボ動作example_apps/gemini.py: Gemini 応答を発話
- VOICEVOX を起動
- FastAPI サーバーを
example_apps.*:app.fastapiで起動 - CoreS3 が WebSocket 接続
- ウェイクワードまたは REST API の wakeword 呼び出しで対話開始
- 必要に応じて発話・サーボ制御を返送