WebView传递大段SRT文本至谷歌翻译报错,寻求解决方案
解决WebView传递大SRT字符串到Google翻译的请求过大问题
问题根源
你遇到的报错核心原因是GET请求的URL长度存在浏览器/服务器限制,把完整SRT文本塞进URL的text参数时,超出了允许的最大长度,导致请求被拦截或失败。以下是几个实用的解决方案:
方案1:分块处理SRT内容
将SRT拆分为独立的字幕块(每个块包含序号、时间轴、字幕文本),仅翻译每个块中的文本部分,最后重新拼接成完整的SRT文件。这种方式既规避了超长URL,又能保证字幕结构不被破坏。
实现步骤:
- 解析SRT为字幕块:
data class SubtitleBlock(val index: String, val timestamp: String, val text: String) fun parseSrt(srtContent: String): List<SubtitleBlock> { val blocks = mutableListOf<SubtitleBlock>() val lines = srtContent.split("\n") var i = 0 while (i < lines.size) { val index = lines[i].trim() if (index.isEmpty()) { i++ continue } val timestamp = lines[i+1].trim() val textBuilder = StringBuilder() i +=2 while (i < lines.size && lines[i].trim().isNotEmpty()) { textBuilder.append(lines[i].trim()).append("\n") i++ } blocks.add(SubtitleBlock(index, timestamp, textBuilder.toString().trim())) i++ } return blocks }
- 批量翻译并重组:
循环调用翻译逻辑处理每个块的文本,完成后拼接回完整SRT:
fun translateSrtBlocks(blocks: List<SubtitleBlock>, from: String, into: String, webView: WebView, onComplete: (String) -> Unit) { val translatedBlocks = mutableListOf<SubtitleBlock>() var currentIndex = 0 fun translateNextBlock() { if (currentIndex >= blocks.size) { val resultSrt = translatedBlocks.joinToString("\n\n") { "${it.index}\n${it.timestamp}\n${it.text}" } onComplete(resultSrt) return } val block = blocks[currentIndex] setupWebView(block.text, from, into, webView) { translatedText -> translatedBlocks.add(block.copy(text = translatedText)) currentIndex++ translateNextBlock() } } translateNextBlock() }
方案2:改用POST请求提交文本
Google翻译支持通过POST方式提交待翻译文本,完全避开GET请求的URL长度限制。你可以在WebView中加载一个本地HTML表单,通过JavaScript自动提交POST请求。
修改后的setupWebView函数:
fun setupWebViewPost( input: String, from: String, into: String, webView: WebView, resultHandler: (String) -> Unit ) { webView.settings.javaScriptEnabled = true webView.addJavascriptInterface(JsInterface, "JsInterface") JsInterface.setResultCallback { resultHandler(it) } // 构造POST表单的HTML内容 val html = """ <html> <body> <form id="translateForm" action="https://translate.google.com/?sl=$from&tl=$into&op=translate" method="POST"> <textarea name="text" style="display:none">$input</textarea> </form> <script> document.getElementById('translateForm').submit(); </script> </body> </html> """.trimIndent() webView.loadDataWithBaseURL("https://translate.google.com/", html, "text/html", "UTF-8", null) webView.webViewClient = object : WebViewClient() { override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) view?.postDelayed({ injectJavascript(view) // 保留你原有的注入JS提取结果的逻辑 }, 2000) // 根据内容大小灵活调整延迟时间 } } }
方案3:过滤无需翻译的内容
SRT文件中的序号(如1、2)和时间轴(如00:00:01,000 --> 00:00:03,000)不需要翻译,可先剥离这些内容,仅发送纯字幕文本,翻译完成后再重新拼接。
示例代码:
fun extractTextFromSrt(srtContent: String): Pair<List<String>, List<String>> { val nonTranslatableParts = mutableListOf<String>() val translatableTexts = mutableListOf<String>() val lines = srtContent.split("\n") var i = 0 while (i < lines.size) { val index = lines[i].trim() if (index.isEmpty()) { i++ continue } val timestamp = lines[i+1].trim() nonTranslatableParts.add("$index\n$timestamp") val textBuilder = StringBuilder() i +=2 while (i < lines.size && lines[i].trim().isNotEmpty()) { textBuilder.append(lines[i].trim()).append("\n") i++ } translatableTexts.add(textBuilder.toString().trim()) i++ } return Pair(nonTranslatableParts, translatableTexts) } // 翻译后重新拼接成完整SRT fun reconstructSrt(nonTranslatable: List<String>, translatedTexts: List<String>): String { return nonTranslatable.zip(translatedTexts).joinToString("\n\n") { "${it.first}\n${it.second}" } }
额外优化建议
- 动态调整
postDelayed延迟:避免固定1秒等待,可根据文本长度设置更长的延迟,确保翻译结果完全加载。 - 增加重试机制:如果某块翻译失败,自动重试1-2次,提升整体稳定性。
内容的提问来源于stack exchange,提问作者Roony
相关产品推荐
相关产品推荐

