Alias Archiveアーカイブ更新中
アーカイブ更新中

ブラウザを表示装置として扱う:ホスト非依存の舞台と三つの基盤戦

デジタル伴侶制作記04 / SERIES

一つのAI伴侶をブラウザ、独立ウィンドウ、デスクトップ壁紙として同時に存在させる構成。ロジックをサーバーへ集め、ページを表示装置へ戻す。

記録日
所属分野
その他
言語版
JA / 閲覧版

本稿は「デジタル伴侶制作記」の第4篇である。彼女には身体が必要だった。最初はブラウザのタブ、次は枠のない独立ウィンドウ、最後はデスクトップ壁紙そのもの。三形態を別々に実装すれば保守は破綻する。本稿は三者を共存させた設計判断と、そのために戦った三つの基盤戦を記録する。

原則:ページは表示装置であり、アプリではない

ブラウザ、枠なしウィンドウ、デスクトップ壁紙が同じページを読み、一つのローカルサーバーへ接続する構成図。サーバーには頭脳、ローカル音声認識、システム音声出力、弁、イベント配信があり、マクロパッドはHTTPで呼び出す
ロジックはすべてサーバーに置く。ページを一度変えれば三形態が同時に変わる。

規則は一つだけである。すべての状態、判断、副作用を持つ動作はローカルサーバーで起こる。ページはWebSocketでイベントを受け、HTTPで要求を送り、真実を保持しない。これにより次の性質を得た。

  • 三つのホストは同じURLを読み、互いの予備になる。
  • ページをすべて閉じても、音声とホットキーを含むシステムは動き続ける。
  • ホスト固有の欠陥はサーバー側で迂回できる。これは以下三戦の共通テーマである。

第1戦:耳をサーバーへ移す

音声認識は当初ブラウザのWeb Speech APIを使った。壁紙では解けない問題が起きた。マイク権限の吹き出しはネイティブUIだが、壁紙ソフトはマウスをページ内容へしか転送しない。吹き出しは永遠に押せず、WebView2の音声バックエンドも不安定だった。

解法は根本からページを外すことだった。マイクは機械に属し、ページには属さない。 サーバーが直接録音し、ローカルwhisperで転写する。16GB GPUでは45秒の音声を約0.7秒で処理し、文字は入力欄と同じ経路へ送る。ページ権限は不要になり、三ホストが同等に音声入力を得た。プライベート文脈の音声は機械の外へ出ない。

二つの補助設計も重要である。

自己音声の抑制。 常時認識中は、彼女自身の声がスピーカーからマイクへ入り、自分と会話し始める。再生側が発話時間帯を報告し、サーバーはBooleanではなく絶対期限として保持する。報告元が途中で死んでも期限は自然に切れるが、フラグは永久に残り得る。期限内に始まった認識区間を捨てる。押して話す操作は抑制しない。キーを押していること自体が割り込みの意図だからである。

CUDA不足は推論時まで見えない。 モデル構築の成功は動作を保証しない。cuBLASがなければ構築は通り、最初の転写で落ちる。読み込み後に0.5秒の無音を転写して実動作を確かめ、失敗時はCPUへ降格する。動的ライブラリの通常検索はPATHを参照するため、Pythonのadd_dll_directoryだけでは足りない。

第2戦:喉をサーバーへ移す

きっかけは、別ウィンドウへ焦点が移ると壁紙ソフトが壁紙プロセスを停止することだった。話の途中で彼女全体が止まる。ホスト側の停止設定と何度か戦った後、原則へ戻った。音は機械に属し、ページには属さない。

サーバーが音声を復号し、システム音声ストリームへ直接書く。効果は予想より多かった。ホスト停止で発話が途切れない。複数ホストを開いても音源が一つなので重複しない。ブラウザの「クリックして自動再生を許可」表示が消える。小さなブロック単位で停止でき、割り込み精度は約40msになった。自己音声抑制時間もサーバー自身が正確に知る。

この途中、環境依存の罠が音声経路全体を殺した。日本語地域設定でファイルへ転送したログがcp932へ戻り、簡体字中国語を一行出力しただけで例外になった。 そのprintは転写後の必須経路にあった。UTF-8を強制し、ログ出力が例外を投げないようにした。教訓は一つ。ログに、観測対象を殺す力を持たせてはならない。

第3戦:手

最初のグローバルショートカットはWin+文字で、システム機能と衝突した。プログラム可能なマクロパッドへ移り、USB HIDには存在するが通常の物理キーボードにはないF13–F19を送ることで衝突を避けた。監視側はOS標準のRegisterHotKeyを使う。予定していた外部ホットキーソフトが実際には一度も正しく導入されていなかったため、Pythonで書き直して起動工程へ統合した。

本当の敵はチャタリングだった。一度の押下が複数イベントになり、三つの層を壊した。それぞれ別の修正が必要だった。

場所症状対策
押して話すキー押下中に接触不良のような開始・停止を反復離上後120ms以内の再押下をチャタリングとみなす
モード切替キーパスワード画面を閉じると次が開くmutexで直列化し、閉じた後に冷却時間を置く
壁紙上のボタン二重クリックが相殺し、反応しないように見える同じ対象への250ms以内の二度目をcapture層で除外

一つのハードウェア障害に、三つの抽象層で三種類の修正が必要だった。これが本稿で最も工学的な教訓かもしれない。

再利用できる原則

  • ホストが増えるほどロジックを下へ集める。「ページは表示装置」という規律の利益はホスト数とともに増える。
  • マイク、スピーカー、ホットキーのように機械へ属する能力をページ経由で実装しない。ホストの制限がそのまま自分の制限になる。
  • Booleanよりタイムアウトと絶対期限を使う。保持者が死んだ時、前者は自己回復し、後者は固着する。
  • 「構築成功」を疑い、最小の実呼び出しで検証する。

あわせて読む

02 / LINKS
C01

デジタル伴侶制作記:経過記録と全体目次

オープンソースのデスクトップ伴侶から出発し、2週間で完全に自前のシステムへ至った。全工程の記録であり、5本の技術記事への入口でもある。

全文を読む ↗
C02

自作の頭脳:四層記憶、速いモデルと遅いモデル、そして口癖との戦い

オープンソースの対話エンジンから完全自作へ。セッションを持たない関係の時間軸、四層記憶、口癖が自己増幅する障害とその構造的な対処、遅延感度に応じた二モデル構成を記録する。

全文を読む ↗