> ## Documentation Index
> Fetch the complete documentation index at: https://supertone-b89202c8.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 음성 스트리밍

> 오디오가 합성되는 즉시 청크 단위로 수신합니다. 단일 클립이 길어 생성이 끝나기 전에 재생을 시작하고 싶을 때 유용합니다.

> [!NOTE]
>
> 이 문서는 영어 원문을 기반으로 자동 번역되었습니다. 표현이 어색하거나 모호한 부분이 있을 수 있으니, 정확한 내용은 [영어 원문](/en/docs/text-to-speech/stream-speech)을 함께 확인해 주세요.

`stream_speech`는 오디오를 청크 단위로 반환하므로, 전체 클립이 완성되기 **전에** 재생이나 전달을 시작할 수 있습니다. 경로는 `/v1/text-to-speech/{voice_id}/stream`입니다.

> [!NOTE]
>
> 스트리밍은 현재 \*\*`sona_speech_1`\*\*에서만 지원됩니다.

## 언제 스트리밍을 사용하는가

스트리밍은 **단일** TTS 클립이 충분히 길어, 전체가 완성될 때까지 기다리는 시간이 체감될 정도일 때 가장 유용합니다. 예를 들어 여러 문장으로 이루어진 단락을 한 번의 호출로 합성하는 경우입니다.

각 발화가 짧은 문장인 **인터랙티브 에이전트나 챗봇**의 경우, 보통 빠른 논스트리밍 모델을 사용하는 편이 전체 지연시간 면에서 더 유리합니다.

* **`sona_speech_2_flash`** — 속도와 품질의 균형을 잡은 모델입니다.
* **`supertonic_api_3`** — 추론 속도가 가장 빠르면서도 음성 안정성이 높은 모델입니다. 첫 오디오 도달 시간(time-to-first-audio)이 최우선일 때 사용해 주십시오.

자세한 논의는 [지연시간 최적화](/ko/docs/production/latency-optimization)를 참고해 주십시오. [LLM 응답을 TTS로 스트리밍하기](/ko/docs/examples/llm-streaming-tts)에서 소개하는 문장 단위 패턴은 `stream_speech`를 전혀 사용하지 않으며, 문장마다 빠른 논스트리밍 모델을 호출하는 방식에 의존합니다.

## 기본 스트리밍

**Python (sync)**

```python theme={"dark"}
from supertone import Supertone

VOICE_ID = "20160a4c5ba38967330c84"  # replace with your voice ID

with Supertone(api_key=API_KEY) as client:
    response = client.text_to_speech.stream_speech(
        voice_id=VOICE_ID,
        text="This response is streamed chunk by chunk.",
        language="en",
        model="sona_speech_1",
        output_format="wav",
    )

    with open("streamed.wav", "wb") as f:
        for chunk in response.result.iter_bytes():
            f.write(chunk)
```

**Python (async)**

```python theme={"dark"}
import asyncio
from supertone import Supertone

VOICE_ID = "20160a4c5ba38967330c84"  # replace with your voice ID

async def main():
    async with Supertone(api_key=API_KEY) as client:
        response = await client.text_to_speech.stream_speech_async(
            voice_id=VOICE_ID,
            text="This response is streamed chunk by chunk.",
            language="en",
            model="sona_speech_1",
        )

        with open("streamed.wav", "wb") as f:
            async for chunk in response.result.aiter_bytes():
                f.write(chunk)

asyncio.run(main())
```

**TypeScript**

```typescript theme={"dark"}
import { Supertone } from "@supertone/supertone";
import * as fs from "node:fs";

const VOICE_ID = "20160a4c5ba38967330c84"; // replace with your voice ID

const client = new Supertone({ apiKey: API_KEY });

const response = await client.textToSpeech.streamSpeech({
  voiceId: VOICE_ID,
  apiConvertTextToSpeechUsingCharacterRequest: {
    text: "This response is streamed chunk by chunk.",
    language: "en",
    model: "sona_speech_1",
    outputFormat: "wav",
  },
});

if (response.result && typeof response.result === "object" && "getReader" in response.result) {
  const reader = (response.result as ReadableStream<Uint8Array>).getReader();
  const chunks: Uint8Array[] = [];
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    if (value) chunks.push(value);
  }
  fs.writeFileSync("streamed.wav", Buffer.concat(chunks));
}
```

**cURL**

```bash theme={"dark"}
curl -X POST "https://supertoneapi.com/v1/text-to-speech/20160a4c5ba38967330c84/stream" \
  -H "x-sup-api-key: $SUPERTONE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "This response is streamed chunk by chunk.",
    "language": "en",
    "model": "sona_speech_1"
  }' \
  --output streamed.wav
```

`curl`은 들어오는 청크를 도착하는 대로 곧바로 파일에 기록합니다.

## 요청 필드

[Create speech](/ko/docs/text-to-speech/create-speech)와 동일하며, `model`은 `sona_speech_1`로 고정됩니다(현재 스트리밍을 지원하는 유일한 모델입니다). 경로는 `/v1/text-to-speech/{voice_id}/stream`입니다.

## 응답

기본적으로 응답 본문은 `output_format`에 일치하는 `Content-Type`을 가진 **바이너리 오디오 스트림**입니다.

* `audio/wav` — WAV 파일의 청크입니다(첫 번째 청크에 WAV 헤더가 포함됩니다).
* `audio/mpeg` — MP3 파일의 청크입니다.

`include_phonemes=true`인 경우, 응답은 **NDJSON**으로 전환됩니다. 한 줄에 하나의 JSON 객체가 들어 있으며, 각각 base64 오디오 청크와 대응하는 음소 데이터를 포함합니다.

## 긴 입력 스트리밍

SDK는 스트리밍 시에도 300자를 초과하는 텍스트를 자동으로 분할합니다. 내부적으로 텍스트를 분할하고 순차적인 스트리밍 요청을 보낸 뒤, 청크를 호출자의 이터레이터로 전달하므로 읽기 루프 코드는 그대로 유지할 수 있습니다.

자세한 내용은 [Long text](/ko/docs/text-to-speech/long-text)를 참고해 주십시오.

## 팁

* **플레이어 버퍼링.** 대부분의 플레이어는 재생을 시작하기 전에 초기 버퍼가 필요합니다. 첫 청크가 도착하자마자 재생하는 것보다, 1\~2초 분량의 오디오를 버퍼링한 뒤 재생하는 편이 더 매끄럽게 느껴집니다.
* **WAV 대 MP3.** WAV 청크는 크기가 크지만 연결이 쉽고, MP3 스트림은 더 작아 느린 네트워크에서 전달하기에 유리합니다.
* **오류 처리.** 스트림 오류는 읽기 도중에 발생할 수 있습니다. 반복 처리를 평소의 오류 핸들러로 감싸고, 특히 일시적인 `429`나 `5xx` 응답에 대비한 재시도를 준비해 주십시오. [재시도 및 백오프](/ko/docs/production/retries-and-backoff)를 참고해 주십시오.

## 관련 문서

> **[LLM 스트리밍 TTS](/ko/docs/examples/llm-streaming-tts)**
>
> 보이스 에이전트를 위한 문장 단위 패턴입니다.

> **[지연시간 최적화](/ko/docs/production/latency-optimization)**
>
> 낮은 지연시간을 위해 적합한 모델과 패턴을 선택하세요.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.