NISHIO Hirokazu[Translate]
Andriodデバイスを声で操作する
僕「シンクレット!」 → ピポ! → 僕「これは何」 → (写真撮影)「考え中」 → 「これは〜〜です」というシステムを作っていた。音声トリガーの部分に興味のある人がいたのでそこの解説を書こうかと思ったが、AIに音声トリガー部分だけ切り出したサンプルアプリのrepoを作ってもらうほうがいいなと思ったのでやっておいた


簡単な仕組み
デバイス内でストリーミング音声認識→「シンク レット」「シンク レッド」が出現したら以降の処理をトリガー
VoskはAndroid等でストリーミング認識できる汎用ASR(音声文字起こし)
新しいモデルを学習するのではなくVoskの学習済み日本語モデルをそのまま使い、認識候補をウェイクワード周辺だけに絞って使っている
ウェイクワード専用エンジンPicovoice Porcupineを使わなかったのは、これが7日間の無償試用以降は営業に問い合わせろとか書いてあってめんどくさかったから
ストリーミング認識はウェイクワード専用エンジンに比べるとCPU消費や遅延の点で不利ではある
CPU利用率は6.9%だった
Picovoice Porcupineは音声処理単位が32msでVoskは200msなのでまあ遅延はある
これくらいのスピードで反応する
僕の目的には問題ないかな〜という気持ち

AndroidデバイスとしてはTHINKLETを使った。
首掛け型で3264x2448の高解像度の写真が撮れる。
ボタンもあるのでそれでトリガーするのが確実だが僕はTHINKLETで読書支援の「書籍を両手で持って読んでる時に使いたい」というニーズのために音声で操作したかった


2026-10-05 追記Codex
サンプルの範囲
「シンクレット」を検出→マイクを止める→「ピポ」を鳴らす→待受へ戻る、という部分だけを切り出してある。カメラ・質問録音・LLM回答は含まない。
音声の保存も外部送信もしない。アプリにINTERNET権限がなく、モデルを同梱したAPKなら待受はオフラインで動く。
Android 8.1以降のマイク付き端末が対象。THINKLET専用ではない。導入方法とAPKはサンプルのREADMEから辿れる。
このサンプルはアプリを前面で動かすもの。画面消灯後やアプリを閉じた後も待ち続けるOS常駐の仕組みは含んでいない。
反応を早くし、二重起動を避ける工夫
認識途中のpartialも調べ、一致すれば無音で発話が区切られるのを待たずに反応する。
同じ発話の途中結果・確定結果が何度来ても、検出通知は1回だけにする。確認音の再生中はマイクを解放し、再生終了から250ms待って待受へ戻る。確認音の回り込みや自己再トリガを避けるため。
別の起動語に変えるなら、Voskに渡す認識候補と、認識結果を受け入れる表記のリストの両方を変更する。
数値についての補足
CPU 6.9%は、カメラも待機している元の読書アプリ全体を一時点で測った値。Vosk単体や、この切り出したサンプルの平均値ではない。
200msはこの実装がVoskに音声を渡す単位、32msはPorcupineのフレーム長。「起動語を言い終えてからピポが鳴るまで」の実測時間ではないので、この数字の差をそのまま応答の遅延差とは言えない。
Porcupineとの同条件での性能比較、長時間の誤検出率、電池持続時間の比較はまだしていない。CPU使用率だけから電池が何時間持つかは分からない。
"Engineer's way of creating knowledge" the English version of my book is now available on [Engineer's way of creating knowledge]

(C)NISHIO Hirokazu / Converted from [Scrapbox] at [Edit]