Skip to content

No Android existe a API nativa do pacote android.speech é uma biblioteca nativa que fornece os elementos básicos para executar a tarefa de reconhecimento de fala, também conhecida como ASR (Automatic Speech Recognition) ou STT (speech-to-text).

Notifications You must be signed in to change notification settings

andrebarsotti/lab-voice-to-text-android

Repository files navigation

Lab Voice To Text no Android

No Android existe a API nativa do pacote android.speech é uma biblioteca nativa que fornece os elementos básicos para executar a tarefa de reconhecimento de fala, também conhecida como ASR (Automatic Speech Recognition) ou STT (speech-to-text). Esse é um método convencional de tratamento de fala e portanto, em geral, apenas o conjunto das palavras é obtido como resultado, isto é, não são identificadas pontuações de forma automática.

Esse laboratório explora a utilização dessa biblioteca nativa para apresentar os textos que são falados pelo usuário ao clicar em um botão.

Requisitos

Esse aplicativo foi desenvolvido no seguinte ambiente:

  • Android Studio Hedgehog | 2023.1.1 Patch 1 (Build #AI-231.9392.1.2311.11255304, built on December 26, 2023)
  • OpenJDK 17
  • Android SDK 34
  • Gradle 8.2.0

Sobre a aplicação e sua arquitetura

O aplicativo foi construído seguindo a arquitetura sugerida pelo The Android Open Source Project (2023) e utiliza Jetpack Compose para construção das interfaces. O core foi construído seguindo basicamente os passos descritos por Atitienei (2023) em seu artigo do Medium, com ajustes para a arquitetura e alguns pontos relevantes descritos no artigo de Khare (2021).

A classe VoicetoTextParser.kt contém o core da aplicação, com a implementação do processo de reconhecimento de voz e seu envio para a UI utilizando StateFlow.

Bibliotecas e permissões

Para incluir o STT (speech-to-text) em uma aplicação Android nenhuma biblioteca externa é necessária, porém é preciso que a aplicação tenha permissões para "gravar" audios. Dessa forma é preciso incluir a linha abaixo no manifesto da aplicação:

<uses-permission android:name="android.permission.RECORD_AUDIO" />

De forma complementar também será necessário solicitar a permissão de audio em algum momento o que pode ser feito da seguinte forma:

ActivityCompat.requestPermissions(
    context as Activity,
    arrayOf(Manifest.permission.RECORD_AUDIO),
    123
)

Um exemplo completo da implementação do código necessário pode ser encontrado no arquivo setupRecordPermissions.kt

Reconhecendo a fala do usuário e convertendo em texto

Existem dois elementos básicos necessários para utilizar a função de texto para fala da biblioteca nativa do android:

  • SpeechRecognizer: Essa é a classe responsável por efetivamente executar a função de reconhecimento de voz.
  • RecognitionListener: Essa é uma interface onde os retornos das chamadas do reconhecimento de voz podem ser manipulados através de sua implementação em um objeto concreto.

O início do processo acontece quando uma instância do SpeechRecognizer é criada a partir do método estático factory da própria classe como no exemplo abaixo:

import android.speech.SpeechRecognizer

val recognizer = SpeechRecognizer.createSpeechRecognizer(context)

Nesse caso o contexto pode ser tanto a aplicação quanto a Activity, no nosso app de exemplo utilizamos como contexto a própria aplicação.

Com o recognizer criado vamos agora setar o listener, que será responsável por intermediar o que será reconhecido e tratar o texto resultante. Para setar utilize o método setRecognitionListener como no exemplo abaixo:

recognizer.setRecognitionListener(listener)

Agora será preciso definir uma Intent que irá iniciar nossa aplicação, esse intent passa para o SpeechRecognizer vários parâmetros que desejamos. Abaixo um exemplo:

import android.speech.RecognizerIntent

val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
    putExtra(
        RecognizerIntent.EXTRA_LANGUAGE_MODEL,
        RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
    )
    putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true)
    putExtra(RecognizerIntent.EXTRA_LANGUAGE, "pt-BR")
}

Nessa Intent informamos que nossa ação será de reconhecimento de voz (ACTION_RECOGNIZE_SPEECH), o extra EXTRA_LANGUAGE_MODEL é obrigatório pois precisamos definir o modelo de reconhecimento de falar que será utilizado, no nosso caso utilizamos o LANGUAGE_MODEL_FREE_FORM que indica um modelo de fala livre. Já o extra EXTRA_PARTIAL_RESULTS setado como true nos permite receber parciais do texto durante o reconhecimento da fala e o EXTRA_LANGUAGE com o valor pt-BR garante que haverá reconhecimento de voz para o português brasileiro. Mais detalhes sobre os parâmetros pode ser obtido na documentação do Intent.

Com esses passos feitos podemos iniciar o reconhecimento de voz chamando o método startListening passando nossa Intent como parâmetro:

recognizer.startListening(intent)

Para interromper basta chamar o método stopListening. Abaixo o exemplo:

recognizer.stopListening()

Como mencionado anteriormente os texto gerado pelo SpeechRecognizer é tratado em uma instância concreta da interface RecognitionListener, pois é nela que estão os eventos. Essa interface obriga a implementação dos seguintes métodos:

  • onReadyForSpeech: É chamado quando o SpeechRecognizer foi corretamente inicializado e esta pronto para processar a voz do usuário. Pode ser utilizado para indicar na interface com o usuário que ele pode começar a falar.
  • onBeginningOfSpeech: É chamado após o SpeechRecognizer identificar que o usuário começou a falar. Essa informação pode ser utilizada para indicar graficamente na interface que o usuário começou a falar.
  • onRmsChanged: Esse método recebe como um float (rmsdB) que indica uma métrica da variação do volume da fala durante o reconhecimento da voz. Pode ser utilizado para indicar graficamente na interface que a voz esta sendo reconhecida.
  • onEndOfSpeech: É chamado após o SpeechRecognizer identificar que o usuário terminou de falar. Essa informação pode ser utilizada para indicar graficamente na interface que o usuário terminou a falar.
  • onResults e onPartialResults: recebe um Bundle como parâmetro com o resultado do processamento total (onResults) ou parcial (onPartialResults), antes do usuário terminar de falar. É através desses métodos que o texto do que foi falados é gerado.
  • onError: Quando acontece algum erro no processamento da fala (fala irreconhecida, por exemplo) esse método será chamado e ele recebe um inteiro com o código do erro correspondente.
  • onBufferReceived: Recebe um buffer como um array de bytes que pode ser utilizado para salvar o audio gravado se for desejado.
  • onEvent: Esse método esta reservado para uso futuro e no momento não é chamado.

Mais detalhes sobre cada um dos callbacks pode ser encontrada na documentação. Podemos verificar que os métodos mais relevantes são o onResults e o onError, pois contemplam o texto transcrito do que foi falado ou o erro, caso aconteça algum problema. Abaixo um exemplo de implementação simples.

import android.speech.RecognitionListener
import android.widget.Toast

recognizer.setRecognitionListener(object:RecognitionListener {
    override fun onReadyForSpeech(params: Bundle?) = Unit

    override fun onBeginningOfSpeech() = Unit

    override fun onRmsChanged(rmsdB: Float) = Unit

    override fun onBufferReceived(buffer: ByteArray?) = Unit

    override fun onEndOfSpeech() = Unit

    override fun onError(error: Int) {
        val msgError = when (error) {
            SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "Network timeout"
            SpeechRecognizer.ERROR_NETWORK -> "Network error"
            SpeechRecognizer.ERROR_AUDIO -> "Audio recording error"
            SpeechRecognizer.ERROR_SERVER -> "Server error"
            SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "Speech input"
            SpeechRecognizer.ERROR_NO_MATCH -> "No recognition result matched."
            SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "RecognitionService busy"
            SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> "Insufficient permissions"
            else -> "Didn't understand, please try again."
        }
        
        Toast.makeText(context,"Error: $msgError", Toast.LENGTH_SHORT).show()
    }

    override fun onResults(results: Bundle?) {
        results
            ?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
            ?.getOrNull(0)
            ?.let { text ->
                Toast.makeText(context,"Text: $text", Toast.LENGTH_LONG).show()
            }
    }

    override fun onPartialResults(partialResults: Bundle?) = Unit

    override fun onEvent(eventType: Int, params: Bundle?) = Unit
})

Conclusões

A implementação do ASR em aplicações Android Nativas com a biblioteca nativa android.speech provou ser extremamente simplificada e prática, sem grandes complexidades no processo. Se o dispositivo estiver corretamente configurado em testes iniciais provou-se possível o seu uso offline, entende-se que seja necessário solicitar que o pacote de reconhecimento de fala padrão do assistente de voz local seja baixado para esse tipo de uso.

Tendo em vista sua facilidade e a ausência de pacotes adicionais entendem-se que trata-se de uma forma viável para o uso embarcado da tecnologia em aplicações Android Nativas.

Possíveis estudos futuros

Como desdobramentos desse lab entende-se que podem ser interessantes as seguintes linhas de pesquisa:

  • Incorporar um modelo de predição de pontuação após receber o resultado: Pesquisar uma forma de aplicar o modelo em cascata treinando um segundo modelo para a predição de pontuação ou utilizando um existente, como descrito por Casanova et al. (2023).
  • Desenvolvimento de Assistentes Virtuais: Pesquisar outras ferramentas que descrevam como montar um assistente virtual com base nas ferramentas existentes e como integrar essas ferramentas, com exemplos práticos

REFERÊNCIAS

ANDROID API REFERENCE: android.speech. [S. l.], [s. d.]. Disponível em: https://developer.android.com/reference/android/speech/package-summary. Acesso em: 12 jan. 2024.

ATITIENEI, D. Voice to Text in Jetpack Compose — Android. In: MEDIUM. 10 mar. 2023. Disponível em: https://medium.com/@daniel.atitienei/voice-to-text-in-jetpack-compose-android-c1e077627abe. Acesso em: 9 jan. 2024.

CASANOVA, E. et al. Recursos para o processamento de fala. In: Processamento de Linguagem Natural: Conceitos, Técnicas e Aplicações em Português. 1. ed. São Carlos: BPLN, 2023. E-Book. cap. 3 p. 42-63. Disponível em: https://brasileiraspln.com/livro-pln/1a-edicao/parte2/cap3/cap3.html. Acesso em: 15 jan. 2024.

KHARE, A. Add Voice Commands to Android Apps. In: MEDIUM. GEEK CULTURE. 6 jul. 2021. Disponível em: https://medium.com/geekculture/add-voice-commands-to-android-apps-80157c0d5bcc. Acesso em: 9 jan. 2024.

THE ANDROID OPEN SOURCE PROJECT. GUIDE TO APP ARCHITECTURE. Android for Developers, 2023. Disponível em: https://developer.android.com/topic/architecture#modern-app-architecture Acessado em: 29/11/2023.

About

No Android existe a API nativa do pacote android.speech é uma biblioteca nativa que fornece os elementos básicos para executar a tarefa de reconhecimento de fala, também conhecida como ASR (Automatic Speech Recognition) ou STT (speech-to-text).

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages