Based on an article, I tried to integrate a Text-to-Speech feature into my application. However, I can't say it works well since I still encounter some bugs. First, I copied the following function:
@Composable
fun rememberTextToSpeech(ttsLocale: Locale): MutableState<TextToSpeech?> {
val context = LocalContext.current
val tts = remember { mutableStateOf<TextToSpeech?>(null) }
DisposableEffect(context) {
val textToSpeech = TextToSpeech(context) { status ->
if (status == TextToSpeech.SUCCESS) {
tts.value?.language = ttsLocale
}
}
tts.value = textToSpeech
onDispose {
tts.value?.stop()
tts.value?.shutdown()
}
}
return tts
}
Then, I created a reusable component for my button. Depending on the screen, it can be rendered 2–3 times with different parameters.
@Composable
fun AudioButton(
language: Language,
text: String
) {
val ttsLocale = when (language) {
Language.EN -> Locale("en", "GB")
...
}
var isSpeaking by remember { mutableStateOf(false) }
val tts = rememberTextToSpeech(ttsLocale)
isSpeaking = false
Button(
onClick = {
if (tts.value?.isSpeaking == true) {
tts.value?.stop()
isSpeaking = false
} else {
tts.value?.speak(text, TextToSpeech.QUEUE_FLUSH, null, null)
isSpeaking = true
}
},
modifier = Modifier.size(48.dp),
...
) {
Icon(
modifier = Modifier.size(24.dp),
imageVector = AudioIcon,
...
)
}
}
Even when only one button is rendered, there is noticeable latency the first few times I press it. I have to press it multiple times before the audio starts playing. However, after a few attempts, it begins playing instantly.
I would like the audio to start as soon as I press the button and stop automatically once the word has been pronounced.