Android语音识别单词拆分匹配异常的解决方案咨询
问题场景与遇到的问题
我在Android中实现语音识别功能,流程如下:将一段文本显示在TextView中,先把文本按空格拆分为单词列表;通过onPartialResult获取用户语音输入的逐步结果,格式示例:
[I]
[I am]
[I am android]
[I am android user]
当前逻辑是:把语音输入内容按空格拆分后取最后一个单词,用全局索引和段落单词列表匹配,匹配成功就用Spannable给该单词设置绿色高亮。
但遇到了问题:像“carefree”这类单词经常被识别成“care free”两个词,导致匹配逻辑失效。偶尔能识别成单个单词,但多数情况拆分错误。我有初步的拼接验证思路,但不够合理,想了解处理这类问题的算法或库,找可行的检测与匹配方案。
当前使用的代码
private void applyColor(String param){ ArrayList<String> params = paraToArray(param); // 只取输入内容的最后一个单词 String newWord = params.get(params.size()-1); // 通过全局索引获取段落中的当前目标单词 String currentWord_FromParagraph = paragraphWords.get(indexHistory); // 处理带's的单词 if(currentWord_FromParagraph.contains("'s")){ String rootWord = currentWord_FromParagraph.replaceAll("'s\\b", ""); newWord = rootWord+"'s"; } // 获取单词在段落中的起始位置 int start = paragraph.indexOf(newWord, indexHistoryChar); int end = newWord.length(); // 匹配判断 if(start != -1 && newWord.equalsIgnoreCase(currentWord_FromParagraph) ){ // 给匹配到的单词设置绿色高亮 spannableString.setSpan(new ForegroundColorSpan(Color.GREEN), start, start+end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // 更新全局单词索引,匹配成功后指向段落的下一个单词 indexHistory++; // 更新全局字符索引,记录当前高亮结束的位置 indexHistoryChar = start+end; spannableString.setSpan(new ForegroundColorSpan(Color.WHITE), startNext, endNext, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } txtv_paragraph.setText(spannableString); }
可行的解决方案
1. 基于词典的拼接校验
- 维护一个常用英语单词词典(可以复用Android系统内置词典,或者导入开源的单词库)
- 当语音识别出连续短单词时,尝试将它们拼接成一个完整单词,去词典中查询是否存在:
比如识别到“care free”,拼接成“carefree”,如果词典里存在这个词,就优先用拼接后的结果匹配段落单词 - 实现思路:在处理语音部分结果时,检查最后1-2个单词,尝试拼接后验证有效性,若有效则替换拆分的单词
2. 模糊匹配与编辑距离算法
- 使用**编辑距离(Levenshtein Distance)**计算语音识别结果(或拼接后的组合)与段落目标单词的相似度
- 设定阈值(比如编辑距离≤2),当相似度足够高时判定匹配成功
- 示例逻辑:
// 计算两个字符串的编辑距离 private int calculateLevenshteinDistance(String s1, String s2) { int[][] dp = new int[s1.length()+1][s2.length()+1]; for(int i=0; i<=s1.length(); i++) dp[i][0] = i; for(int j=0; j<=s2.length(); j++) dp[0][j] = j; for(int i=1; i<=s1.length(); i++){ for(int j=1; j<=s2.length(); j++){ int cost = s1.charAt(i-1) == s2.charAt(j-1) ? 0 : 1; dp[i][j] = Math.min(Math.min(dp[i-1][j]+1, dp[i][j-1]+1), dp[i-1][j-1]+cost); } } return dp[s1.length()][s2.length()]; } // 在匹配逻辑中添加模糊校验 String targetWord = paragraphWords.get(indexHistory); // 先尝试精确匹配 if(newWord.equalsIgnoreCase(targetWord)){ // 原高亮逻辑 } else { // 尝试拼接前一个单词和当前单词 if(params.size() >=2){ String combinedWord = params.get(params.size()-2) + params.get(params.size()-1); if(calculateLevenshteinDistance(combinedWord.toLowerCase(), targetWord.toLowerCase()) <= 2){ // 匹配成功,用段落中的原单词做高亮 int start = paragraph.indexOf(targetWord, indexHistoryChar); spannableString.setSpan(new ForegroundColorSpan(Color.GREEN), start, start+targetWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); indexHistory++; indexHistoryChar = start + targetWord.length(); } } }
3. 利用语音识别置信度优化
- 部分语音识别API会返回每个单词的置信度得分
- 如果连续两个单词的置信度都偏低,就尝试将它们拼接成一个词,再验证是否匹配段落目标单词
- 比如Google Speech API的
RecognitionResult包含confidence字段,可据此判断是否需要触发拼接校验
4. 预生成段落单词的备选形式
- 提前给段落中的单词生成备选拆分形式:比如给“carefree”添加“care free”作为备选
- 匹配时同时检查语音输入的单词组合是否匹配备选形式
- 示例:维护一个
Map<String, List<String>> wordAlternatives,key是段落原单词,value是可能的拆分形式列表,匹配时遍历列表做校验
内容的提问来源于stack exchange,提问作者CrackerKSR
相关产品推荐
相关产品推荐

