You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:48:16