# 文本拼接算法详解 ## 概述 [`merge_by_text`](../util/server/text_merge.py) 是 CapsWriter-Offline 中用于解决**语音切片重叠去重**的核心算法,采用**模糊文本匹配**策略,具有高鲁棒性和抗噪音能力。 ## 问题背景 在流式语音识别中,音频被切片处理(如 25 秒一段,2 秒重叠),导致同一内容在相邻片段中重复出现: ``` 片段 1: "...今天天气真" 片段 2: "天气真好啊..." ↑ ↑ 重叠部分(需要去重) ``` ## 核心思想 算法在**前一段文本的末尾**和**新文本的开头**之间寻找最长公共部分,以此为界进行智能拼接。不同于简单的尾部匹配,该算法采用窗口搜索策略,能够在末尾区域内灵活定位最佳拼接点。 ### 三大设计原则 1. **从长到短匹配**: 优先匹配更长的文本片段,因为长匹配更可靠 2. **允许噪音跳过**: 新文本开头可能有截断噪音(如口语"嗯"、"啊"),允许跳过这些字符 3. **精确→模糊→兜底**: 三层容错机制,确保在各种情况下都能找到合理拼接点 ## 算法流程 ``` 输入: prev_text = "今天天气真" + new_text = "嗯天气真好啊" 步骤 1: 预处理 └─> 去掉两端标点符号,保留有效文本 步骤 2: 确定搜索窗口 └─> 在 prev_text 末尾 20 字内查找(非全文本搜索) 步骤 3: 智能匹配(两阶段) ├─> 阶段一:精确匹配 │ ├─ 从长到短尝试匹配 │ ├─ 允许跳过 new_text 开头噪音 │ └─ 反向查找(优先靠近尾部的匹配) │ └─> 阶段二:模糊匹配(容错 3 字) ├─ 处理同音字、识别错误 └─ 匹配长度必须 > 容错数(避免误匹配) 步骤 4: 执行拼接 ├─> 找到重叠 "天气" ├─> 丢弃 prev_text 尾部可能的漂移噪音 ├─> 跳过 new_text 开头的噪音 └─> 结果: "今天天气真好啊" 步骤 5: 兜底逻辑 └─> 未找到匹配时,直接拼接 ``` ## 典型场景与效果 ### 场景 1: 完美重叠 ``` 输入: "今天天气真" + "天气真好啊" 匹配: "天气"(精确匹配) 结果: "今天天气真好啊" ``` ### 场景 2: 开头有口语噪音 ``` 输入: "今天天气真" + "嗯天气真好啊" 匹配: 跳过 1 字噪音,匹配 "天气" 结果: "今天天气真好啊" ``` ### 场景 3: 识别错误(同音字) ``` 输入: "今天天气真" + "天起真好啊" ("气"识别成"起") 匹配: 模糊匹配,容错 1 字 结果: "今天天真好啊"(可能残留,交给下游 LLM 润色) ``` ### 场景 4: 尾部漂移 ``` 输入: "今天天气真的" + "好的天气真好啊" 匹配: "天气"(丢弃 prev 的 "真的",丢弃 new 的 "好的") 结果: "今天天气真好啊" ``` ## 核心优势 1. **鲁棒性强**: 精确→模糊→兜底三层容错,应对各种识别异常 2. **抗噪音能力**: 处理开头截断、尾部漂移、口语噪音、识别错误 3. **高性能**: 窗口搜索 + 反向查找,避免全文本扫描 4. **智能拼接**: 不强制必须在绝对末尾匹配,灵活定位最佳拼接点 ## 配置参数 在 [`util/constants.py`](../util/constants.py) 中定义: - **`OVERLAP_CHARS = 20`**: 搜索窗口大小(prev_text 末尾字符数) - **`ERROR_TOLERANCE = 3`**: 容错字符数(模糊匹配时允许的最大误差) ## 实际应用 该算法用于生成 `text` 字段(简单文本拼接),相比基于时间戳的精确拼接,具有更强的容错能力,适合作为**鲁棒输出**使用。 ## 总结 `merge_by_text` 通过窗口搜索、分层匹配、智能去重的设计,有效解决了语音切片重叠问题。在实际使用中,能够处理大部分常见的识别异常,是 CapsWriter-Offline 实现流畅语音识别体验的关键技术之一。