0Pricing
AI Prompt Engineering · 강의

SSML 및 운율 제어

음성 합성 마크업 언어: 쉼, 강조, 속도, 음높이를 다룹니다.

SSML 및 운율 제어은(는) CoddyKit의 무료 AI Prompt Engineering 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Prompt Engineering 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Prompt Engineering 강의에는 총 4개의 강의가 포함되어 있습니다.

SSML이란 무엇인가요

SSML(음성 합성 마크업 언어)은 TTS 엔진이 텍스트를 읽는 방식을 세밀하게 제어할 수 있게 해 주는 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 전용 확장 기능을 함께 지원합니다. 인터페이스 사용법은 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].text

SSML 검증과 테스트

형식이 잘못된 SSML은 TTS 인터페이스 오류를 일으키거나 원시 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 및 운율 제어” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Prompt Engineering 강의 전체를 잠금 해제할 수 있습니다. AI Prompt Engineering 강의에는 총 4개의 강의가 포함되어 있습니다.

“SSML 및 운율 제어”에서 뭘 배우나요?

음성 합성 마크업 언어: 쉼, 강조, 속도, 음높이를 다룹니다. 브라우저에서 직접 실행하는 실습 코드로 AI Prompt Engineering을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

AI Prompt Engineering을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 AI Prompt Engineering은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“SSML 및 운율 제어” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 AI Prompt Engineering 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 AI Prompt Engineering 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 자연스러운 음성을 위한 TTS 프롬프트 패턴
  2. SSML 및 운율 제어
  3. 음성 인공지능 페르소나 설계
  4. 다중 모달 음성 및 텍스트 에이전트
← AI Prompt Engineering(으)로 돌아가기