11のAIプロバイダーにルーティングする「ソブリン音声レイヤー」を自作—アーキテクチャ解説

Dev.to / 2026/4/30

💬 オピニオンDeveloper Stack & InfrastructureSignals & Early TrendsTools & Practical UsageModels & Research

要点

  • 著者は、BRAGIという「ソブリンな音声レイヤー」を紹介し、マイク入力→ウェイクワード検出→ローカルSTT→クラウド/ローカルを含む複数のAIプロバイダーへのルーティングを行う仕組みを説明しています。
  • 音声はマシン外に出さず、送られるのは選択したプロバイダーに対する文字起こしテキストのみであるため、特定のアシスタントへの固定化を避けつつ切り替えやすくなります。
  • BRAGIでは、CPUで動くopenwakewordによるウェイク検出、低遅延を狙ったfaster-whisper(CUDA上のmedium)によるバイリンガルSTT、TTSはeSpeakまたはOpenAI Nova(BYOK)を用いる構成になっています。
  • v0.2を出荷する中で得た実務的な学びとして、openwakewordの前処理バージョン違いによるウェイクワードモデル互換性問題や、Whisperをリクエストごとに起動せず起動時にウォームアップして遅延を抑える必要性が挙げられます。
  • さらに難しかったのがプロバイダールータで、各プロバイダーのSDK・ストリーミング形式・認証方式の違いを1つのインターフェースに抽象化し、準備完了(is_ready)も扱えるようにする点が強調されています。

Claudeデスクトップ、ChatGPTボイス、Gemini、そして数多くのOllamaフロントエンドを行ったり来たりして2年。ウェイクワードの“よじれ”に疲れました。どのアシスタントも、あなたがずっとそのチームを選び続ける前提で作られています。

そこでBRAGIを作りました。ローカルで動くボイスレイヤーで、ローカルで聞き取り、指定したどのAIにもルーティングします。同じマシン上で動いているAIも含みます。

この記事は販売宣伝ではなく、アーキテクチャの話です。同じようなものを作ろうと考えているなら、v0.2を出荷して学んだことを共有します。

The pipeline

マイク入力

openwakeword(ローカル)—「Hey Jarvis」

faster-whisper medium(ローカル、GPUは任意)

プロバイダー・ルーター(設定UIで宛先を選択)

[クラウド:Claude / OpenAI / Gemini / Grok / Groq / Together / HuggingFace]
[ローカル:Ollama / LM Studio / FREYA / Echo]

TTS(eSpeak free、OpenAI Nova BYOK)

スピーカー出力
音声は一切マシン外に出ません。どのクラウドを選んでいる(または選んでいない)かに関係なく、送られるのは文字起こしテキストのみです。

Wake word

主権型(ソブリン)プロダクトならopenwakewordが正解です。Picovoiceの方が品質は良いですが、有料の商用ライセンスに縛られます。openwakewordはApache 2.0で、CPU上で動きます。

落とし穴:独自のカスタムモデルを学習するには、対象としているどの前処理(preprocessor)バージョンに対しても、特徴次元(feature dimensions)を完全に一致させる必要があります。openwakewordが32×147を期待しているのに、96×103の特徴を持つモデルに手を入れてしまい、半日を無駄にしました。v0.2には標準の「Hey Jarvis」モデルを同梱し、対応するハードウェアを持つユーザー向けにカスタムの「Hey BRAGI」モデルも含めています。

STT

CUDAでのfaster-whisper mediumがベストです。Tinyは実会話には不正確すぎますし、largeは短いボイスコマンドには過剰です。mediumはミッドレンジGPUで約1秒のレイテンシを出し、バイリンガル入力にも最初から対応しています。

重要な点:Whisperは起動時に1回だけインスタンス化し、リクエストごとに作らないこと。最初の推論呼び出しはCUDAをウォームアップするために5〜10秒かかります。毎回のウェイクごとにそれを許容するユーザーはいません。

The router

ここが一番大変でした。各プロバイダーには別々のSDK、別々のストリーミング形式、別々の認証パターンがあります。ルーターはそれらを1つのインターフェースに抽象化します:

class Provider(Protocol):
    def name(self) -> str: ...
    def is_ready(self) -> bool: ...
    async def respond(self, prompt: str, history: list[Message]) -> AsyncIterator[str]: ...

各プロバイダー実装は、それぞれのSDKのクセを自分で処理します。ルーターはユーザー設定、またはボイスコマンド(「BRAGI、Claudeに切り替えて」)に基づいて1つを選び、respond()を呼ぶだけです。

ローカルモデルについては、Ollama(HTTP API)とLM Studio(OpenAI互換のHTTP API)の両方に対応しています。どちらもユーザーのマシン上で動きます。どちらもルーターから見れば同じに見えます。

TTS

eSpeakは無料でオフライン対応、100以上の言語があるため、インストーラーに同梱されています。音はロボットっぽいです。でもそれで問題ありません。プレミアムな音声を望む人はOpenAIのAPIキーを貼り付けてNovaを使えます。

オフラインTTSの品質を上げるためにKokoroも試しました。開発ではうまく動きました。ところが本番ビルドでは、HuggingFaceのデフォルト音声ファイルで404を踏み続けました。デフォルトはeSpeakのまま、Kokoroはベストエフォートで提供しました。

The settings UI

ローカルWeb UI:http://127.0.0.1:7777。プロバイダーを設定し、APIキーを貼り付け、ボイスを選び、ライセンスを管理します。このページはユーザーのマシン上に存在します。アカウントもログインも、クラウドのダッシュボードもありません。

APIキーはローカルのボールト(保管庫)に保存します。APIキーは一度もマシンの外に出ません。このプロダクトは“主権”です。つまり、あらゆるレイヤーでそうでなければならない。

Stack

  • Python 3.11
  • ウェイク検出用のopenwakeword
  • STT用のfaster-whisper
  • TTS用のeSpeak / OpenAI Nova
  • ローカル設定サーバ用のFastAPI
  • 日常利用のためのトレイモードのpythonw.exe
  • 同梱(バンドル)用のPyInstaller
  • Windowsインストーラー用のNSIS
  • 約169MBのインストーラー、Win10/11

What I'd do differently

  1. カスタムのウェイクワード学習は、ドキュメントが言うよりずっと難しい。 openwakewordの前処理はバージョン管理されていて、特徴次元は完全に一致する必要があります。自分で学習したいユーザー向けに、これをドキュメント化します。

  2. PyInstaller + 4GB CUDA torchのビルドは、NSISの2GB単一ファイル上限を超えてしまう。 torchとKokoroは、同梱ではなく初回起動時のダウンロードに移す必要がありました。

  3. 埋め込みPythonのpython311._pthデフォルト値を信用しないこと。 %APPDATA%\Roaming\Pythonからのユーザーサイト汚染により、インストールが静かに壊れます。必ず-s -Eフラグ付きで起動してください。

What's next

v0.3ではおそらく、より良いKokoroのフォールバック、カスタムウェイクワード学習UI、マルチルームの同時実行性を追加します。アーキテクチャはそれに対応しています。ですがまずv0.2を出荷し、ユーザーが実際に何を求めているのかを確認する必要があります。

見てみたいなら:clintwave84.gumroad.com/l/leetkd

同じようなものを作ったなら、感想を比較しませんか。コメントをどうぞ。特に、クラウド+ローカルにまたがるプロバイダー抽象化を他の人がどう扱っているのかが気になります。

— アイダホの一人の男によって制作。Snake River AI。