Я использовал ИИ для создания основ и настройки движка с системой Android. Но я не могу заставить TTS нормально работать при использовании его для чтения текста в программе для чтения книг.
Я использую следующий сервер: https://github.com/travisvn/chatterbox-tts-api
Служба, которую я использую, возвращает файлы WAV, которые работают нормально. Но при их фрагментировании для добавления в TTS я продолжаю получать искажения и искаженный текст (например, отсутствие звука на старых ЭЛТ-телевизорах). Единственное, о чем я могу думать, это разбиение аудио при передаче к системному обработчику.
Вот основной цикл кода:
Код: Выделить всё
// This function is called when apps ask to convert TTS
// callback is an injected object to interact with the app asking for the TTS
override fun onSynthesizeText(
request: SynthesisRequest?,
callback: SynthesisCallback
) {
val text = request?.charSequenceText?.toString()
if (text.isNullOrEmpty()) {
callback.error()
return
}
runBlocking(Dispatchers.IO) {
try {
when (val result = repository.generateSpeech(text)) {
is TtsRepository.TtsResult.Success -> {
val audioData = result.audioData
val inputStream = audioData.byteStream()
// reading the WAV header
val headerBytes = ByteArray(44)
inputStream.read(headerBytes)
val wavInfo = parseWavHeader(headerBytes)
// finding the audio format, mostly for debugging
val audioFormat = when (wavInfo.bitsPerSample) {
8 -> AudioFormat.ENCODING_PCM_8BIT
16 -> AudioFormat.ENCODING_PCM_16BIT
24 -> AudioFormat.ENCODING_PCM_24BIT_PACKED
32 -> AudioFormat.ENCODING_PCM_32BIT
else -> AudioFormat.ENCODING_PCM_16BIT
}
val channelConfig = when (wavInfo.channels) {
1 -> 1 // AudioFormat.CHANNEL_OUT_FRONT_LEFT or AudioFormat.CHANNEL_OUT_FRONT_RIGHT
else -> AudioFormat.CHANNEL_CONFIGURATION_INVALID
}
callback.start(wavInfo.sampleRate, audioFormat, channelConfig)
Log.d(TAG, "TTS request started: ${wavInfo.sampleRate}Hz, ${wavInfo.channels}ch, ${wavInfo.bitsPerSample}bit")
val maxBufferSize = callback.maxBufferSize // {
callback.error()
}
}
} catch (e: Exception) {
callback.error()
}
}
}
Редактировать:
- Пример аудио: https://afilehost.com/EBnkmWYrzR0y.
- Значение «1» — это просто количество каналов, оно принимает либо 2, либо 1, и Я просто жестко запрограммировал его на 1, так как это то, что отправляет моя служба TTS.
- Сначала 44 байта считываются из аудиопотока, поэтому они пропускаются здесь:
так что с ними не должно быть проблем.
Код: Выделить всё
val headerBytes = ByteArray(44) inputStream.read(headerBytes) - вот функция parseWavHeader:
Код: Выделить всё
private fun parseWavHeader(header: ByteArray): WavAudioInfo { val buffer = ByteBuffer.wrap(header).order(ByteOrder.LITTLE_ENDIAN) val chunkId = String(header, 0, 4) require(chunkId == "RIFF") { "Not a valid WAV file" } val format = String(header, 8, 4) require(format == "WAVE") { "Not a WAV file" } val subChunk1Id = String(header, 12, 4) require(subChunk1Id == "fmt ") { "Invalid WAV format chunk" } val audioFormat = buffer.getShort(20).toInt() require(audioFormat == 1) { "Only PCM format supported, got: $audioFormat" } val numChannels = buffer.getShort(22).toInt() val sampleRate = buffer.getInt(24) val byteRate = buffer.getInt(28) val blockAlign = buffer.getShort(32).toInt() val bitsPerSample = buffer.getShort(34).toInt() val subChunk2Id = String(header, 36, 4) Log.d(TAG, "subChunk =$subChunk2Id") //require(subChunk2Id == "data") { "Invalid WAV data chunk" } // Подробнее здесь: [url]https://stackoverflow.com/questions/79859781/how-to-correctly-parse-a-wav-file-for-use-with-android-tts[/url]