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