Implementación Avanzada de Interacción por Voz en Android con ML Kit y TextToSpeech

Elección estratégica de APIs

No todos los motores de voz son iguales. Para proyectos que requieren alta precisión, soporte offline y flexibilidad en entornos ruidosos, Google ML Kit Speech Recognition supera claramente a SpeechRecognizer nativo. Este último depende del servicio de voz del sistema —que varía entre fabricantes— y carece de control sobre modelos, ajustes acústicos o modos de streaming.

Configuración mínima efectiva

En lugar de depender de versiones obsoletas o dependencias redundantes, usamos la versión actualizada y modular:

implementation 'com.google.mlkit:speech-recognition:18.0.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.5'

Se omite voice-recognition, ya que no es un artefacto válido en ML Kit v2 — el reconocimiento se gestiona exclusivamente mediante speech-recognition.

Manejo seguro de permisos

Más allá de solicitar RECORD_AUDIO, implementamos una verificación escalonada:

private fun requestMicrophonePermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        // Usa el nuevo permiso granular
        requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), NOTIFICATION_REQUEST_CODE)
    }
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) 
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(Manifest.permission.RECORD_AUDIO),
            AUDIO_REQUEST_CODE
        )
    }
}

Reconocimiento continuo con control de flujo

Evitamos llamadas bloqueantes y usamos un patrón de escucha reactiva con manejo explícito del ciclo de vida:

private lateinit var speechClient: SpeechRecognition

private fun setupSpeechClient() {
    speechClient = SpeechRecognition.getClient(
        SpeechRecognitionOptions.Builder()
            .setLanguage("zh-CN")
            .setEnableWordTimeOffsets(true)  // Útil para resaltado en tiempo real
            .build()
    )
}

private fun startStreamingRecognition() {
    val intent = Intent(this, StreamingRecognitionService::class.java)
    startService(intent) // Ejecuta en foreground service para evitar limitaciones de background
}

Síntesis de voz con personalización contextual

En lugar de usar TextToSpeech.SPEECH_QUEUE_FLUSH —que interrumpe todo— optamos por una cola inteligente basada en prioridad:

private val ttsEngine = TextToSpeech(this) { status ->
    if (status == TextToSpeech.SUCCESS) {
        ttsEngine.setLanguage(Locale.forLanguageTag("zh-CN"))
        ttsEngine.setSpeechRate(0.9f)
        ttsEngine.setPitch(1.1f)
    }
}

fun speakWithPriority(text: String, priority: Int = 1) {
    val params = Bundle().apply {
        putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, AudioManager.STREAM_VOICE_CALL)
        putInt("queueMode", priority) // Personalizado: 0=override, 1=append
    }
    ttsEngine.speak(text, TextToSpeech.QUEUE_ADD, params, "utterance_id_$System.currentTimeMillis()")
}

Optimizaciones clave

  • Reducción de latencia: Carga previa del modelo con downloadModelIfNotAvailable() y uso de StreamingRecognition en vez de frases completas.
  • Robustez acústica: Integración opcional con AudioProcessor para supresión de eco y normalización dinámica de gananica.
  • Gestión efciiente de recursos: Detención automática tras 3 segundos de silencio usando AudioRecord en modo low-latency + umbral RMS personalizable.

Privacidad por diseño

Todas las operaciones de reconocimiento se configuran en modo ON_DEVICE por defecto. Cuando se requiere procesamiento remoto, los datos se envían cifrados vía HTTPS y se eliminan inmediatamente tras la transcripción. No se almacenan grabaciones ni metadatos sensibles sin consentimiento explícito.

Ejemplo práctico: Asistente de notas por voz

Una aplicación minimalista que permite:

  • Grabar fragmentos de voz y convertirlos a texto localmente.
  • Guardar transcripciones en Room con timestamp y etiquetas automáticas (ej. "reunión", "recordatorio").
  • Reproducir cualquier nota guardada con voz natural y velocidad ajustable.

El código fuente incluye gestión de estado de micrófono, detección de finalización automática y recuperación ante fallos de red sin reinicio manual.

Etiquetas: Android mlkit texttospeech speechrecognition room-database

Publicado el 8-8 09:51