Saltar al contenido principal

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

  1. El usuario hace click en el botón "voz" del input. Si features.voiceSearch = false o el navegador no soporta Web Speech API, el botón no se renderiza (widget/src/core/voiceSearch.ts:96-99 chequea 'SpeechRecognition' in window).
  2. Se abre el modal y el navegador pide permiso de micrófono (la primera vez).
  3. 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).
  4. Cuando la transcripción acaba, el widget llama a POST /api/widget/search con query = 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

NavegadorSoporte
Chrome / Edge (≥ 90)
Safari (≥ 14.1)
iOS Safari (≥ 14.5)sí — con permiso explícito
Android Chrome
Firefoxno — Firefox no implementa webkitSpeechRecognition ni SpeechRecognition. El botón no se muestra.
Otrosfallback 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 bloquees microphone=*. 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