分类
自然语言处理

利用语音合成标记语言(SSML)优化语音合成质量

语音合成标记语言(Speech Synthesis Markup Language,SSML)是用于控制语音合成中停顿、音量、音调、语速以及名词读法等因素的标记语言。这个由万维网联盟(W3C)以 XML 为基础进行标准化的语言受到许多在线语音合成服务的广泛支持:包括 Google Cloud、AWS、阿里云等服务商均提供了支持 SSML 的语音合成服务。相较以纯文本进行的文本到语音转换(TTS)任务,利用 SSML 能够更细粒度地控制语音的合成方式,从而优化语音合成质量。

SSML 标准(最新为 1.1 版本)中定义了一系列用于控制语音合成方式的标记,这些标记类似于 HTML 与 XML,能够细粒度地控制语音的合成方式。一个简单的示例是:

<speak>
<p><s><say-as interpret-as="characters">12345</say-as>,<emphasis level="moderate">大家注意听了:</emphasis><break time="200ms"/></s>
<s><prosody rate="90%" pitch="+3st" volume="110%">我能吞下玻璃而不伤害身体。</prosody></s></p>
</speak>

大多数云服务商提供的在线语音合成服务实现了 W3 标准中的一个子集,上述示例中展示的标记是这些语音合成服务广泛支持的一些功能。这些功能包括描述文本构造类型的 <say-as> 标签、控制文本读法与强调的 <emphasis><prosody> 标签,以及划分文章中段落的 <p><s> 标签等。Google Text-To-Speech 页面提供了一个交互式的演示器,以便于测试你编写的 SSML 代码的效果。

基本结构

我们从最简单的开始:SSML 将要读出的内容放置于 <speak> 标签中,将纯文本转换为 SSML 格式的最快方式是使用 <speak> 标签对将其包裹。

纯文本SSML
我能吞下玻璃而不伤害身体<speak>我能吞下玻璃而不伤害身体</speak>
很明显,“5>3”<speak>很明显,“5&gt;3”</speak>
嘿!是的,你已经学会了<speak>嘿!是的,你已经学会了</speak>
在 Google Text-To-Speech 的交互式测试页面试一试

分段与分句

SSML 使用 <p><s> 标签实现分段与分句功能。在传统的以纯文本进行的语音合成任务中,文本分析器通过自动化的规则推断每段或每句文字的边界,并插入适当的空白。但如果自动推断的停顿风格不是你想要的,则可以手动通过这些标签指定文本边界:

<speak>
  <p>
    <s>这是本段的第一句话。</s>
    <s>这是另一句。</s>
  </p>
</speak>

在部分实现中,以 <p> 标签划分的段落相当于一个 strength="x-strong"<break> 标签带来的停顿;同样地,以 <s> 标签划分的句子相当于一个 strength="strong"<break> 标签的停顿。

停顿

如果在音频中需要显式声明停顿,则使用 <break> 标签,该标签用于控制停顿或其他韵律学上的词汇边界。该标签有两个属性:

  • strength[可选]:以“none”、“x-weak”、“weak”、“medium”(默认值)、“strong”与“x-strong”标记的停顿强度;例如 none 值表示在合成语音中不包含任何韵律学上的停顿
  • time:停顿时长,遵循以 CSS2 为标准的时间记法,如“3s”、“200ms”
嘘<break time="1000ms"/>别出声<break time="1.5s"/>你听见了吗

如果 SSML 中出现不含有上述任何一个属性的 <break> 标签,则标准中规定语音合成器应当以比起没有该标签时更长的时间做出停顿。time 属性的优先级比 strength 要高,因为其更加精确。

音调、音量与语速

着重强调

<emphasis> 标签用于标记一个着重语气。可选的 level 属性支持从“strong”、“moderate”,“none”到“reduced”的取值。其中,strongmoderate 分别表示两种不同的句子强调程度,具体的合成风格由语音合成器的实现决定;none 告知语音合成器避免此处自动推定的强调;而 reduced 值则表示减弱语气:

<emphasis level="strong">重要通知</emphasis>

高级控制

要控制音调、说话速率以及合成音量,需要使用 <prosody> 标签。该标签提供的属性有:

  • pitch:读出文本的音高,尽管对于“基础音高”的定义依不同语音合成器的变化而异,但通过该属性通常能够调整音高效果。可能的取值为:以 Hz 为单位的值,或者“x-low”、“low”、“medium”、“high”、“x-high”或者“default”;从 x-lowx-high 代表了一个音高的非递减序列
  • volume:读出文本的音量。可能的取值是一个百分比(%)值,或者下列取值之一:“silent”、“x-soft”、“soft”、“medium”、“loud”、“x-loud”或者“default”;默认值 default 代表 +0.0dB;而值 silent 代表 -∞dB;也可以使用一个类似 ±x dB 的值,代表指定的音量与目前默认音量之间的分贝关系。
他走过来悄悄跟我说:<prosody pitch="x-low" rate="80%">“别让别人看见”</prosody>

另外,在 W3C 标准中还规定了该标签的额外属性 rangeduration,如需详细了解 <prosody> 元素,请参阅 W3 规范

指定文本构型

SSML 提供了一系列能够描述文本构造类型的机制,便于控制指定文本块的语音合成方法。

替换读法

<sub> 标签用于在语音合成时使用 alias 属性值中的文本替换所包含的文本:

<sub alias="超文本传输协议">HTTP</sub>在互联网中已经有许多年历史。

实践中,通常使用 <sub> 标签为难读文本指定其简化发音,如 Google Text-To-Speech 文档中提供的下列示例:

<sub alias="にっぽんばし">日本橋</sub>

字面量的读出方式

除了 <sub> 标签以外,标准中为了解决数字、序号、日期以及货币等的不同朗读方式问题,提供了 <say-as> 标签供用户指明元素中包含的文本构造类型的相关信息。

<say‑as> 元素具有必要属性 interpret-as,它决定值的读出方式。可以根据特定的 interpret-as 值选用属性 formatdetail。根据选用的语音合成服务商不同,其支持的 interpret-as 值可能也存在差异,具体请参见具体服务的文档。

cardinal – 直接读出数字

以下示例读作“Twelve thousand three hundred forty five”(美式英语)或“Twelve thousand three hundred and forty five”(英式英语):

<speak>
  <say-as interpret-as="cardinal">12345</say-as>
</speak>

针对中文语音合成,将会以“读出”该数字的方式合成语音,即:“一万两千三百四十五”。

ordinal – 读出序号

以下示例读作“First”:

<speak>
  <say-as interpret-as="ordinal">1</say-as>
</speak>

verbatim – 逐个读出字母

以下示例指定这些数字和字母是被逐个读出的:

<speak>
  车牌是<say-as interpret-as="verbatim">京A00003</say-as>
</speak>

telephone – 号码读法

下述示例读作“幺三零一二三四五六七八”:

<speak>
  我的手机号是<say-as interpret-as="telephone">13012345678</say-as>。
</speak>

致谢

感谢 Taotie Languages。