fix(chat): TTS 朗读净化——不念 Markdown/英文标点/表情符号(中文停顿标点保留做自然停顿)

This commit is contained in:
xsl
2026-09-11 23:45:15 +08:00
parent aafacbf020
commit 9161a2013c
@@ -8,6 +8,8 @@
* - 不依赖 queueMode:官方 API 文档(0=flush)与 Codelabs(0=排队)说法
* 互相矛盾,新朗读前显式 engine.stop() 打断,语义自持
* - 播报状态回调 onStateChanged:页面据此复位 🔊 图标
* - V3:speak 前 sanitizeForSpeech 净化——不念 Markdown/英文标点/表情符号
* (中文停顿标点保留做自然停顿)
*
* 模型:offline 中文引擎(online: 1,系统内置);模拟器通常无此服务,须真机。
* 日志 tag MEIDA_TTS:hdc shell hilog | grep MEIDA_TTS
@@ -18,6 +20,18 @@ import { textToSpeech } from '@kit.CoreSpeechKit'
const SEGMENT_MAX_CHARS: number = 400
const SEGMENT_FALLBACK_MS: number = 150000
/**
* 朗读净化(V3):剥掉会被引擎念出来的符号——Markdown 标记(**、#、- 列表符)、
* 英文标点、表情等,只留中英文、数字与中文停顿标点(,。;:!?、……靠它们做自然停顿,
* 引擎不会逐字念)。顾问回答被要求不写 Markdown(agent_chat v1),这里是双保险。
*/
function sanitizeForSpeech(text: string): string {
return text
.replace(/[^一-龥a-zA-Z0-9\s。,、;:!?]/g, ' ')
.replace(/\s+/g, ' ')
.trim()
}
/** 播报状态变化回调(speaking=false 表示本轮朗读完全结束或被停止)。 */
export type TtsStateChanged = (speaking: boolean) => void
@@ -78,7 +92,7 @@ export class TtsEngine {
* 由调用方决定是否提示(自动朗读静默、手动点击提示)。
*/
async speak(text: string): Promise<void> {
const trimmed: string = text.trim()
const trimmed: string = sanitizeForSpeech(text)
if (trimmed.length === 0) {
return
}