話題
Cactus Compute、16.9MBの軽量音声認識モデル「Whistle」を公開
デイリートピックス編集部公開: 2026/10/09約7分で読めます3 views
Cactus Computeは2026年10月2日、音声認識モデル「Whistle」を公開した。1ファイル16.9MBでCPUのみで動作し、外部の依存ライブラリを持たない。Cactus Computeはモバイル、ウェアラブル、ロボット、スマートホーム、自動車、マイコンでの利用を想定すると説明する。
対応言語は英語、ドイツ語、フランス語、スペイン語、イタリア語、オランダ語、ポーランド語の7言語で、利用者が言語を指定しない場合はモデルが自動で検出する。日本語は7言語に含まれない。16kHzのモノラル音声を最大30秒まで1回で文字起こしし、単語ごとの時刻情報と音声埋め込みを端末内で処理する。同社の言語モデル「Needle」と組み合わせると、音声の文字起こしからツール呼び出しまでを同じエンジンで一括処理できる。
16.9MBでCPUのみ動作する仕様と7言語対応
Whistleは1ファイル16.9MBのモデルで、CPUで動作する。Cactus Computeは同じC++エンジン、同じ `.cact` コンテナ、同じ量子化方式でNeedleと読み替えられると説明する。GPUを必要とせず、依存ライブラリを追加しない構成だ。
音声の入力条件は16kHzのモノラルで、1回あたり最大30秒、最大48万サンプルに対応する。フロントエンドは25ミリ秒窓、10ミリ秒ホップで80次元の対数メル特徴量を作り、250から3500ヘルツに帯域制限してチャンネルごとに正規化する。30秒の音声は3000枠になり、128チャンネル、カーネル9の畳み込みで3回間引いて375枠、80ミリ秒あたり1枠の粒度で後段を処理する。エンコーダは8ブロックで全層を実行し、利用者が深さを選んでも間引かない。
言語の扱いは7言語の自動検出が基本で、利用者が `language="de"` のように指定すると固定できる。検出した言語は専用トークンとして出力される。入力の音量範囲を測って無音と判断した場合は、空の文字起こしと空の言語を返してビーム探索に入らない。作り話の文を埋めない設計だ。
文字起こし・単語時刻・埋め込みの3機能とキーワード指定
1つ目の機能は文字起こしで、最大30秒の音声を1回でテキスト化する。2つ目は単語タイムスタンプで、単語ごとに開始時刻、終了時刻、確率を返す。デコーダ自身の注意情報から位置を合わせるため、アプリ側で強調表示や頭出し、区間切り出しに使える。3つ目は音声埋め込みで、エンコーダ出力を80ミリ秒枠ごとに1行返す。テキスト化せずに照合や検索へ回せる。
人名や地名、製品語など利用場面で重要な語は、キーワードとして渡すと探索中に優先される。Aho-Corasick法のオートマトンで候補語の進行を追い、対数確率を持ち上げる仕組みだ。語彙はテキスト断片8192個に言語トークン7個を加えた構成で、出力上限は320トークン、ビーム幅5本を長さ正規化した対数確率で評価する。
デコーダは幅512の層を8層備え、8クエリ対2キー値のグループ化クエリ注意、48次元のクエリとキー、64次元の値、因果性のある3タップ畳み込み、第3層と第7層のエングラム参照という構成だ。各デコーダ層はゲート付き交差注意でエンコーダを読み、クリップ到着時にキーと値を1回射影して保持する。5本のビームは音声全体を5回なめるのではなく、短い transcript キャッシュを5本持つだけで済む。デコーダは2層以降の各深さが単独のモデルとして学習済みで、読み込み時に `--audio-depth` で切り替えられる。
Needleと同じエンジンで音声から操作まで一括処理
WhistleはNeedleのコードを共有するブロックで動き、別実装の複製ではない。`needle_load` は `.cact` ファイルの中身を見てモデルを読み分けるため、同じバイナリが音声単独、文章単独、音声と文章の併用の3通りを処理できる。併用時はエンジンがクリップを文字起こしし、その文をツール定義に当てはめて、1つのJSONオブジェクトで呼び出し内容と音声項目を返す。音声項目には `audio_` の接頭辞が付く。呼び出し側が文字起こし文を受け渡す必要はない。
Pythonでの利用は `pip install cactus-needle` の後に `needle.transcribe("clip.wav")` を呼ぶ形だ。16kHzのWAVや生サンプルは基本導入だけで処理でき、他のサンプルレートやマイク取得には `[mic]` 追加で `soxr` と `sounddevice` を使う。戻り値はテキスト、言語、最初のトークンまでのミリ秒、その後の1秒あたりトークン数で、`word_timestamps=True` で単語時刻、`keywords=[...]` で優先語、`language="de"` で言語固定を指定できる。`needle whistle playground` は端末のマイクから文字起こしし、`needle whistle compare` は同じクリップをWhistle、Whisper、Moonshineで並べて時刻とともに比べる。
C言語の窓口は `needle_load`、`needle_transcribe`、`needle_embed` の3関数に、`needle_complete` を加えた構成だ。`needle_complete` はクリップを直接受けて文字起こしまで済ませる。エンジンは環境変数を読まず、同じblobの同じ実行は同じ結果になる。動作の切り替えは規定値か明示のフラグで行う。
Whisper・Moonshineとの比較条件と精度の留保
比較対象はWhisper baseとMoonshine tiny v2で、測定条件はApple M4 Pro CPU上の10秒音声、各モデルの公式ランタイムと既定値だ。WhistleはC++エンジンでビーム5本、`openai-whisper` と非ストリーミングの `moonshine-voice` が相手になる。最初のトークンまでの時間は音声入力から最初のトークンまで、デコード速度はその後をトークン数割る壁時間で求め、エンコーダを二重に数えない。
ファイルサイズはWhistleが16.9MB、Moonshine tiny v2が41.9MB、Whisper baseが145.3MBだ。最初のトークンまでの時間はWhistleが11.1ミリ秒、Moonshine tiny v2が22.8ミリ秒、Whisper baseが73.2ミリ秒、デコード速度はWhistleが1秒あたり1319トークン、Whisper baseが266トークン、Moonshine tiny v2が262トークンだ。Whisperは入力を30秒にそろえるため、最初のトークンまでの時間はクリップ長によらず一定になる。Whistleはクリップ長に追随し、5秒で5.9ミリ秒、10秒で11.1ミリ秒、30秒で36.3ミリ秒と説明される。
精度の採点はWhisper正規化で行い、Whistleは8万6174発話で実測し、WhisperとMoonshineは作者の公開値を多言語チェックポイントで比べる。テスト音声が学習や検証に混ざっていないことは、音声チェックサムと話者IDの照合で確認したと説明される。LibriSpeechのtest-cleanとtest-other、SPGISpeech、Earnings-22、FLEURS平均ではWhistleが先行し、TED-LIUM、AMI、MLS平均ではWhisper baseが先行する。棒がない項目は作者が未公開の指標で、Moonshineは英語のみ、WhisperはSPGISpeech、Earnings-22、AMI cleanedの報告がない。WhisperのAMI値はAMI-IHMで、他2者のAMI cleanedとは部分集合が異なる。TED-LIUMは採点手順の除外区間を除き、FLEURSとMLSはWhistleの7言語、MLSは英語を除く6言語で平均化する。
導入手順と配布の経路
配布はmacOS、Linux、Android、iOS、watchOS、ARM版Windows、RISC-V、MIPS、ブラウザ、WASI部品を含む17ターゲットのビルド済みで、各フォルダが `needle` バイナリと `libneedle.a`、`needle.h` を持つ。重みはHugging Faceの `Cactus-Compute/whistle`、エンジンとプラットフォーム別フォルダは `Cactus-Compute/needle3`、ソースはGitHubの `cactus-compute/needle` で入手できる。Hugging Faceの表示はApache-2.0で、引用用のBibTeXは `whistle_2026` として著者8名とCactus Compute、2026年が示される。