如何在UI中无重复拼接Twilio实时通话转录文本
解决Twilio增量通话转录的重复内容显示问题
Twilio流式语音识别返回的增量转录会包含重复前缀,核心原因是每次返回的是当前已识别的完整临时结果,而非纯新增片段。要实现无重复的UI显示,关键是区分「临时增量」和「最终确认」的转录内容,以下是具体方案:
核心思路
- 维护两个状态变量:
finalTranscript:存储已确认的完整语句(对应isFinal: true的识别结果)partialTranscript:存储当前正在识别的临时增量内容
- 利用Twilio返回结果中的
isFinal标记:- 当
isFinal为true时,说明这段转录已确认,将其合并到finalTranscript并清空临时内容 - 当
isFinal为false时,仅更新临时增量内容,用于实时显示用户正在说的内容
- 当
最佳实践
- 分开显示已确认文本和临时文本(比如已确认文本用常规样式,临时文本用浅灰色),提升用户体验
- 通过状态变量跟踪内容,避免直接拼接所有返回的转录文本,减少不必要的字符串操作
- 每轮对话确认结束(
isFinal: true)时,可添加换行或分隔符,让对话结构更清晰
代码示例
修改你的WebSocket回调代码,加入状态管理和去重逻辑:
// 初始化状态变量 let finalTranscript = ''; let partialTranscript = ''; ws.on("message", function incoming(message) { const msg = JSON.parse(message); switch (msg.event) { case "connected": console.log(`A new call has connected.`); break; case "start": recognizeStream = client .streamingRecognize(request) .on("error", console.error) .on("data", data => { // 遍历所有识别结果(处理多备选情况) data.results.forEach(result => { const transcript = result.alternatives[0].transcript; if (result.isFinal) { // 确认的转录:合并到最终文本,清空临时内容 finalTranscript += transcript + ' '; partialTranscript = ''; } else { // 临时增量:更新临时文本 partialTranscript = transcript; } // 更新UI:显示最终文本 + 临时文本 updateTranscriptUI(finalTranscript + partialTranscript); }); }); break; case "media": console.log(`Receiving Audio...`); break; case "stop": console.log(`Call Has Ended`); break; } }); // 示例UI更新函数 function updateTranscriptUI(text) { document.getElementById('transcript-display').textContent = text.trim(); }
额外优化
如果遇到isFinal标记延迟的场景,可通过字符串比对提取新增片段:
// 保存上一次的临时转录内容 let lastPartial = ''; // 在非isFinal的分支里: const newPartial = transcript; // 提取新增部分(假设新内容是旧内容的超集) const addedText = newPartial.slice(lastPartial.length); partialTranscript = newPartial; lastPartial = newPartial; // 可单独处理新增文本,比如追加到UI而非替换整个内容
内容的提问来源于stack exchange,提问作者amal m reji
相关产品推荐
相关产品推荐

