음성 합성 API
음성 합성 API는 텍스트와 voice_id를 받아 MP3 또는 WAV 음성을
반환합니다. 기본 Base URL은 https://api.kitschlabs.com이며, 공개 요청은
xi-api-key 헤더로 인증합니다.
API 한눈에 보기
| 항목 | 값 |
|---|---|
| Base URL | https://api.kitschlabs.com |
| 인증 | xi-api-key: <API_KEY> |
| 기본 출력 | mp3_44100_128 (audio/mpeg) |
| 추가 출력 | wav_24000 (audio/wav) |
language_code 스키마는 en, ko, ja, zh를 받습니다. 사용할 수 있는
언어와 음성은 계정에 따라 다를 수 있으므로
GET /v1/voices 응답을 기준으로 선택하세요.
어떤 endpoint를 사용하나요?
| Method | Endpoint | 용도 |
|---|---|---|
GET | /v1/voices | 사용 가능한 음성 조회 |
POST | /v1/text-to-speech/{voice_id} | 완성된 음성 파일 생성 |
어떻게 인증하나요?
모든 공개 endpoint에 xi-api-key를 보냅니다. 예제의 <API_KEY>를 발급받은
키로 바꾸되 코드나 로그에 실제 키를 남기지 마세요.
xi-api-key: <API_KEY>
음성 조회
curl "https://api.kitschlabs.com/v1/voices" \
--header "xi-api-key: <API_KEY>"
음성 합성에는 /v1/voices 응답의 voice_id를 사용합니다. 표시 이름을 코드에
고정하면 이름 변경 시 문제가 생길 수 있으므로 voice_id를 저장하세요.
음성을 어떻게 생성하나요?
POST /v1/text-to-speech/{voice_id}에 JSON을 보내고 응답 body를 파일로
저장합니다.
- cURL
- Python
- JavaScript
curl --request POST \
"https://api.kitschlabs.com/v1/text-to-speech/<VOICE_ID>?output_format=mp3_44100_128" \
--header "xi-api-key: <API_KEY>" \
--header "Content-Type: application/json" \
--data '{
"text": "오늘도 좋은 하루 보내세요.",
"language_code": "ko"
}' \
--output speech.mp3
import os
import requests
response = requests.post(
"https://api.kitschlabs.com/v1/text-to-speech/<VOICE_ID>",
params={"output_format": "mp3_44100_128"},
headers={
"xi-api-key": os.environ["KITSCH_API_KEY"],
"Content-Type": "application/json",
},
json={
"text": "오늘도 좋은 하루 보내세요.",
"language_code": "ko",
},
timeout=120,
)
response.raise_for_status()
with open("speech.mp3", "wb") as audio_file:
audio_file.write(response.content)
import { writeFile } from "node:fs/promises";
const response = await fetch(
"https://api.kitschlabs.com/v1/text-to-speech/<VOICE_ID>?output_format=mp3_44100_128",
{
method: "POST",
headers: {
"xi-api-key": process.env.KITSCH_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
text: "오늘도 좋은 하루 보내세요.",
language_code: "ko",
}),
},
);
if (!response.ok) {
throw new Error(`${response.status}: ${await response.text()}`);
}
await writeFile("speech.mp3", Buffer.from(await response.arrayBuffer()));
어떤 필드를 보내나요?
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
text | string | 예 | 합성할 텍스트. 빈 문자열은 허용하지 않음 |
language_code | string | 아니요 | en, ko, ja, zh 중 하나 |
instruct | string | 아니요 | 말하기 방식에 대한 자연어 지시 |
speed | number | 아니요 | 발화 속도. 0.25부터 4 |
voice_settings.emotion_code | string | 아니요 | 사용할 수 있는 감정 선택 |
지원하는 텍스트 태그
text 안에 [laughter], [sigh], [en], [wa], [hnn] 태그를 넣을 수
있습니다. 그 밖의 대괄호 태그는 요청 오류로 거절됩니다.
{
"text": "정말요? [laughter] 저도 전혀 예상하지 못했어요."
}
오류에는 어떻게 대응하나요?
오류 응답은 일반적으로 detail.status, detail.message,
detail.request_id를 포함합니다.
{
"detail": {
"status": "rate_limited",
"message": "Rate limit exceeded. Please retry later.",
"request_id": "<REQUEST_ID>"
}
}
| 상태 코드 | 의미 | 권장 행동 |
|---|---|---|
400·422 | 요청 값 오류 | body, tag, 범위를 수정 |
401 | API 키가 없거나 유효하지 않음 | 키와 xi-api-key 헤더 확인 |
402 | 사용 가능한 credit 부족 | 결제 및 청구 상태 확인 |
404 | 음성을 찾지 못하거나 접근할 수 없음 | voice_id와 계정 접근 범위 확인 |
429 | 계정별 요청 한도 초과 | Retry-After를 따르고 backoff 적용 |
5xx | 일시적인 서버 오류 | request ID를 기록하고 제한적으로 재시도 |
성공·오류 응답 헤더의 x-kitsch-request-id를 로그에 남기면 지원 문의와 장애
추적에 사용할 수 있습니다.