← トップに戻る

技術ドキュメント

Hush Meet のアーキテクチャと設計について

アーキテクチャ概要

┌─────────────────────────────────────────────────────┐
│  Chrome Extension (Manifest V3)                     │
│                                                     │
│  ┌──────────────┐     ┌───────────────────────────┐ │
│  │   Popup UI   │     │     Content Script         │ │
│  │  (React)     │     │   (meet.google.com)        │ │
│  │              │     │                            │ │
│  │  - Toggle    │     │  ┌────────────────────┐   │ │
│  │  - Meter     │◄───►│  │  Audio Analyser    │   │ │
│  │  - Settings  │     │  │  (Web Audio API)   │   │ │
│  │              │     │  └────────┬───────────┘   │ │
│  └──────────────┘     │           │               │ │
│         ▲             │  ┌────────▼───────────┐   │ │
│         │             │  │  State Machine     │   │ │
│         │             │  │  IDLE → MUTED →    │   │ │
│         │             │  │  SPEAKING → GRACE  │   │ │
│         │             │  └────────┬───────────┘   │ │
│         │             │           │               │ │
│         │             │  ┌────────▼───────────┐   │ │
│         │             │  │  Mute Controller   │   │ │
│         │             │  │  (DOM操作)│   │ │
│         │             │  └────────────────────┘   │ │
│         │             └───────────────────────────┘ │
│         │                                           │
│         └─── Chrome Storage API (設定/状態の同期)─┘
│                                                     │
└─────────────────────────────────────────────────────┘

プロジェクト構成

src/
├── constants.ts          # 定数・モード・閾値・ストレージキー定義
├── messages.ts           # i18n メッセージ(EN/JA)
├── i18n.ts               # ロケール管理
├── manifest.ts           # Chrome拡張マニフェスト定義
├── background/
│   └── service-worker.ts # Service Worker(ゲーム起動等)
├── content/
│   └── index.ts          # Content Script(状態マシン・モード制御・ショートカット)
└── popup/
    ├── index.html        # Popup エントリHTML
    ├── main.tsx          # React マウント
    ├── Popup.tsx         # Popup UIコンポーネント
    ├── popup.css         # スタイル
    ├── Equalizer.tsx     # スペクトラムアナライザー
    ├── ThemeSwitcher.tsx # テーマ切替
    ├── LocaleSwitcher.tsx# 言語切替
    └── GameLauncher.tsx  # ミニゲーム起動

コンポーネント詳細

1. Content Script (src/content/index.ts)

Google Meet のページに注入されるスクリプトです。主に以下の責務を持ちます:

1.1 音声解析エンジン

Web Audio API の AnalyserNode を使用して、マイク入力の音量をリアルタイムに測定します。

getUserMedia() → AudioContext → MediaStreamSource → AnalyserNode
                                                          │
                                                    getFloatTimeDomainData()
                                                          │
                                                    RMS (二乗平均平方根) 算出

設定パラメータ:

パラメータ 説明
fftSize 512 FFTウィンドウサイズ
smoothingTimeConstant 0.3 時間方向の平滑化係数
echoCancellation true エコーキャンセルを有効化
noiseSuppression false ノイズ抑制はオフ(VAD精度のため)

1.2 状態マシン

5つの状態を持つ有限状態マシンで発話状態を管理します。

IDLE ──(Off 以外のモード選択)──► MUTED ──(音量 > speechThreshold)──► UNMUTING ──► SPEAKING
                     ▲                                                │
                     │                              (音量 < silenceThreshold)
                     │                                                │
                     └──(graceTimer満了)── GRACE ◄────────────────────┘
                                            │
                                     (音量 > silenceThreshold)
                                            │
                                            ▼
                                        SPEAKING

※ ユーザーが手動で Meet のマイクを触った場合も、モードは変えず状態だけ追従します。
状態 説明 Meet操作
IDLE Off モードまたは未初期化 なし
MUTED 無音 → ミュート中 ミュート
UNMUTING 音声検出 → 解除中 ミュート解除
SPEAKING 発話中 なし
GRACE 発話終了 → 猶予期間 なし

1.3 動作モード

4つのモードで状態遷移の挙動を切り替えられます。Off が制御停止モードです。

モード ミュート解除 ミュート ショートカット
Off なし なし 無効
Auto 音声検知で自動 無音で自動 トグル
Auto-Off 手動/ショートカット 無音で自動 トグル
Push-to-Talk キー押下中のみ キー離す→Grace→ミュート ホールド

1.4 ショートカットキー

カスタマイズ可能なキーボードショートカット(デフォルト: Ctrl+Shift+M)を提供します。

ショートカットキーはポップアップの設定から自由に変更できます。

1.5 非対称閾値設計

ミュート解除とミュートで異なる閾値を使用することで、チャタリング(頻繁な切り替わり)を防止しています。

speechThreshold (発話開始)  = 0.025  (デフォルト)
silenceThreshold (無音判定) = speechThreshold × 0.5 = 0.0125

  音量
   ▲
   │  ┄┄┄┄┄┄┄┄┄ speechThreshold (0.025) ┄┄┄┄  ← これを超えたらミュート解除
   │
   │  ┄┄┄┄┄┄┄┄┄ silenceThreshold (0.0125) ┄┄  ← これを下回ったら猶予開始
   │
   └──────────────────────────────────────────► 時間

1.6 ミュートボタン検出

Google Meet のミュートボタンを複数の戦略で検出します:

  1. aria-label 属性による検索(日本語/英語対応)
  2. data-tooltip 属性による検索
  3. フォールバック: Ctrl+D キーボードショートカットのシミュレーション

ミュート状態の判定は data-is-muted 属性または aria-label の文言から行います。

2. Popup UI (src/popup/)

React 19 で構築された設定UIです。Chrome Storage API を介して Content Script とリアルタイムに状態を同期します。

データフロー

Popup → Chrome Storage → Content Script
  │                            │
  │  hushMeetConfig: object    │  (感度/猶予時間の設定)
  │  hushMeetMode: string      │  (動作モード)
  │  hushMeetShortcutKey: str  │  (ショートカットキー)
  │                            │
  │                            ▼
  │                      Content Script → Chrome Storage → Popup
  │                            │
  │                            │  hushMeetState: string  (現在の状態)
  │                            │  hushMeetLevel: number  (音量レベル)
  │                            │  hushMeetSpectrum: array (スペクトラム)
  └────────────────────────────┘

Popup と Content Script は直接通信せず、Chrome Storage API の変更イベントを介して双方向に通信します。

ビルドシステム

ツール バージョン 用途
Vite+ toolchain 依存管理・ビルド・テスト・検証
Vite 8.x 内部ビルド基盤
CRXJS Vite Plugin 2.x Chrome拡張のHMR・manifest生成
React 19.x Popup UI
TypeScript 5.9.x 型安全性

コマンド

コマンド 説明
vp install 依存関係のインストール
vp build プロダクションビルド
vp test テスト実行
vp check format / lint / typecheck

既知の制限事項

今後の改善案