语音合成技术发展到今天,发音的准确率已经不是主要瓶颈,真正拉开体验差距的是节奏感。真人朗读时会自然地换气、犹豫、强调前留白,而机器默认只会机械地按句切分。想让 TTS 输出的声音有呼吸感,就必须学会主动控制停顿。本文介绍几种在文本中插入停顿控制符号的实用方法,重点是 SSML 的 <break> 标签,同时也会覆盖不支持 SSML 场景下的替代手段。

为什么需要显式控制停顿
大多数 TTS 引擎会根据标点符号自动决定停顿时长,大致规律是:顿号约 150 毫秒,逗号约 300 毫秒,句号约 600 毫秒,段落约 1 秒。这个规则在朗读新闻时基本够用,但遇到以下场景就会露怯。
第一是列举场景。比如朗读「本课程包含三个模块,分别是基础语法、实战演练和项目复盘」,引擎会在顿号处快速带过,听感上三个并列项挤在一起,用户还没反应过来就过去了。第二是强调场景,重点内容前留半秒空白,听众的注意力会被自然吸引过去,这是广播播音员常用的技巧。第三是长句换气,超过 30 字的句子中间没有停顿点,合成出来的语音会越读越赶,甚至出现吞字。
显式停顿还有一个容易被忽视的用途:留出交互时间。在语音应答系统里,说完「请稍等」之后插入一段静音,正好可以掩盖后台查询的耗时,用户感知上系统是在思考而不是卡死。
SSML break 标签:标准停顿控制方案
SSML(Speech Synthesis Markup Language)是 W3C 制定的语音合成标记语言,几乎所有主流引擎都支持。控制停顿靠的是 <break> 标签,它有两个属性可以指定停顿方式。
用 time 属性精确指定时长
time 属性直接给出停顿的毫秒数或秒数,精度高、可预测,适合需要精确对齐时间的场景,比如配音、提示音生成。常见取值在 100ms 到 5000ms 之间,部分引擎对上限有限制,例如 Azure 支持最长 5000ms,超出会被拒绝或截断。
<speak> 会议将于明天上午十点开始<break time="500ms"/>, 请各位提前进入会议室。 </speak>
上面这段 SSML 会在「开始」之后强制插入 500 毫秒静音,比默认逗号停顿更明显。需要注意的是,<break> 自带闭合斜杠,写成 <break></break> 虽然部分引擎容忍,但标准写法是自闭合。
用 strength 属性语义化控制
如果不想纠结具体毫秒数,可以用 strength 属性表达停顿强度,可选值包括 none、x-weak、weak、medium、strong 和 x-strong。引擎会根据自身的韵律模型把强度映射为实际时长,好处是与音色、语速自适应:当用户把语速调快时,strong 停顿也会相应缩短,整体节奏保持协调。
<speak> 前方到站<break strength="weak"/>人民广场<break strength="strong"/>请下车的乘客提前做好准备。 </speak>
一般建议优先用 strength,只有在需要精确时长的场合才用 time。两者不要同时写在同一个标签里,规范虽然允许并用,但实际各引擎处理不一致,容易产生不可预期的效果。
不支持 SSML 时的替代方案
并不是所有 TTS 接口都开放了 SSML,不少在线 API 或移动端 SDK 只接受纯文本。这时候可以通过字符技巧模拟停顿,效果虽然粗颗粒,但聊胜于无。
最直接的手段是堆叠标点。连续使用逗号(如「今天天气不错,,,我们出去走走」)在多数引擎里会叠加停顿时长;省略号「……」通常会产生一个比句号更长的停顿,且自带拖长音效果,适合表达迟疑;空行或换行符在部分引擎中会被当作段落边界,产生接近 1 秒的停顿。不同引擎对同一字符的解析差异很大,上线前务必用目标引擎实测。
另一个思路是插入静音音频片段。如果播放流程由自己控制,可以在合成音频上叠加静音 WAV,或者用音频处理库在指定位置插入空白帧。这种方式完全不依赖引擎能力,缺点是需要知道准确的插入位置,只能按字数或标点位置估算,适合列表朗读这类结构固定的内容。
各平台支持差异与调用示例
主流云厂商对 <break> 的支持程度并不相同,接入前建议先查文档确认。下表是常见平台的对比情况。
| 平台 | SSML 支持 | break 说明 |
|---|---|---|
| Azure Speech | 完整支持 | time 最长 5000ms,strength 全部取值可用 |
| Google Cloud TTS | 完整支持 | time 上限约 10s,部分音色对 strength 支持有限 |
| Amazon Polly | 完整支持 | time 最长 10s,strength 建议只用 medium 以上 |
| 讯飞在线合成 | 部分支持 | 需使用特定标签版本,break 属性集较精简 |
以 Python 调用 Azure 为例,把 SSML 直接塞进请求体即可:
import azure.cognitiveservices.speech as speechsdk speech_config = speechsdk.SpeechConfig(subscription="你的密钥", region="eastasia") synthesizer = speechsdk.SpeechSynthesizer(speech_config=speech_config) ssml = """ <speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="zh-CN"> 感谢您的来电<break time="800ms"/>您的工单已受理<break strength="strong"/>请记录受理编号。 </speak> """ result = synthesizer.speak_ssml_async(ssml).get() print(result.reason)
写 SSML 时有两个易错点值得提醒。一是转义问题:SSML 本身是 XML,文本中出现 <、& 这类字符必须转义,否则整个请求会报 XML 解析错误;二是中文引擎里 <break> 与标点叠加时,实际停顿时长可能超过两者之和,因为部分引擎会取标点停顿与显式停顿的最大值而非求和,做时间轴对齐时要留出余量。
实战建议与调优思路
停顿不是越多越好。测试下来一个比较实用的经验值是:正文段落之间 600 到 800 毫秒,列举项之间 300 毫秒左右,强调前 500 毫秒。超过 1 秒的停顿在没有视觉配合的纯音频场景里,容易让用户误以为播放中断。
调优时建议建立一套停顿标注规范,把「强停顿、中停顿、弱停顿」定义成固定标签或固定时长,让所有文案生产者统一使用。这样不仅合成效果稳定,后续更换 TTS 引擎时只需调整一处映射配置,而不必逐篇修改文本。
最后,停顿控制最好和语速、音调配合使用。同一个 500 毫秒的停顿,在慢速温柔的音色里显得从容,在快速播报的音色里就显得突兀。把停顿时长看作整体节奏的一部分去调试,而不是孤立地插入静音,才能让合成语音真正接近真人朗读的呼吸感。
TTS停顿控制SSML break语音合成修改时间:2026-09-06 05:30:40