Inworld TTS의 준언어적 태그(Paralinguistic Tags)가 작동하지 않는 이유 — 해결 방법은 이것입니다
요약
Inworld TTS에서 준언어적 태그([laugh], [sigh] 등)가 작동하지 않는 원인을 분석하고, 이를 대체하여 표현력 있는 음성을 생성하는 네 가지 실질적인 해결 방법을 제시합니다.
핵심 포인트
- Inworld TTS는 인라인 태그 대신 SSML과 텍스트 구성을 통해 표현력을 조절해야 함
- 별표(*)를 사용하여 특정 단어에 가청적인 강조(stress)를 부여할 수 있음
- 말줄임표(...)를 활용해 자연스러운 운율적 휴지(pause)를 생성 가능
- SSML의 <break> 태그를 사용하여 정밀한 시간 단위의 휴지 제어 가능
- 의성어(ha-ha, mmm 등)를 직접 입력하여 실제 소리로 렌더링 유도
지난 1년 동안 표현력이 풍부한 TTS (Text-to-Speech)를 다뤄보셨다면 아마 다음과 같은 패턴을 보셨을 것입니다:
그녀는 잠시 멈췄다. [sigh] "좋아, 들어와도 돼."
인라인 준언어적 태그 (Inline paralinguistic tags)입니다. 모델 데모의 절반 정도가 이를 사용합니다. 그래서 음성 메시지가 핵심 출력물인 Telegram 기반 AI 컴패니언 HoneyChat을 위해 Inworld TTS-1.5 Max를 연결했을 때, 저희는 프롬프트 곳곳에 [laugh], [sigh], [breathe]를 뿌려 넣고 출시했습니다.
오디오는 괜찮게 들렸습니다. 다만... 이전과 정확히 똑같았습니다. 웃음도 없었고, 한숨도 없었습니다. 태그들은 목소리에 따라 기껏해야 침묵으로 읽히거나, 최악의 경우
동일한 문장, 동일한 목소리로 테스트한 병렬 오디오 비교 결과입니다:
| 패턴 | 결과 |
|---|---|
[laugh] [sigh] | 출력 시 침묵 발생 |
| ... | ... |
Inworld API 문서에는 이러한 태그들에 대한 지원 내용이 명시되어 있지 않습니다. 저희는 (인터넷상의 다른 모든 TTS 게시물들이 이들을 사용하기 때문에) 이것들이 보편적인 관례라고 가정했습니다. 하지만 그렇지 않았습니다.
Inworld가 실제로 노출하는 것은 요청 파라미터(request parameters)로서의 **temperature**와 speakingRate, 그리고 SSML의 작은 하위 집합뿐입니다. 표현력은 이 요소들과 더불어 _텍스트 자체_를 어떻게 구성하느냐에서 얻어야 합니다.
실제로 작동하는 방법
26개의 아키타입(archetypes) × 15개 언어에 대해 충분한 A/B 테스트를 거친 결과, 네 가지 패턴이 오디오 출력을 안정적으로 변화시킵니다.
1. 강조를 위한 별표 (Asterisks)
"You did *what?*"
별표는 음성 텍스트에서 제거되지만, 강조된 단어에 가청적인 스트레스(stress)가 실립니다. 저희가 테스트한 모든 목소리에서 작동했습니다. 가장 저렴하면서도 적중률이 높은 표식입니다.
2. 분위기 있는 휴지를 위한 말줄임표 (Ellipsis)
"Fine... you can come in."
세 개의 점은 톤이 떨어지는 실제 휴지(pause)를 생성합니다. 이는 [sigh]를 억지로 흉내 내지 않고도 목소리로 한숨을 쉬는 것과 같은 효과를 줍니다. 더 긴 휴지를 원한다면 다섯 개의 점을 사용하세요. 모델은 이를 운율적 단서(prosodic cues)로 해석합니다.
3. 강제 휴지를 위한 SSML <break>
<speak>
She paused. <break time="0.4s"/> "Fine, you can come in."
</speak>
Inworld는 SSML의 유용한 하위 집합을 수용하며, 그중 <break>가 표현력 있는 음성을 위해 가장 중요합니다. 짧은 박자에는 0.2s, 한숨 섞인 휴지에는 0.4s, 대사를 내뱉기 직전의 긴장된 순간에는 0.8s를 사용하세요. 전체 텍스트를 <speak>로 감싸면 파서(parser)가 이를 처리합니다.
4. 웃음, 신음, 숨소리를 위한 의성어 (Onomatopoeia)
"Mmm... ha-ha, you're right."
"ahh... I needed that."
모델은 ha-ha, mmm, ahh, oh, nnn을 메타 태그가 아닌 소리의 철자로 인식하기 때문에 실제 소리로 렌더링합니다. 이는 설령 합성된 [laugh]가 존재하더라도 그보다 훨씬 더 자연스럽게 들립니다.
감정적이거나 친밀한 장면에서는 리듬을 반복하는 것(ah... ah... ah) 자체가 실제 운율(prosody)을 전달합니다. 다른 TTS 시스템이라면 [breathe] 마커를 사용해야 할 호흡 패턴에 저희는 이 방식을 활용합니다.
모든 것을 하나로 묶어주는 Wrapper
core/voice.py 파일에서 우리는 모든 청크를 Inworld에 전달하기 전에 enrich_for_tts() 함수(772행 근처)를 통해 처리합니다. 이는 정규표현식 기반이며, 언어 인식적이고, 반복 실행해도 문제가 없는(idempotent) 방식입니다:
def enrich_for_tts(text: str, lang: str = "en") -> tuple[str, dict]:
"""Return (preprocessed_text, request_params).
Strips fake paralinguistic tags, adds SSML breaks where appropriate,
...
무드 감지기(mood detector)는 감정적 단서(강도어, 반복되는 구두점, 의성어 밀도)를 찾고, 더 표현력이 풍부한 장면의 경우 temperature와 speakingRate 값을 높입니다. 모델은 동일하고 목소리도 같지만, 인라인 태그가 없어 모델이 무시할 수 있는 방식임에도 훨씬 역동적인 출력을 만듭니다.
교훈
[laugh]나[sigh]가 보편적이라고 가정하지 마세요. 그렇지 않습니다. 제공업체의 문서를 확인하고 테스트해 보세요.- 시각적 차이만으로 판단하지 말고, 나란히 배치된 오디오로 테스트하세요. 침묵을 내보내는
[sigh]는 어떤 로그에서든 실제 한숨 소리를 내보내는 것과 똑같이 보입니다. - API가 실제로 노출하는 것을 사용하세요. Inworld의 경우 인라인 태그가 아니라
temperature,speakingRate, 그리고 유용한 SSML 하위 집합입니다. - 감정적 사운드에는 의성어가 메타태그보다 우세합니다. `
이 글은 음성 메시지가 핵심 출력물(first-class output)인 Telegram 기반 AI 컴패니언, **HoneyChat**의 프로덕션 작업 과정에서 작성되었습니다. 원문 버전: honeychat.bot/en/blog/inworld-tts-paralinguistic-tags-alternatives.
— HoneyChat Engineering
출처 (Sources)
- Inworld TTS — documentation — 지원되는 요청 파라미터 (
temperature,speakingRate), SSML 하위 집합, 보이스 디자인 API. - W3C — Speech Synthesis Markup Language (SSML) 1.1 — 전체 SSML 명세;
<break>,<speak>, 운율(prosody) 요소. - TTS Arena (Hugging Face) — 커뮤니티 ELO 랭킹; Inworld TTS-1.5 Max의 상위권 위치 맥락.
- gTTS — Python library — Inworld을 사용할 수 없을 때 사용하는 무료 폴백(fallback) 라이브러리.
- HoneyChat 엔지니어링 노트: LLM 프롬프트 캐싱 측정 · LLM 거부 구조(refusal rescue) 체인.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기