Búsqueda por voz
El widget ofrece búsqueda por voz como alternativa al input de texto. La transcripción ocurre en el navegador del usuario con la Web Speech API (webkitSpeechRecognition / SpeechRecognition); el widget envía sólo el texto resultante a /api/widget/search. El componente es VoiceSearchModal.
Cómo funciona
- El usuario hace click en el botón "voz" del input. Si
features.voiceSearch = falseo el navegador no soporta Web Speech API, el botón no se renderiza (widget/src/core/voiceSearch.ts:96-99chequea'SpeechRecognition' in window). - Se abre el modal y el navegador pide permiso de micrófono (la primera vez).
- El navegador transcribe en tiempo real. El modal aplica:
MAX_RECORDING_SECONDS = 60— corta la grabación al minuto.- Detección de silencio: 1.5 s sin voz tras al menos 2 s grabados → corta y procesa (
VoiceSearchModal.tsx:32-35).
- Cuando la transcripción acaba, el widget llama a
POST /api/widget/searchconquery = transcripción(useModalSearchHandlers.handleVoiceSearch:120-156). No hay subida de audio: la STT vive entera en el cliente.
Decisión de diseño: usar Web Speech API significa cero latencia de red para STT y cero coste server-side, a costa de soporte limitado a Chromium-based + Safari. No hay fallback server-side: si el navegador no soporta Web Speech API, el feature se oculta.
Compatibilidad de navegadores
| Navegador | Soporte |
|---|---|
| Chrome / Edge (≥ 90) | sí |
| Safari (≥ 14.1) | sí |
| iOS Safari (≥ 14.5) | sí — con permiso explícito |
| Android Chrome | sí |
| Firefox | no — Firefox no implementa webkitSpeechRecognition ni SpeechRecognition. El botón no se muestra. |
| Otros | fallback graceful: el botón se oculta si la API no existe. |
Estados del modal
El modal pasa por estos estados (claves i18n en voice.*):
tapToStart— invitación inicial.recording— grabando y transcribiendo en streaming.processing— confirmando transcripción y disparando search.success— transcripción completada.- Errores:
microphonePermissionDenied,microphoneAccessFailed,microphoneBlockedByPolicy,noAudioDetected,noVoiceDetected,audioProcessError,recordingError,browserNotSupported.
Permisos del navegador
getUserMedia()requiere contexto seguro (HTTPS). En localhost funciona sin HTTPS por excepción.- Si tu host aplica
Permissions-Policy, no bloqueesmicrophone=*. Recomendado:Permissions-Policy: microphone=(self "https://cdn.neuroon.ai").
Endpoint server-side existe (pero el widget no lo usa)
Existe POST /api/widget/search/audio (WidgetSearchController.java:185) que acepta un multipart/form-data con campo audio. Está disponible si quieres construir un cliente custom con STT server-side, pero el widget oficial no lo usa hoy.
curl -X POST https://api.neuroon.ai/api/widget/search/audio \
-H "X-Widget-Token: $WIDGET_TOKEN" \
-F "audio=@grabacion.webm" \
-F "locale=es"
Devuelve AudioSearchResponseDTO con la transcripción y los resultados. Útil para integraciones server-side o navegadores sin Web Speech API.
Próximas lecturas
- Búsqueda por texto — flujo principal al que llega la transcripción.
- Accesibilidad — el modal cumple focus trap y
Esccierra. - Reference → Errores.