SSML 与韵律控制
语音合成标记语言:停顿、重音、语速和音高。
SSML 与韵律控制 是 CoddyKit 上的免费 AI Prompt Engineering 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 AI Prompt Engineering 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 AI Prompt Engineering 课程共包含 4 节课。
什么是 SSML
SSML(语音合成标记语言)是一种基于 XML 的语言,可以让您细致控制文本转语音引擎朗读文本的方式。Google Cloud TTS、Amazon Polly、Microsoft Azure TTS 以及许多其他服务都支持它。
纯文本只能提供词语本身,而 SSML 可以让您控制停顿、重音、速度、音调、发音等内容。
SSML 的基本结构
所有 SSML 文档都包裹在 <speak> 标签中。在其中,您可以将纯文本与 SSML 标记元素混合使用。TTS 引擎会处理 SSML,并据此生成音频。
# SSML document structure
SSML_BASIC = """
<speak>
Welcome to the course.
<break time="500ms"/>
Today we will cover three topics.
First, we will discuss SSML basics.
<break time="300ms"/>
Second, we will explore prosody control.
<break time="300ms"/>
And third, we will look at advanced features.
</speak>
"""
# Send to Google Cloud TTS
from google.cloud import texttospeech
client_tts = texttospeech.TextToSpeechClient()
input_text = texttospeech.SynthesisInput(ssml=SSML_BASIC)
voice = texttospeech.VoiceSelectionParams(
language_code='en-US',
ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL
)
audio_config = texttospeech.AudioConfig(
audio_encoding=texttospeech.AudioEncoding.MP3
)
print('SSML document ready to synthesize')break 元素
<break> 会在语音中插入停顿。您可以使用它来创造自然节奏、分隔列表项或增加戏剧效果。time 属性接受毫秒(ms)或秒(s)。
# break element examples
BREAK_EXAMPLES = """
<speak>
Are you ready?
<break time="1s"/>
Let us begin.
The three rules are:
number one,
<break time="300ms"/>
always test your code.
<break time="200ms"/>
Number two,
<break time="300ms"/>
write clear documentation.
<break time="200ms"/>
And number three,
<break time="300ms"/>
review before you ship.
<break strength="x-strong"/>
That is all for today.
</speak>
"""
# break strength values: none, x-weak, weak, medium, strong, x-strong
# These map to approximate pause durations defined by the engine
print('break time: explicit duration (e.g. 500ms)')
print('break strength: semantic pause level (weak/medium/strong)')emphasis 元素
<emphasis> 会加强词语的重音,使引擎以更大的音量、更慢的速度或更高的音调读出这些词语。请谨慎使用;过度强调会听起来不自然。
EMPHASIS_EXAMPLES = """
<speak>
This update is
<emphasis level="strong">critically important</emphasis>.
Please read it carefully.
The deadline is
<emphasis level="moderate">this Friday</emphasis>,
not next week.
We
<emphasis level="reduced">recommend</emphasis>
enabling this feature, but it is optional.
</speak>
"""
# emphasis level values:
# strong — much more stress (louder, slower, higher pitch)
# moderate — some additional stress (default if level omitted)
# reduced — less stress (quieter, faster)
print('Use strong for critical information')
print('Use reduced for parenthetical or secondary information')prosody 元素:速率
<prosody rate> 控制说话速度。重要信息应放慢语速;次要细节或免责声明可以加快语速。
PROSODY_RATE_EXAMPLES = """
<speak>
<prosody rate="slow">
This is the most important thing to remember.
Take a moment to let it sink in.
</prosody>
<prosody rate="medium">
Now, for some context about how we got here.
</prosody>
<prosody rate="fast">
And now a quick summary of less critical details that you
can refer back to in the documentation.
</prosody>
</speak>
"""
# rate values:
# x-slow, slow, medium (default), fast, x-fast
# Or percentage: rate="75%" (75% of normal speed)
# Or absolute: rate="200 words per minute"
print('Slow: for emphasis, complex information, or pauses for thought')
print('Fast: for disclaimers, secondary info, rapid listing')prosody 元素:音调
<prosody pitch> 调整语音的基频。您可以使用它来表示语气变化,例如疑问、兴奋或严肃的内容。
PROSODY_PITCH_EXAMPLES = """
<speak>
<prosody pitch="high" rate="medium">
Exciting news! We just launched a brand new feature!
</prosody>
<prosody pitch="low" rate="slow">
Unfortunately, this service will be discontinued.
We apologize for any inconvenience.
</prosody>
<prosody pitch="+20%">
Did you know that our users save three hours per week on average?
</prosody>
<prosody pitch="-15%">
Please review the terms and conditions carefully.
</prosody>
</speak>
"""
# pitch values:
# x-low, low, medium, high, x-high
# Or relative: +20%, -15%
# Or semitones: +2st, -4st
print('High pitch: excitement, questions, announcements')
print('Low pitch: serious, cautionary, or somber content')say-as 元素
<say-as> 告诉 TTS 引擎应当如何解读文本,例如将其解读为日期、电话号码、货币、字符等。这是处理数字和特殊值的可靠方法。
SAY_AS_EXAMPLES = """
<speak>
Your appointment is on
<say-as interpret-as="date" format="mdy">01/15/2025</say-as>.
Call us at
<say-as interpret-as="telephone">1-800-555-1234</say-as>.
Your confirmation code is
<say-as interpret-as="characters">XK7T9</say-as>.
The total is
<say-as interpret-as="currency" language="en-US">$47.50</say-as>.
This is version
<say-as interpret-as="characters">2.3.1</say-as>
of the software.
</speak>
"""
# interpret-as values:
# characters — spell out each character
# cardinal — number as cardinal ("forty-seven")
# ordinal — "forty-seventh"
# fraction — "three halves"
# date — format string controls order
# telephone — phone number formatting
# currency — monetary value with currency name
print('say-as is the most reliable way to control number pronunciation')phoneme 元素
<phoneme> 为 TTS 引擎经常误读的词语提供明确的音标发音,例如品牌名称、技术术语或外语词。
PHONEME_EXAMPLES = """
<speak>
Welcome to
<phoneme alphabet="ipa" ph="ent.ro.pi">Entropiq</phoneme>,
the leading analytics platform.
Our CEO,
<phoneme alphabet="ipa" ph="joo.serf">Josef</phoneme>,
will present the results.
This API uses
<phoneme alphabet="ipa" ph="kwer.i">GraphQL</phoneme>
for data fetching.
</speak>
"""
# IPA (International Phonetic Alphabet) is the most precise
# x-sampa is an alternative ASCII-friendly phonetic alphabet
# Use an IPA converter tool to find the right phonemes:
# - https://tophonetics.com
# - Dictionary.com pronunciation guides use IPA
print('Use phoneme for brand names, technical terms, proper nouns')
print('Test with multiple phoneme values until it sounds right')使用 Amazon Polly 的 SSML
Amazon Polly 支持标准 SSML 以及 Polly 特有的扩展功能。其 API 用法与 Google Cloud TTS 略有不同,但 SSML 标记本身相同。
import boto3
polly = boto3.client('polly', region_name='us-east-1')
SSML_CONTENT = """
<speak>
<prosody rate="slow" pitch="low">
Welcome to our quarterly earnings call.
</prosody>
<break time="1s"/>
We are pleased to report
<emphasis level="strong">record revenue</emphasis>
of
<say-as interpret-as="currency" language="en-US">$4200000</say-as>
this quarter.
</speak>
"""
response = polly.synthesize_speech(
Text=SSML_CONTENT,
TextType='ssml', # Tell Polly this is SSML
OutputFormat='mp3',
VoiceId='Joanna', # US English female voice
)
if 'AudioStream' in response:
with open('output.mp3', 'wb') as f:
f.write(response['AudioStream'].read())
print('Audio saved to output.mp3')使用 LLM 生成 SSML
您可以使用 LLM 将纯文本转换为带有 SSML 注释的语音脚本。这样,您可以先按通常的方式撰写内容,再对其进行后处理,以获得最佳的 TTS 播报效果。
import anthropic
client = anthropic.Anthropic(api_key='sk-ant-...')
SSML_GENERATION_PROMPT = (
'Convert the following text into an SSML document for Google Cloud TTS.\n\n'
'Rules:\n'
'- Wrap the entire output in <speak> tags\n'
'- Add <break time="500ms"/> between major points\n'
'- Add <emphasis level="strong"> around key terms or critical information\n'
'- Use <prosody rate="slow"> for important warnings or summaries\n'
'- Use <say-as interpret-as="date"> for all dates\n'
'- Use <say-as interpret-as="telephone"> for phone numbers\n'
'- Return only the SSML, no explanation\n\n'
'Text: {text}'
)
def text_to_ssml(text):
prompt = SSML_GENERATION_PROMPT.format(text=text)
r = client.messages.create(
model='claude-opus-4-5',
max_tokens=2000,
messages=[{'role': 'user', 'content': prompt}]
)
return r.content[0].textSSML 验证与测试
格式错误的 SSML 会导致 TTS API 错误,或退回到将原始 XML 标签直接读出来。发送到生产环境之前,务必验证 SSML。
import xml.etree.ElementTree as ET
def validate_ssml(ssml_string):
"""
Basic SSML validation: checks XML is well-formed
and has a <speak> root element.
"""
try:
root = ET.fromstring(ssml_string)
if root.tag != 'speak':
return False, 'Root element must be <speak>'
# Check for common misuse patterns
warnings = []
for elem in root.iter():
if elem.tag == 'break' and 'time' not in elem.attrib and 'strength' not in elem.attrib:
warnings.append('<break> has no time or strength attribute')
return True, warnings if warnings else 'Valid'
except ET.ParseError as e:
return False, f'XML parse error: {e}'
# Test
valid_ssml = '<speak>Hello <break time="500ms"/> world.</speak>'
bad_ssml = '<speak>Hello <break> world.</speak>' # break not self-closed
print(validate_ssml(valid_ssml))
print(validate_ssml(bad_ssml))知识检查:SSML say-as
SSML 的 <say-as> 元素的主要用途是什么?
回顾:SSML 与韵律控制
SSML 可以细致控制 TTS 输出。关键元素包括:<break>(按时间或强度控制停顿)、<emphasis>(重音级别:强、中等、弱化)、<prosody rate>(说话速度)、<prosody pitch>(声音频率)、<say-as>(对数字、日期和电话号码进行语义解读),以及 <phoneme>(明确指定 IPA 发音)。Google Cloud TTS 和 Amazon Polly 都支持 SSML,并支持相同的核心标签集。请使用 LLM 根据纯文本自动生成 SSML,并在发送到生产环境之前,务必验证 XML 的格式是否正确。
常见问题解答
「SSML 与韵律控制」课时是免费的吗?
是的 — 「SSML 与韵律控制」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 AI Prompt Engineering 课程的其余内容,请升级到 CoddyKit PRO。 AI Prompt Engineering 课程共包含 4 节课。
「SSML 与韵律控制」这节课中我会学到什么?
语音合成标记语言:停顿、重音、语速和音高。 你通过在浏览器中直接运行的动手代码来练习 AI Prompt Engineering,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 AI Prompt Engineering 需要有经验吗?
无需任何先前经验。CoddyKit 上的 AI Prompt Engineering 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「SSML 与韵律控制」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 AI Prompt Engineering 课中编写并运行代码吗?
能。每节 AI Prompt Engineering 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 适用于自然语音的 TTS 提示词模式
- SSML 与韵律控制
- 语音人工智能人格设计
- 多模态语音与文本代理