2026/2/10 18:05:28
网站建设
项目流程
北京市保障性住建设投资中心网站,苏州优秀网站设计公司,国外seo网站,安卓开发工具idea手机版开篇#xff1a;数字朗读的那些坑
做客服系统的朋友都懂#xff0c;最怕听到机器人把“您的余额为 12345.67 元”读成“一万二千三百四十五点六七”#xff0c;用户直接懵#xff1a;我到底还剩多少钱#xff1f;金融报数、快递电话、验证码播报#xff0c;场景不同数字朗读的那些坑做客服系统的朋友都懂最怕听到机器人把“您的余额为 12345.67 元”读成“一万二千三百四十五点六七”用户直接懵我到底还剩多少钱金融报数、快递电话、验证码播报场景不同数字读法却必须“像人”。ChatTTS 默认把连续数字当成整数处理结果“123”秒变“一百二十三”和“一二三”相差十万八千里。痛点总结一句话数字格式不对业务直接翻车。方案对比三选一怎么挑我先后试过三条路踩坑记录如下直接调 API最省事却最不可控。ChatTTS 内部规则黑盒数字读法随版本变今天“123”是“一二三”明天就可能变“一百二十三”。线上事故复盘时只能干瞪眼。正则替换自己先把“123”换成“一二三”再喂给 ChatTTS。可控、轻量半小时能跑通。缺点是正则写不严谨就错杀比如把“1号线”拆成“一号线”用户听着别扭。自定义发音词典把数字、单位、多音字全部写进词典ChatTTS 优先走词典 fallback 再走模型。前期工作量最大但一次到位后期基本不动。金融客户最认这条宁可多花两天排词典也不想上线后因为读错钱数被投诉。一句话总结原型阶段→直接调 API快速上线→正则替换长期运营→自定义词典核心代码从“123”到“一二三”下面给出可复用的 Python3.8 模块开箱即用。整体思路正则抓数字 → 转拼音 → 拼回文本 → 喂给 ChatTTS。# num2spell.py import re from typing import Dict, List _DIGIT_MAP: Dict[str, str] { 0: líng, 1: yī, 2: èr, 3: sān, 4: sì, 5: wǔ, 6: liù, 7: qī, 8: bā, 9: jiǔ } # 预编译正则O(n) 扫描 _RE_NUMBER re.compile(r\d(?:\.\d)?) # 匹配 123 或 123.45 def _digits2spell(match: re.Match) - str: 把纯数字串逐字转拼音保留小数点读‘点’ num: str match.group() return .join(_DIGIT_MAP[ch] if ch in _DIGIT_MAP else diǎn for ch in num) def preprocess(text: str) - str: 入口函数线程安全无全局状态 return _RE_NUMBER.sub(_digits2spell, text)与 ChatTTS 的集成示例官方 SDK 假设为chatttsimport chattts from num2spell import preprocess def tts_with_num(text: str, out_wav: str): clean preprocess(text) tts chattts.TTS() tts.t2w(clean, out_wav) # text-to-wave单元测试顺手写掉pytest 一把过# test_num2spell.py import pytest from num2spell import preprocess pytest.mark.parametrize(raw,exp, [ (验证码1234, 验证码 yī èr sān sì), (余额123.45元, 余额 yī èr sān diǒu sì wǔ 元), ]) def test_preprocess(raw, exp): assert preprocess(raw) exp时间复杂度正则一次扫描 O(n)n 为字符数空间复杂度输出新字符串 O(n)。百万级文本内存占用约 2 倍原串可接受。性能优化别让预处理拖垮延迟延迟预算实测 200 字符文本预处理 1 msChatTTS 本身 200 ms占比可忽略。但正则别写贪婪回溯一旦用(.\d)这类死亡模式CPU 直接飙升。大文本内存管理批量合成 10 MB 文稿时避免text text式拼接改用io.StringIO流式读写正则替换开启re.DEBUG观察回溯。若仍吃内存可切片分段每段 5 k 字符合成完立即落盘GC 及时回收。生产环境注意事项多音字陷阱“1月”读“yī yuè”没错但“第一名”要读“dì yī míng”。解决思路扩展正则先匹配“第\d名”“\d月”这类固定搭配命中就走专用函数不走通用 digit2spell。并发线程安全上面_RE_NUMBER.sub与_DIGIT_MAP都是只读无共享状态放心直接放 Web 框架线程池。若后续动态热更新词典加threading.RLock保护 reload 即可。错误重试ChatTTS 偶现网络 502外层包一层 tenacityfrom tenacity import retry, stop_after_attempt, wait_exponential retry(stopstop_after_attempt(3), waitwait_exponential(multiplier1, max10)) def safe_tts(text, out_wav): tts.t2w(text, out_wav)失败自动退避重试避免把瞬时错误抛给用户。开放讨论自然度 vs 准确性怎么选把“110”读成“yāo yāo líng”更口语却和“一百一十”冲突金融场景要求一字不差客服场景又希望越自然越好。你的业务会倾向哪一边或者有没有办法让模型自己学会“场景感知”先读准再读美欢迎留言聊聊。