Pular para o conteúdo principal

Kotlin Android Text To Speech e Speech To Text Example

Este tutorial ensinará através de exemplos simples Text To Speech e Speech To Text. Como você pode converter texto escrito em palavras faladas ou palavras faladas em texto escrito programaticamente.

Há dois exemplos até agora:

  1. Exemplo 1 Kotlin Speech to Text e Text to Speech
  2. Exemplo 2- Kotlin Speech to Text e Text to Speech

Vamos começar.

Exemplo 1: Kotlin Android Text to Speech e Text Speech

Vejamos nosso exemplo. Este exemplo abrange tanto Text To Speech quanto Speech To Text. Existe um texto de edição onde você digita o texto a ser convertido.

Aqui está uma demonstração do que vamos criar:

Kotlin Android Text to Speech and Text Speech

Etapa 1: criar projeto

Comece criando um projeto Android Studio vazio.

Etapa 2: dependências

Nenhuma biblioteca de terceiros é necessária.

Etapa 3: Layout do projeto

Temos um layout: o layout para nossa MainActivity:

atividade_main.xml

Adicionaremos TextInputEditText, um FloatingActionButton e um ExtendedFloatingAction como nossos componentes de interface do usuário:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edtText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Text" />
</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/fabPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Play"
android:textAlignment="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textInputLayout" />

<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fabVoice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/ic_keyboard_voice" />

</androidx.constraintlayout.widget.ConstraintLayout>

Etapa 4: criar um ViewModel

Teremos uma classe chamada BaseViewModel que estenderá o androidx.lifecycle.ViewModel e será nossa classe ViewModel. Aqui teremos pelo menos duas funções:

Uma função para iniciar nosso reconhecedor de fala via Intent:

    fun displaySpeechRecognizer() {
startForResult.launch(Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale("in_ID"))
putExtra(RecognizerIntent.EXTRA_PROMPT, Locale("Bicara sekarang"))
})
}

E uma função para transformar nosso Texto em Fala através do textToSpeechEngine:

    fun speak(text: String) = viewModelScope.launch{
textToSpeechEngine.speak(text, TextToSpeech.QUEUE_FLUSH, null, "")
}

Aqui está o código completo:

BaseViewModel.kt

import android.content.Intent
import android.speech.RecognizerIntent
import android.speech.tts.TextToSpeech
import androidx.activity.result.ActivityResultLauncher
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import java.util.*

class BaseViewModel : ViewModel() {

private lateinit var textToSpeechEngine: TextToSpeech
private lateinit var startForResult: ActivityResultLauncher<Intent>

fun initial(
engine: TextToSpeech, launcher: ActivityResultLauncher<Intent>
) = viewModelScope.launch {
textToSpeechEngine = engine
startForResult = launcher
}

fun displaySpeechRecognizer() {
startForResult.launch(Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale("in_ID"))
putExtra(RecognizerIntent.EXTRA_PROMPT, Locale("Bicara sekarang"))
})
}

fun speak(text: String) = viewModelScope.launch{
textToSpeechEngine.speak(text, TextToSpeech.QUEUE_FLUSH, null, "")
}

}

Etapa 5: crie nossa MainActivity

Finalmente teremos nossa MainActivity:

MainActivity.kt

import android.os.Bundle
import android.speech.RecognizerIntent
import android.speech.tts.TextToSpeech
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import id.derysudrajat.stttts.databinding.ActivityMainBinding
import java.util.*

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding
private val model: BaseViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
model.initial(textToSpeechEngine, startForResult)
with(binding) {
fabVoice.setOnClickListener { model.displaySpeechRecognizer() }
fabPlay.setOnClickListener {
val text = edtText.text?.trim().toString()
model.speak(if (text.isNotEmpty()) text else "Text tidak boleh kosong")
}
}
}

private val startForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == RESULT_OK) {
val spokenText: String? =
result.data?.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
.let { text -> text?.get(0) }
binding.edtText.setText(spokenText)
}
}

private val textToSpeechEngine: TextToSpeech by lazy {
TextToSpeech(this) {
if (it == TextToSpeech.SUCCESS) textToSpeechEngine.language = Locale("in_ID")
}
}
}

Correr

Copie o código ou baixe-o no link abaixo, construa e execute.

Referência

Seguem os links de referência:

Download Exemplo

Exemplo 2: Texto para fala simples e exemplo de fala para texto

Este é um exemplo simples de Text To Speech e Speech To Text no Kotlin Android.

Etapa 1: criar projeto

Comece criando um projeto Android Studio vazio.

Etapa 2: dependências

Nenhuma biblioteca de terceiros é necessária.

Etapa 3: Layout do projeto

Adicione dois botões: um para TTS e outro STT, bem como um texto de edição para inserir ou exibir o texto.

atividade_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="24dp"
tools:context=".MainActivity">

<Button
android:id="@+id/btn_stt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Speak" />

<EditText
android:id="@+id/et_text_input"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="24dp"
android:layout_marginBottom="24dp"
android:layout_weight="1"
android:gravity="center"
android:hint="Text from STT or for TTS goes here." />

<Button
android:id="@+id/btn_tts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Listen" />

</LinearLayout>

Etapa 4: escrever código

Aqui está o código completo:

MainActivity.kt

import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.speech.RecognizerIntent
import android.speech.tts.TextToSpeech
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*

class MainActivity : AppCompatActivity() {

companion object {
private const val REQUEST_CODE_STT = 1
}

private val textToSpeechEngine: TextToSpeech by lazy {
TextToSpeech(this,
TextToSpeech.OnInitListener { status ->
if (status == TextToSpeech.SUCCESS) {
textToSpeechEngine.language = Locale.UK
}
})
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

btn_stt.setOnClickListener {
val sttIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
sttIntent.putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
)
sttIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
sttIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Speak now!")

try {
startActivityForResult(sttIntent, REQUEST_CODE_STT)
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
Toast.makeText(this, "Your device does not support STT.", Toast.LENGTH_LONG).show()
}
}

btn_tts.setOnClickListener {
val text = et_text_input.text.toString().trim()
if (text.isNotEmpty()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
textToSpeechEngine.speak(text, TextToSpeech.QUEUE_FLUSH, null, "tts1")
} else {
textToSpeechEngine.speak(text, TextToSpeech.QUEUE_FLUSH, null)
}
} else {
Toast.makeText(this, "Text cannot be empty", Toast.LENGTH_LONG).show()
}
}

}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_CODE_STT -> {
if (resultCode == Activity.RESULT_OK && data != null) {
val result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
result?.let {
val recognizedText = it[0]
et_text_input.setText(recognizedText)
}
}
}
}
}

override fun onPause() {
textToSpeechEngine.stop()
super.onPause()
}

override fun onDestroy() {
textToSpeechEngine.shutdown()
super.onDestroy()
}
}

Correr

Copie o código ou baixe-o no link abaixo, construa e execute.

Referência

Seguem os links de referência:

Download Exemplo