Arquitectura y diseño de Hush Meet
┌─────────────────────────────────────────────────────┐
│ Extensión de Chrome (Manifest V3) │
│ │
│ ┌──────────────┐ ┌───────────────────────────┐ │
│ │ Popup UI │ │ Content Script │ │
│ │ (React) │ │ (meet.google.com) │ │
│ │ │ │ │ │
│ │ - Alternar │ │ ┌────────────────────┐ │ │
│ │ - Medidor │◄───►│ │ Analizador de Audio │ │ │
│ │ - Ajustes │ │ │ (Web Audio API) │ │ │
│ │ │ │ └────────┬───────────┘ │ │
│ └──────────────┘ │ │ │ │
│ ▲ │ ┌────────▼───────────┐ │ │
│ │ │ │ Máquina de Estados │ │ │
│ │ │ │ IDLE → MUTED → │ │ │
│ │ │ │ SPEAKING → GRACE │ │ │
│ │ │ └────────┬───────────┘ │ │
│ │ │ │ │ │
│ │ │ ┌────────▼───────────┐ │ │
│ │ │ │ Controlador de Silencio │ │ │
│ │ │ │ (manipulación DOM)│ │ │
│ │ │ └────────────────────┘ │ │
│ │ └───────────────────────────┘ │
│ │ │
│ └─── Chrome Storage API (sincr. config/estado)─┘
│ │
└─────────────────────────────────────────────────────┘
src/
├── constants.ts # Constantes, modos, umbrales, claves de almacenamiento
├── messages.ts # Mensajes i18n (EN/JA)
├── i18n.ts # Gestión de idioma
├── manifest.ts # Definición del manifiesto de la extensión de Chrome
├── background/
│ └── service-worker.ts # Service Worker (lanzador de juegos, etc.)
├── content/
│ └── index.ts # Content Script (máquina de estados, control de modo, atajos)
└── popup/
├── index.html # HTML de entrada del Popup
├── main.tsx # Montaje de React
├── Popup.tsx # Componente UI del Popup
├── popup.css # Estilos
├── Equalizer.tsx # Analizador de espectro
├── ThemeSwitcher.tsx # Selector de tema
├── LocaleSwitcher.tsx# Selector de idioma
└── GameLauncher.tsx # Lanzador de minijuegos
src/content/index.ts)Este script se inyecta en la página de Google Meet. Sus principales responsabilidades son:
Utiliza el AnalyserNode de la Web Audio API para medir el volumen de entrada del micrófono en tiempo real.
getUserMedia() → AudioContext → MediaStreamSource → AnalyserNode
│
getFloatTimeDomainData()
│
Cálculo RMS (Root Mean Square)
Parámetros de configuración:
| Parámetro | Valor | Descripción |
|---|---|---|
fftSize |
512 | Tamaño de la ventana FFT |
smoothingTimeConstant |
0.3 | Coeficiente de suavizado temporal |
echoCancellation |
true | Activar cancelación de eco |
noiseSuppression |
false | Supresión de ruido desactivada (para precisión del VAD) |
Una máquina de estados finitos con 5 estados gestiona el estado del habla.
IDLE ──(modo distinto de Off seleccionado)──► MUTED ──(volumen > speechThreshold)──► UNMUTING ──► SPEAKING
▲ │
│ (volumen < silenceThreshold)
│ │
└──(graceTimer expirado)── GRACE ◄───────────────┘
│
(volumen > silenceThreshold)
│
▼
SPEAKING
* Si el usuario alterna manualmente el micrófono de Meet, el modo permanece igual y solo el estado se actualiza.
| Estado | Descripción | Acción en Meet |
|---|---|---|
| IDLE | Modo Off o no inicializado | Ninguna |
| MUTED | Silencio detectado → silenciado | Silenciar |
| UNMUTING | Habla detectada → activando micrófono | Activar micrófono |
| SPEAKING | Hablando actualmente | Ninguna |
| GRACE | Habla finalizada → período de gracia | Ninguna |
Cuatro modos controlan cómo se comportan las transiciones de estado. Off es el modo con control deshabilitado.
| Modo | Activar micrófono | Silenciar | Atajo |
|---|---|---|---|
| Off | Ninguno | Ninguno | Deshabilitado |
| Auto | Automático al detectar voz | Automático en silencio | Alternar |
| Auto-Off | Manual / atajo | Automático en silencio | Alternar |
| Push-to-Talk | Mientras se mantiene la tecla presionada | Tecla liberada → Gracia → Silenciar | Mantener |
Proporciona un atajo de teclado personalizable (por defecto: Ctrl+Shift+M).
La tecla de atajo se puede cambiar libremente desde los ajustes del popup.
Diferentes umbrales para activar y silenciar el micrófono previenen el chattering (alternancia frecuente).
speechThreshold (inicio del habla) = 0.025 (por defecto)
silenceThreshold (detección silencio) = speechThreshold × 0.5 = 0.0125
Volumen
▲
│ ┄┄┄┄┄┄┄┄┄ speechThreshold (0.025) ┄┄┄┄ ← Activar micrófono al superar
│
│ ┄┄┄┄┄┄┄┄┄ silenceThreshold (0.0125) ┄┄ ← Período de gracia al bajar
│
└──────────────────────────────────────────► Tiempo
Detecta el botón de silencio de Google Meet usando múltiples estrategias:
aria-label (compatible con japonés/inglés)data-tooltipCtrl+D
El estado de silencio se determina a partir del atributo data-is-muted o del contenido de texto de aria-label.
src/popup/)Una interfaz de configuración construida con React 19. Sincroniza el estado con el Content Script en tiempo real a través de la Chrome Storage API.
speechThreshold (0.005–0.25) — guardado por modo
gracePeriod (500ms–4000ms) — guardado por modo
Popup → Chrome Storage → Content Script
│ │
│ hushMeetConfig: object │ (ajustes de sensibilidad/período de gracia)
│ hushMeetMode: string │ (modo de operación)
│ hushMeetShortcutKey: str │ (tecla de atajo)
│ │
│ ▼
│ Content Script → Chrome Storage → Popup
│ │
│ │ hushMeetState: string (estado actual)
│ │ hushMeetLevel: number (nivel de volumen)
│ │ hushMeetSpectrum: array (espectro)
└────────────────────────────┘
El Popup y el Content Script no se comunican directamente; se comunican bidireccionalmente a través de eventos de cambio de la Chrome Storage API.
| Herramienta | Versión | Propósito |
|---|---|---|
| Vite+ | toolchain | Gestión de dependencias, compilación, pruebas, validación |
| Vite | 8.x | Infraestructura interna de compilación |
| CRXJS Vite Plugin | 2.x | HMR de extensión de Chrome y generación de manifiesto |
| React | 19.x | Popup UI |
| TypeScript | 5.9.x | Seguridad de tipos |
| Comando | Descripción |
|---|---|
vp install |
Instalar dependencias |
vp build |
Compilación para producción |
vp test |
Ejecutar pruebas |
vp check |
formato / lint / verificación de tipos |