fix: TTS read-aloud downloads audio via OkHttp before playing

MediaPlayer.setDataSource(url) with HTTPS URLs can silently fail due to
certificate issues, redirect handling, or listener race conditions (listeners
were set after prepareAsync). Fix: download the WAV file via OkHttp (same
client as all other network calls) to a temp file, set listeners before
prepareAsync, play from local path. Temp file cleaned up on completion/error.
This commit is contained in:
Bruno Deanoz 2026-06-24 01:33:23 +02:00
parent 287cdb4c6b
commit bb53b24655

View file

@ -370,26 +370,42 @@ fun ChatScreen(
}
fun playTtsUrl(url: String, messageId: Long) {
try {
val player = MediaPlayer().apply {
setDataSource(url)
prepareAsync()
setOnPreparedListener { start() }
setOnCompletionListener {
release()
ttsPlayerRef.value = null
playingTtsForId = null
scope.launch {
try {
val tmpFile = kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.IO) {
val req = okhttp3.Request.Builder().url(url).build()
KaizenApi.imageClient.newCall(req).execute().use { resp ->
if (!resp.isSuccessful) return@withContext null
val bytes = resp.body!!.bytes()
java.io.File.createTempFile("tts_", ".wav", context.cacheDir).also { it.writeBytes(bytes) }
}
}
setOnErrorListener { _, _, _ ->
release()
ttsPlayerRef.value = null
if (tmpFile == null) {
playingTtsForId = null
true
return@launch
}
val player = MediaPlayer().apply {
setOnPreparedListener { start() }
setOnCompletionListener {
release()
ttsPlayerRef.value = null
playingTtsForId = null
tmpFile.delete()
}
setOnErrorListener { _, _, _ ->
release()
ttsPlayerRef.value = null
playingTtsForId = null
tmpFile.delete()
true
}
setDataSource(tmpFile.absolutePath)
prepareAsync()
}
ttsPlayerRef.value = player
} catch (_: Exception) {
playingTtsForId = null
}
ttsPlayerRef.value = player
} catch (_: Exception) {
playingTtsForId = null
}
}