This commit is contained in:
Horis
2023-06-20 18:11:45 +08:00
parent c621e3a670
commit 883a0bea4e
@@ -26,13 +26,14 @@ import io.legado.app.utils.printOnDebug
import io.legado.app.utils.servicePendingIntent import io.legado.app.utils.servicePendingIntent
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import okhttp3.Response import okhttp3.Response
import org.mozilla.javascript.WrappedException import org.mozilla.javascript.WrappedException
import java.io.File import java.io.File
@@ -68,32 +69,22 @@ class HttpReadAloudService : BaseReadAloudService(),
super.onDestroy() super.onDestroy()
downloadTask?.cancel() downloadTask?.cancel()
exoPlayer.release() exoPlayer.release()
Coroutine.async {
removeCacheFile()
}
} }
override fun play() { override fun play() {
pageChanged = false pageChanged = false
exoPlayer.stop() exoPlayer.stop()
exoPlayer.clearMediaItems()
if (!requestFocus()) return
if (contentList.isEmpty()) { if (contentList.isEmpty()) {
AppLog.putDebug("朗读列表为空") AppLog.putDebug("朗读列表为空")
ReadBook.readAloud() ReadBook.readAloud()
} else { } else {
super.play() super.play()
kotlin.runCatching { downloadAndPlayAudios()
if (nowSpeak == 0) {
downloadAudio()
} else {
val fileName = md5SpeakFileName(contentList[nowSpeak])
val file = getSpeakFileAsMd5(fileName)
if (file.exists()) {
playAudio(file)
} else if (!downloadTaskActiveLock.isLocked) {
downloadAudio()
}
}
}.onFailure {
toastOnUi("朗读出错:${it.localizedMessage}")
AppLog.put("朗读出错:${it.localizedMessage}", it)
}
} }
} }
@@ -105,21 +96,20 @@ class HttpReadAloudService : BaseReadAloudService(),
readAloudNumber += contentList[nowSpeak].length + 1 readAloudNumber += contentList[nowSpeak].length + 1
if (nowSpeak < contentList.lastIndex) { if (nowSpeak < contentList.lastIndex) {
nowSpeak++ nowSpeak++
play()
} else { } else {
nextChapter() nextChapter()
} }
} }
private fun downloadAudio() { private fun downloadAndPlayAudios() {
downloadTask?.cancel() downloadTask?.cancel()
downloadTask = execute { downloadTask = execute {
downloadTaskActiveLock.withLock { downloadTaskActiveLock.withLock {
ensureActive() ensureActive()
removeCacheFile()
val httpTts = ReadAloud.httpTTS ?: throw NoStackTraceException("tts is null") val httpTts = ReadAloud.httpTTS ?: throw NoStackTraceException("tts is null")
contentList.forEachIndexed { index, content -> contentList.forEachIndexed { index, content ->
ensureActive() ensureActive()
if (index < nowSpeak) return@forEachIndexed
val fileName = md5SpeakFileName(content) val fileName = md5SpeakFileName(content)
val speakText = content.replace(AppPattern.notReadAloudRegex, "") val speakText = content.replace(AppPattern.notReadAloudRegex, "")
if (speakText.isEmpty()) { if (speakText.isEmpty()) {
@@ -141,13 +131,19 @@ class HttpReadAloudService : BaseReadAloudService(),
return@execute return@execute
} }
} }
if (index == nowSpeak) { val file = getSpeakFileAsMd5(fileName)
val file = getSpeakFileAsMd5(fileName) val mediaItem = MediaItem.fromUri(Uri.fromFile(file))
playAudio(file) launch(Main) {
exoPlayer.addMediaItem(mediaItem)
if (!exoPlayer.isPlaying && nowSpeak == index) {
exoPlayer.playWhenReady = true
exoPlayer.prepare()
}
} }
} }
} }
}.onError(IO) { }.onError {
toastOnUi("朗读出错:${it.localizedMessage}")
AppLog.put("朗读下载出错\n${it.localizedMessage}", it) AppLog.put("朗读下载出错\n${it.localizedMessage}", it)
} }
} }
@@ -193,6 +189,7 @@ class HttpReadAloudService : BaseReadAloudService(),
e.printOnDebug() e.printOnDebug()
throw e throw e
} }
is SocketTimeoutException, is ConnectException -> { is SocketTimeoutException, is ConnectException -> {
downloadErrorNo++ downloadErrorNo++
if (downloadErrorNo > 5) { if (downloadErrorNo > 5) {
@@ -202,6 +199,7 @@ class HttpReadAloudService : BaseReadAloudService(),
throw e throw e
} }
} }
else -> { else -> {
downloadErrorNo++ downloadErrorNo++
val msg = "tts下载错误\n${e.localizedMessage}" val msg = "tts下载错误\n${e.localizedMessage}"
@@ -223,22 +221,6 @@ class HttpReadAloudService : BaseReadAloudService(),
return null return null
} }
@Synchronized
private fun playAudio(file: File) {
if (requestFocus()) {
launch {
kotlin.runCatching {
val mediaItem = MediaItem.fromUri(Uri.fromFile(file))
exoPlayer.setMediaItem(mediaItem)
exoPlayer.playWhenReady = true
exoPlayer.prepare()
}.onFailure {
it.printOnDebug()
}
}
}
}
private fun md5SpeakFileName(content: String): String { private fun md5SpeakFileName(content: String): String {
return MD5Utils.md5Encode16(textChapter?.title ?: "") + "_" + return MD5Utils.md5Encode16(textChapter?.title ?: "") + "_" +
MD5Utils.md5Encode16("${ReadAloud.httpTTS?.url}-|-$speechRate-|-$content") MD5Utils.md5Encode16("${ReadAloud.httpTTS?.url}-|-$speechRate-|-$content")
@@ -338,7 +320,7 @@ class HttpReadAloudService : BaseReadAloudService(),
downloadTask?.cancel() downloadTask?.cancel()
exoPlayer.stop() exoPlayer.stop()
speechRate = AppConfig.speechRatePlay + 5 speechRate = AppConfig.speechRatePlay + 5
downloadAudio() downloadAndPlayAudios()
} }
override fun onPlaybackStateChanged(playbackState: Int) { override fun onPlaybackStateChanged(playbackState: Int) {
@@ -347,15 +329,18 @@ class HttpReadAloudService : BaseReadAloudService(),
Player.STATE_IDLE -> { Player.STATE_IDLE -> {
// 空闲 // 空闲
} }
Player.STATE_BUFFERING -> { Player.STATE_BUFFERING -> {
// 缓冲中 // 缓冲中
} }
Player.STATE_READY -> { Player.STATE_READY -> {
// 准备好 // 准备好
if (pause) return if (pause) return
exoPlayer.play() exoPlayer.play()
upPlayPos() upPlayPos()
} }
Player.STATE_ENDED -> { Player.STATE_ENDED -> {
// 结束 // 结束
playErrorNo = 0 playErrorNo = 0
@@ -364,6 +349,12 @@ class HttpReadAloudService : BaseReadAloudService(),
} }
} }
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED) return
upPlayPos()
playNext()
}
override fun onPlayerError(error: PlaybackException) { override fun onPlayerError(error: PlaybackException) {
super.onPlayerError(error) super.onPlayerError(error)
AppLog.put("朗读错误\n${contentList[nowSpeak]}", error) AppLog.put("朗读错误\n${contentList[nowSpeak]}", error)