pull/1814/head
kunfei 3 years ago
parent e99459e2e7
commit 8bdb3042da
  1. 181
      app/src/main/java/io/legado/app/service/HttpReadAloudService.kt

@ -43,6 +43,7 @@ class HttpReadAloudService : BaseReadAloudService(),
private val cacheFiles = hashSetOf<String>() private val cacheFiles = hashSetOf<String>()
private var downloadTask: Coroutine<*>? = null private var downloadTask: Coroutine<*>? = null
private var playIndexJob: Job? = null private var playIndexJob: Job? = null
private var downloadTaskIsActive = false
private var downloadErrorNo: Int = 0 private var downloadErrorNo: Int = 0
private var playErrorNo = 0 private var playErrorNo = 0
@ -103,104 +104,114 @@ class HttpReadAloudService : BaseReadAloudService(),
} }
private fun downloadAudio() { private fun downloadAudio() {
downloadTask?.cancel() launch {
downloadTask = execute { downloadTask?.cancel()
clearSpeakCache() while (downloadTaskIsActive) {
removeCacheFile() //在线tts大部分只能单线程,等待上次访问结束
val httpTts = ReadAloud.httpTTS ?: return@execute delay(100)
contentList.forEachIndexed { index, content -> }
ensureActive() downloadTask = execute {
val fileName = clearSpeakCache()
md5SpeakFileName(httpTts.url, speechRate.toString(), content) removeCacheFile()
val speakText = content.replace(AppPattern.notReadAloudRegex, "") val httpTts = ReadAloud.httpTTS ?: return@execute
if (hasSpeakFile(fileName)) { //已经下载好的语音缓存 contentList.forEachIndexed { index, content ->
if (index == nowSpeak) { ensureActive()
val file = getSpeakFileAsMd5(fileName) val fileName =
playAudio(file) md5SpeakFileName(httpTts.url, speechRate.toString(), content)
} val speakText = content.replace(AppPattern.notReadAloudRegex, "")
} else if (hasSpeakCache(fileName)) { //缓存文件还在,可能还没下载完 if (hasSpeakFile(fileName)) { //已经下载好的语音缓存
return@forEachIndexed if (index == nowSpeak) {
} else if (speakText.isEmpty()) { val file = getSpeakFileAsMd5(fileName)
createSilentSound(fileName) playAudio(file)
return@forEachIndexed
} else {
runCatching {
createSpeakCache(fileName)
val analyzeUrl = AnalyzeUrl(
httpTts.url,
speakText = speakText,
speakSpeed = speechRate,
source = httpTts,
headerMapF = httpTts.getHeaderMap(true)
)
var response = analyzeUrl.getResponseAwait()
ensureActive()
httpTts.loginCheckJs?.takeIf { checkJs ->
checkJs.isNotBlank()
}?.let { checkJs ->
response = analyzeUrl.evalJS(checkJs, response) as Response
} }
httpTts.contentType?.takeIf { ct -> } else if (hasSpeakCache(fileName)) { //缓存文件还在,可能还没下载完
ct.isNotBlank() return@forEachIndexed
}?.let { ct -> } else if (speakText.isEmpty()) {
response.headers["Content-Type"]?.let { contentType -> createSilentSound(fileName)
if (!contentType.matches(ct.toRegex())) { return@forEachIndexed
throw NoStackTraceException(response.body!!.string()) } else {
} runCatching {
createSpeakCache(fileName)
val analyzeUrl = AnalyzeUrl(
httpTts.url,
speakText = speakText,
speakSpeed = speechRate,
source = httpTts,
headerMapF = httpTts.getHeaderMap(true)
)
var response = analyzeUrl.getResponseAwait()
ensureActive()
httpTts.loginCheckJs?.takeIf { checkJs ->
checkJs.isNotBlank()
}?.let { checkJs ->
response = analyzeUrl.evalJS(checkJs, response) as Response
} }
} httpTts.contentType?.takeIf { ct ->
ensureActive() ct.isNotBlank()
response.body!!.bytes().let { bytes -> }?.let { ct ->
val file = createSpeakFileAsMd5IfNotExist(fileName) response.headers["Content-Type"]?.let { contentType ->
file.writeBytes(bytes) if (!contentType.matches(ct.toRegex())) {
removeSpeakCache(fileName) throw NoStackTraceException(response.body!!.string())
if (index == nowSpeak) { }
playAudio(file) }
} }
} ensureActive()
downloadErrorNo = 0 response.body!!.bytes().let { bytes ->
}.onFailure { val file = createSpeakFileAsMd5IfNotExist(fileName)
when (it) { file.writeBytes(bytes)
is CancellationException -> removeSpeakCache(fileName)
is ConcurrentException -> {
removeSpeakCache(fileName) removeSpeakCache(fileName)
delay(it.waitTime.toLong()) if (index == nowSpeak) {
downloadAudio() playAudio(file)
} }
is ScriptException, is WrappedException -> {
AppLog.put("js错误\n${it.localizedMessage}", it)
toastOnUi("js错误\n${it.localizedMessage}")
it.printOnDebug()
cancel()
pauseReadAloud(true)
} }
is SocketTimeoutException, is ConnectException -> { downloadErrorNo = 0
removeSpeakCache(fileName) }.onFailure {
downloadErrorNo++ when (it) {
if (downloadErrorNo > 5) { is CancellationException -> removeSpeakCache(fileName)
val msg = "tts超时或连接错误超过5次\n${it.localizedMessage}" is ConcurrentException -> {
AppLog.put(msg, it) removeSpeakCache(fileName)
toastOnUi(msg) delay(it.waitTime.toLong())
pauseReadAloud(true)
} else {
downloadAudio() downloadAudio()
} }
} is ScriptException, is WrappedException -> {
else -> { AppLog.put("js错误\n${it.localizedMessage}", it)
removeSpeakCache(fileName) toastOnUi("js错误\n${it.localizedMessage}")
downloadErrorNo++ it.printOnDebug()
val msg = "tts下载错误\n${it.localizedMessage}" cancel()
AppLog.put(msg, it)
it.printOnDebug()
if (downloadErrorNo > 5) {
pauseReadAloud(true) pauseReadAloud(true)
} else { }
createSilentSound(fileName) is SocketTimeoutException, is ConnectException -> {
removeSpeakCache(fileName)
downloadErrorNo++
if (downloadErrorNo > 5) {
val msg = "tts超时或连接错误超过5次\n${it.localizedMessage}"
AppLog.put(msg, it)
toastOnUi(msg)
pauseReadAloud(true)
} else {
downloadAudio()
}
}
else -> {
removeSpeakCache(fileName)
downloadErrorNo++
val msg = "tts下载错误\n${it.localizedMessage}"
AppLog.put(msg, it)
it.printOnDebug()
if (downloadErrorNo > 5) {
pauseReadAloud(true)
} else {
createSilentSound(fileName)
}
} }
} }
} }
} }
} }
}.onStart {
downloadTaskIsActive = true
}.onFinally {
downloadTaskIsActive = false
} }
} }
} }

Loading…
Cancel
Save