Cactus Computeが公開したWhistleは、音声を文字起こしするための小型モデルだ。面白いのは、単に「軽い」だけではなく、同社の別モデルNeedleと同じCPU向けエンジンで動き、1つのバイナリから文字起こしとtool callの両方につなげられる点にある。スマホ、ウェアラブル、ロボット、スマートホーム、車載機器、マイコンまで想定していて、しかも音声データは端末の外に出ない。大きなクラウドに投げず、端末の中で完結する音声AIを本気でやろうとしている記事だと読んだ。
元記事によると、Whistleは「speech recognition model for mobiles, wearables, robots, smart home, automotive and microcontrollers」として発表された。モデル本体は16.9 MBの1ファイルで、CPU上で動き、依存関係はない。しかもNeedleと同じC++エンジン、同じcontainer、同じquantisationで読み込める。つまりWhistleは、別物の音声認識ソフトを新たに足したというより、同じ実行基盤の上に音声認識を載せた形に近い。
対応言語は英語、ドイツ語、フランス語、スペイン語、イタリア語、オランダ語、ポーランド語の7つ。16 kHz mono音声を最大30秒まで一度に扱い、言語は指定しなければ自動判定する。機能は3つで、まず通常のtranscription。次にword timestampsで、各単語の開始・終了時刻と確率を返す。さらにspeech embeddingとして、文字起こしをせずにエンコーダ出力を取り出せる。
仕組みの説明もかなり細かい。入力は16 kHz mono音声で、25 ms window、10 ms hop、80 log-mel binsに変換される。30秒は3,000 framesになり、そこから3回の畳み込みで375 framesまで圧縮される。その後に8層のSimple Attention encoderが走り、decoderは8層のLaddered Simple Attention blockを使う。Whistle特有の追加として、各decoder layerがencoderをgated cross attentionで参照する。ビームサーチは5本で、keyword biasingも使える。さらに silence を検出すると、しきい値以下では空のtranscriptと空のlanguageを返し、beam search自体に入らない。
性能面では、Apple M4 Pro CPU上で10秒音声を使って比較している。サイズはWhistleが16.9 MB、Whisper baseが145.3 MB、Moonshine tiny v2が41.9 MB。first tokenまでの時間はWhistleが11.1 ms、Whisper baseが73.2 ms、Moonshine tiny v2が22.8 ms。decode tokens per secondはWhistleが1,319/sで、Whisper baseの266/s、Moonshine tiny v2の262/sを大きく上回った。WERでは、WhistleがLibriSpeech test-clean/test-other、SPGISpeech、Earnings-22、FLEURS平均で優位だった一方、Whisper baseはTED-LIUM、AMI、MLS平均で上回っていた。なおWhistle側は86,174 utterancesで測定し、訓練・検証データにテスト音声が混ざっていないことも確認したとしている。
使い方も明快だ。pip install cactus-needle のあと、needle.transcribe("clip.wav") を呼べば文字起こしが返る。16 kHz WAVやraw samplesなら追加の依存は不要で、マイク入力や別サンプルレートには [mic] extra を使う。word_timestamps=True で単語ごとの時刻を返し、keywords=["Siobhan", "Krzysztof"] のように語を与えると、その語の出現を拾いやすくする。language="de" で言語固定もできる。さらにWhistleは単体モデルとしてだけでなく、Needleと一緒に読み込んで、音声からそのままtool callにつなぐ使い方も示されていた。
私がまず強く感じたのは、Whistleの価値が「軽い音声認識」ではなく、「同じ基盤に載る軽い音声認識」まで含めて設計されているところだ。端末上で動くAIは増えているが、実際には画像はこのライブラリ、音声は別のライブラリ、LLMはまた別、となりがちで、結局は統合作業が重い。WhistleはNeedleと同じエンジンで動き、同じbinaryで読めることを前面に出している。ここは派手さより実務的な強さがあると思う。開発者から見れば、モデルの性能だけでなく、配布サイズ、ロード方法、実行環境の一貫性まで揃っているからだ。
しかも、Whistleは「文字起こしの結果を表示する」だけで終わらない。元記事の最後では、音声を入力したまま needle_complete でtool callを返す例まで出している。これが示すのは、音声認識を独立した機能として扱うより、自然言語入力の1つとしてアプリの制御に接続する発想だ。スマートホームで「turn off the kitchen lights」を聞き取って、そのまま照明制御に回す。こうした使い方では、認識精度そのものと同じくらい、レイテンシと実装の単純さが効いてくる。Whistleはその弱点をかなり正面から潰しにきているように見える。
一方で、Whistleは万能ではない。対応言語は7つで、しかも最大30秒の単発入力だ。会議全体を丸ごと扱うような用途ではないし、長時間の会話を切れ目なく書き起こすタイプの設計でもない。ここはかなり割り切っている。だが、その割り切りが悪いとは思わない。むしろ、端末内で低遅延に動かすなら、無制限の入力長や多数言語を追うより、よく使う場面に集中したほうが筋がいい。
ベンチマークの読み方にも注意がいる。Whistleは確かにWhisper baseより小さく、first tokenも速い。ただしWhisper baseは145.3 MBとかなり大きいので、サイズ差がそのまま速度差に繋がる面はあるだろう。さらにWhisper、Moonshine、Whistleは評価条件や公開されているベンチマークが完全には揃っていない。元記事自身も、WhisperはSPGISpeechやEarnings-22、AMI cleanedを出していないし、AMIのsubsetも違うと注記している。つまり「完全勝利」と読むより、「軽量モデルとして十分に戦える位置まで来た」と見るのが正確だと思う。
Whistleのもう1つの意味は、音声UIを“別アプリ”から“常駐部品”へ変える可能性だと思う。端末での音声認識は、これまでクラウド依存か、あるいは重い専用機能として実装されることが多かった。だがWhistleのように16.9 MBで、CPUで、しかも同じエンジンから文章モデルと並べて使えるなら、音声は入力手段の一部としてもっと自然に組み込める。たとえば、ロボットが近くの人の発話をすぐテキスト化し、そのまま命令解析まで進む。ウェアラブルが短い音声メモを即座に文字化する。そういう場面では、クラウド往復を消せる意味が大きい。
ただし、ここで重要なのは「端末内で動く」こと自体がゴールではない点だ。端末内で動いても、運用が複雑なら普及しない。Whistleが同じC++ engine、同じcontainer、同じquantisationに寄せているのは、その複雑さを増やさないためだろう。私はこの設計をかなり評価している。派手なデモより、配布と実装の面倒を減らすことのほうが、実際には製品化を左右するからだ。
Whistleは、単に「Whisperより小さい」や「速い」といった比較で片づけるには惜しい。中身を見ると、音声認識を独立した巨大機能としてではなく、テキスト生成やtool callと同じ実行系の部品として扱おうとしている。ここにこの発表の本質があると思う。将来の端末AIは、1つの賢いモデルが全部をやるというより、軽いモデルを同じ土台に積み、用途ごとに切り替えて使う形に寄っていくのではないか。Whistleはその流れをかなり具体的に示した例だ。