> ## Documentation Index
> Fetch the complete documentation index at: https://docs.supertoneapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK

> Supertone Python SDK 설치, 인증, 사용 방법 — 동기 및 비동기 클라이언트, 스트리밍, 자동 청크 분할, 오류 처리까지.

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

공식 Python SDK는 PyPI에 [`supertone`](https://pypi.org/project/supertone/)으로 공개되어 있습니다. 소스: [supertone-inc/supertone-python](https://github.com/supertone-inc/supertone-python).

## 한눈에 보기

|                    |                                                                                     |
| ------------------ | ----------------------------------------------------------------------------------- |
| **패키지**            | PyPI의 [`supertone`](https://pypi.org/project/supertone/)                            |
| **저장소**            | [supertone-inc/supertone-python](https://github.com/supertone-inc/supertone-python) |
| **언어**             | Python 3.9+                                                                         |
| **인증**             | `Supertone(api_key=...)`                                                            |
| **동기 API**         | 지원(기본)                                                                              |
| **비동기 API**        | `*_async` 메서드 + `async with`                                                        |
| **스트리밍**           | `iter_bytes()` / `aiter_bytes()`                                                    |
| **긴 텍스트 자동 청크 분할** | ✅ 300자, 최대 3 워커 병렬                                                                  |
| **커스텀 재시도**        | ✅ `retry_config`로 설정                                                                |
| **HTTP 백엔드**       | `httpx`                                                                             |

## 설치

<Tabs>
  <Tab title="pip">
    ```bash theme={"dark"}
    pip install supertone
    ```
  </Tab>

  <Tab title="uv">
    ```bash theme={"dark"}
    uv add supertone
    ```
  </Tab>

  <Tab title="poetry">
    ```bash theme={"dark"}
    poetry add supertone
    ```
  </Tab>
</Tabs>

Python 3.9+가 필요합니다.

## API Key 설정

SDK는 환경 변수에서 자동으로 키를 읽지 않습니다. `api_key`를 명시적으로 전달하세요. 관례적으로 `SUPERTONE_API_KEY`에서 읽어옵니다.

```bash theme={"dark"}
export SUPERTONE_API_KEY="Kp9mZ3xQ7v..."
```

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

client = Supertone(api_key=os.environ["SUPERTONE_API_KEY"])
```

보이스 ID는 환경 변수로 다루지 않습니다 — 사용 사례마다 달라지므로, 코드에 일반 문자열로 두거나(또는 요청 페이로드에서 전달하세요).

## 음성 생성하기(동기)

권장되는 패턴은 컨텍스트 매니저를 사용해 내부 HTTP 연결이 깔끔하게 닫히도록 하는 것입니다.

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

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

with Supertone(api_key=os.environ["SUPERTONE_API_KEY"]) as client:
    response = client.text_to_speech.create_speech(
        voice_id=VOICE_ID,
        text="Hello from the Python SDK.",
        language="en",
        output_format="wav",
    )

    with open("speech.wav", "wb") as f:
        f.write(response.result.read())
```

## 음성 생성하기(비동기)

`_async` 접미사와 `async with`를 사용하세요.

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

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

async def main():
    async with Supertone(api_key=os.environ["SUPERTONE_API_KEY"]) as client:
        response = await client.text_to_speech.create_speech_async(
            voice_id=VOICE_ID,
            text="Hello from the async Python SDK.",
            language="en",
        )

        with open("speech.wav", "wb") as f:
            f.write(response.result.read())

asyncio.run(main())
```

SDK의 모든 리소스 메서드는 두 가지 형태를 갖습니다: `create_speech` / `create_speech_async`, `stream_speech` / `stream_speech_async`, `list_voices` / `list_voices_async` 등.

## 음성 스트리밍

스트리밍은 오디오 청크의 이터레이터(또는 비동기 이터레이터)를 반환합니다.

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

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

with Supertone(api_key=os.environ["SUPERTONE_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",
    )

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

비동기 버전에서는 `async for chunk in response.result.aiter_bytes()`를 사용하세요. 스트리밍은 현재 `sona_speech_1`에서만 지원됩니다.

## 긴 텍스트 자동 청크 분할

`create_speech`, `create_speech_async`, `stream_speech`, `stream_speech_async`는 300자보다 긴 텍스트를 자동으로 분할합니다. `create_speech`는 최대 3개 세그먼트를 병렬로 실행해 오디오를 병합하며, `stream_speech`는 순차적으로 세그먼트를 실행해 이터레이터로 청크를 전달합니다.

```python theme={"dark"}
LONG_TEXT = "..."  # any length, including thousands of characters

response = client.text_to_speech.create_speech(
    voice_id=VOICE_ID,
    text=LONG_TEXT,
    language="en",
)

with open("narration.wav", "wb") as f:
    f.write(response.result.read())   # single merged file
```

`predict_duration`은 자동 청크 분할을 수행하지 **않습니다**. 입력을 300자 이내로 유지하고, 더 긴 스크립트는 직접 길이를 합산하세요.

자세한 내용과 튜닝은 [긴 텍스트](/ko/docs/text-to-speech/long-text)를 참고하세요.

## 자주 사용하는 작업

```python theme={"dark"}
# List voices with pagination
result = client.voices.list_voices(page_size=20)

# Search voices
result = client.voices.search_voices(language="ko,en", style="happy")

# Get a single voice
voice = client.voices.get_voice(voice_id=VOICE_ID)

# Predict duration (no credits deducted)
duration = client.text_to_speech.predict_duration(
    voice_id=VOICE_ID,
    text="How long will this be?",
    language="en",
)

# Get credit balance
balance = client.usage.get_credit_balance()
```

## 타입 안전 enum(선택)

타입 안전성을 위해 SDK는 `supertone.models`에 enum 상수를 노출합니다.

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

models.APIConvertTextToSpeechUsingCharacterRequestLanguage.EN       # "en"
models.APIConvertTextToSpeechUsingCharacterRequestModel.SONA_SPEECH_1  # "sona_speech_1"
```

일반 문자열(`"en"`, `"sona_speech_1"`)도 동일하게 동작합니다 — 선호하는 방식을 선택하세요.

## 오류 처리

오류는 `supertone.errors`에 있으며 모두 `SupertoneError`를 상속합니다.

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

try:
    response = client.text_to_speech.create_speech(...)
except errors.TooManyRequestsErrorResponse as e:
    # 429 — back off and retry
    print("Rate limited:", e.message)
except errors.UnauthorizedErrorResponse as e:
    # 401 — bad or missing API key
    print("Auth failed:", e.message)
except errors.PaymentRequiredErrorResponse as e:
    # 402 — out of credits
    print("Buy more credits:", e.message)
except errors.SupertoneError as e:
    # Any other API error
    print(f"HTTP {e.status_code}: {e.message}")
```

| Error class                         | HTTP status |
| ----------------------------------- | ----------- |
| `BadRequestErrorResponse`           | 400         |
| `UnauthorizedErrorResponse`         | 401         |
| `PaymentRequiredErrorResponse`      | 402         |
| `ForbiddenErrorResponse`            | 403         |
| `NotFoundErrorResponse`             | 404         |
| `RequestTimeoutErrorResponse`       | 408         |
| `PayloadTooLargeErrorResponse`      | 413         |
| `UnsupportedMediaTypeErrorResponse` | 415         |
| `TooManyRequestsErrorResponse`      | 429         |
| `InternalServerErrorResponse`       | 500         |

네트워크 오류(DNS 실패, 브로큰 파이프 등)는 `httpx`에서 발생하며 `SupertoneError`를 상속하지 않습니다.

## 설정

```python theme={"dark"}
from supertone import Supertone
from supertone.utils.retries import RetryConfig

client = Supertone(
    api_key=os.environ["SUPERTONE_API_KEY"],
    timeout_ms=30_000,
    retry_config=RetryConfig(
        strategy="backoff",
        backoff={"initial_interval": 500, "max_interval": 60_000},
        retry_connection_errors=True,
    ),
)
```

## 관련 문서

<CardGroup cols={2}>
  <Card title="TypeScript SDK" icon="js" href="/ko/docs/developer-tools/typescript">
    Node 및 Bun을 위한 동등한 SDK입니다.
  </Card>

  <Card title="예제" icon="lightbulb" href="/ko/docs/examples/llm-streaming-tts">
    자주 사용하는 워크플로에 대한 레시피입니다.
  </Card>
</CardGroup>
