음성 및 모델 목록
GET /v1/chat/catalog는 공개 모델, 음성, 현재 요금을 반환합니다. 텍스트는 POST /v1/chat/completions를, 음성은 아래 엔드포인트를 사용합니다.
모델과 요금
모델 목록을 불러오는 중…
음성 인식
POST /v1/chat/transcribe는 { "audio": "data:audio/webm;base64,..." }를 받습니다. 일반 base64도 지원하며 디코딩 후 최대 10MB입니다. text와 language를 반환합니다.
음성 합성
모델 목록을 불러오는 중…
모델을 펼치면 활성화된 음성의 이름, ID, 언어를 볼 수 있습니다. 비활성화된 음성은 목록에서 제외되며 새 합성에 사용할 수 없습니다. 모델을 끄면 소속 음성도 모두 제외됩니다. 다시 켜도 개별 음성 설정은 유지됩니다. 기본 음성이나 모델이 비활성화되면 다른 활성 음성을 선택합니다. 새로고침하여 최신 설정을 불러오세요.
POST /v1/chat/speech는 { "text": "Hello", "voice": "speech-light:af_bella" }를 받습니다. 최대 2,000자이며 voice를 생략하면 기본 음성을 사용합니다. voices[].id를 지정하고 modelId에서 음성 모델과 요금을 확인하세요. 채팅과 음성 모델은 독립적입니다.
응답은 audio(data:audio/mpeg;base64,...), voice, billing: { model, credits, characters, price, unit: "1000_characters" }를 포함합니다. Speech Pro를 포함한 모든 음성은 MP3입니다. audio를 오디오 요소의 src로 쓰거나 쉼표 뒤의 base64를 디코딩해 .mp3로 저장하세요. Python 예제도 사용할 수 있습니다.
스트리밍 음성
같은 엔드포인트에 "stream": true를 보내세요. Speech Standard, Speech Light, Speech Pro, Speech Expressive가 지원하며 speechModels[].streaming으로 확인할 수 있습니다. 생략하거나 false면 일반 JSON을 반환합니다.
{ "text": "Hello. How was your day?", "voice": "speech-pro:Ashley", "stream": true }응답은 Content-Type: audio/mpeg인 연속 MP3 바이너리 스트림입니다. JSON, base64, SSE가 아닙니다. 프록시는 도착한 음성을 바로 전달하며 Speech Pro는 점진적으로 MP3로 변환합니다. 모델 자체의 생성 지연을 보장하지는 않습니다. 텍스트는 한 요청으로 보내며 자동 문장 분할은 하지 않습니다.
curl과 FFmpeg가 있으면 수신 중 재생할 수 있습니다.
curl --fail --no-buffer https://api.coldstart.win/v1/chat/speech \
-H "Authorization: Bearer $COLDSTART_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Hello. How was your day?","voice":"speech-pro:Ashley","stream":true}' \
| ffplay -nodisp -autoexit -f mp3 -i pipe:0통화 클라이언트는 수신 데이터를 지속적인 MP3 디코더에 전달해야 합니다. 브라우저에서는 response.body.getReader()를 사용하세요. blob(), arrayBuffer(), json()은 전체 수신을 기다립니다. 네트워크 청크는 임의 바이트 구간이며 각각 독립 MP3 파일이 아닙니다. 사용자가 끼어들거나 통화를 종료하면 fetch와 reader를 취소하세요. 재생에는 브라우저가 요구하는 사용자 동작이 필요합니다.
헤더는 X-Speech-Voice(URL 인코딩된 공개 ID), X-Speech-Credits, X-Speech-Characters, X-Speech-Usage-Id를 제공합니다. 크레딧은 최초 차감액이며 성공 시 비스트리밍과 같은 요금입니다. 서버 처리 완료 전 실패나 연결 종료는 환불되고 실패로 기록됩니다. 완료 후 취소는 이미 성공한 요금을 취소하지 않습니다.
오디오 시작 전 오류는 HTTP 상태와 JSON 본문으로 반환합니다. 시작 후 실패하면 연결이 끊어집니다. 불완전한 오디오는 버리고 사용 기록에서 최종 요금을 확인하세요. HTTP 200이나 첫 청크 수신만으로 완료를 판단하면 안 됩니다. 추가 프록시는 이 경로의 버퍼링과 압축을 꺼야 합니다. API는 X-Accel-Buffering: no, Cache-Control: no-store, no-transform을 보냅니다.
콘텐츠 정책이 텍스트를 명시적으로 거부하면 두 모드 모두 음성 시작 전 400 content_policy_violation을 반환하고 환불합니다. 같은 텍스트를 자동 재시도하지 말고 정책에 맞게 수정하세요. 스트리밍에도 콘텐츠 제한이 적용됩니다.
음성 요청은 독립적입니다. 원하는 공개 음성 ID를 명시하세요. 일반 응답은 오디오 data URI와 과금 정보를 포함한 JSON이며 스트리밍은 오디오 바이트를 반환합니다.
음성 요금은 정규화된 과금 문자 수 × 단가 ÷ 1,000을 소수점 8자리까지 올림한 값입니다. Speech Light, Pro, Expressive는 UTF-16 코드 단위(😀는 2), Standard는 Unicode 코드 포인트를 사용합니다. 규칙은 speechModels[].characterCounting과 billing.character_counting(utf16_code_units 또는 unicode_codepoints), 수량은 billing.characters로 확인합니다. 서식과 지문은 합성과 계산 전에 제거됩니다. 실패하거나 빈 합성 결과는 환불합니다. 합성할 때마다 과금되지만 반환된 오디오를 다시 재생하는 데는 요금이 없습니다. 콘솔은 현재 페이지 세션 동안 메시지와 음성별로 오디오를 캐시합니다.