DIVE WebSocket API
연결 하나를 유지하면서 여러 합성 요청의 이벤트와 오디오 바이너리 프레임을 순차적으로 받습니다.
WebSocket 음성 합성
연결 후 15초 안에 첫 JSON text message를 보내세요. completed 이벤트를 받은 뒤 같은 연결에서 다음 요청을 보낼 수 있으며, 요청은 한 번에 하나씩 처리됩니다.
URL
wss://api-console.humelo.net/api/v1/dive/ws인증 및 헤더
API Key는 서버 환경변수에 보관하고 요청 헤더로만 전달하세요.
X-API-Key: {YOUR_API_KEY}
# 또는
Authorization: Bearer {YOUR_API_KEY}목소리 선택 방법
한 요청에서는 아래 세 가지 중 하나만 선택하세요. 프리셋 목소리를 사용할 때만 mode를 생략할 수 있습니다.
프리셋 목소리
기본mode: "preset"Humelo가 제공하는 목소리 이름과 지원 감정을 선택합니다.
함께 보낼 필드voiceNameemotion
저장된 목소리
mode: "saved"목소리 등록 API로 만든 저장 목소리 ID를 사용합니다.
함께 보낼 필드savedVoiceId
참조 토큰 직접 전달
mode: "saved"저장 목소리 ID 대신 참조 토큰을 요청에 직접 넣습니다.
함께 보낼 필드referenceTokens
첫 text message 필드
| 필드 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
text | string | string[] | 필수 | 합성할 텍스트입니다. 배열이면 순서대로 이어서 처리합니다. 계정별 최대 길이 적용; 별도 설정이 없으면 500 UTF-16 code unit |
mode | "preset" | "saved" | 선택 | 목소리 선택 방법입니다. preset은 voiceName과 emotion을, saved는 savedVoiceId 또는 referenceTokens를 사용합니다. 기본값 "preset" |
lang | string | 선택 | 합성 언어 코드입니다. 기본값 "ko" |
outputFormat | string | 선택 | 스트리밍 오디오 포맷입니다. pcm_8000, pcm_16000, pcm_24000, pcm_48000, opus_48000_32, opus_48000_64, opus_48000_96, opus_48000_128, mp3_22050_48, mp3_24000_64, mp3_44100_96, mp3_48000_128, aac_48000_128, alaw_8000, ulaw_8000 기본값 "mp3_48000_128" |
volume | number | 선택 | 출력 볼륨입니다. 범위를 벗어나면 서버가 허용 범위로 보정합니다. 기본값 50 · 1–100 |
sentenceSilenceSec | number | 선택 | Gateway가 전달한 문장 순번을 바탕으로 DIVE 엔진이 두 번째 이후 문장 스트림 앞에 삽입하는 무음 길이(초)입니다. 기본값 0.4 · 0.1–2.0 |
dictionaryId | UUID | 선택 | 합성 전에 적용할 조직 소유 단어장 ID입니다. |
priority | boolean | 선택 | 우선 처리 권한이 있는 계정에서만 사용할 수 있습니다. 기본값 false |
voiceName | string | 조건부 | `mode`가 `preset`일 때 사용할 프리셋 목소리 이름입니다. mode=preset이면 필수 |
emotion | string | 조건부 | `voiceName`이 지원하는 감정 이름입니다. mode=preset이면 필수 |
savedVoiceId | UUID | 조건부 | `mode`가 `saved`일 때 등록된 목소리 ID입니다. mode=saved에서 referenceTokens가 없으면 필수 |
referenceTokens | number[] | object | 조건부 | 저장 ID 없이 합성할 참조 토큰입니다. 숫자 배열 또는 `{ ko?: number[], en?: number[] }` 객체를 받습니다. mode=saved에서 savedVoiceId가 없으면 필수 |
요청 예시
{
"text": "안녕하세요. DIVE 음성 합성 테스트입니다.",
"mode": "preset",
"voiceName": "시아",
"emotion": "neutral",
"lang": "ko",
"outputFormat": "mp3_48000_128"
}응답
accepted 이벤트
인증, 검증, 사용량 예약이 완료되면 전송됩니다.
{
"type": "accepted",
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"outputFormat": "mp3_48000_128",
"contentType": "audio/mpeg"
}오디오 메시지
선택한 코덱의 오디오 바이트입니다. 도착 순서대로 연결합니다.
completed 이벤트
{
"type": "completed",
"jobId": "550e8400-e29b-41d4-a716-446655440000"
}error 이벤트
{
"type": "error",
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"error": {
"code": "E5002",
"message": "Service temporarily unavailable",
"details": "No DIVE engine capacity available"
}
}- 브라우저 기본 WebSocket API는 handshake header를 지정할 수 없으므로 서버 SDK에서 연결하세요.
- API Key를 URL query parameter에 넣는 방식은 지원하지 않습니다.
- 각 completed 이벤트를 받은 뒤 다음 JSON text 요청을 보내면 같은 연결을 재사용할 수 있습니다.
- accepted 전을 포함해 이전 요청이 처리 중일 때 다음 요청을 보내면 E4201 error와 1008 정책 위반으로 연결이 종료됩니다.
- completed 이후 합성 요청이나 표준 WebSocket ping이 5분 동안 없으면 서버가 1000으로 연결을 정상 종료합니다.
- 유휴 연결을 유지하려면 고객 서버에서 30초 간격의 표준 WebSocket ping control frame을 권장합니다. ping은 idle timeout을 다시 시작하지만 job, rate limit, 사용량을 만들지 않습니다.
- 같은 연결을 재사용해도 각 합성 요청은 별도로 인증·rate limit·사용량 정산됩니다.
- 각 JSON text 요청은 최대 10 MiB이며, 잘못되거나 찾을 수 없는 dictionaryId는 E4301 error 이벤트 후 연결 종료로 처리됩니다.
- 단어장 DB/RPC 조회 장애는 E5002 error 이벤트 후 연결 종료로 처리됩니다.
연결 유지
completed 이후 기본 idle timeout은 5분입니다. 고객 서버에서 표준 WebSocket ping control frame을 30초 간격으로 보내면 idle timeout이 다시 시작되고 서버가 pong으로 응답합니다. ping은 합성 요청이 아니므로 job, rate limit, 사용량을 만들지 않습니다.
const keepAlive = setInterval(() => ws.ping(), 30_000);
ws.on("close", () => clearInterval(keepAlive));WebSocket close code
표준 WebSocket close code를 사용합니다. completed 후에는 기존 연결을 재사용할 수 있고, 표준 ping으로 idle timeout을 연장할 수 있습니다. 오류로 닫힌 경우 새 연결에서 재시도하세요.
| 코드 | 조건 | 권장 처리 |
|---|---|---|
| 1000 | 합성 요청·WebSocket ping 없이 5분 idle 또는 정상 종료 | 필요하면 새 연결 |
| 1003 | 첫 메시지가 JSON text가 아님 | 요청 형식 수정 |
| 1008 | 잘못된 요청, 권한, 겹치는 요청, 초기 요청 시간 초과 | 요청 수정 후 새 연결 |
| 1011 | 합성 중 서버 내부 오류 | 제한적으로 재시도 |
| 1012 | Gateway 재시작 또는 drain | backoff 후 새 연결 |
| 1013 | 사용량·rate limit 또는 일시적 서비스 불가 | 제한 확인 후 backoff |