> ## 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.

# TypeScript SDK

> Supertone TypeScript SDK 설치, 인증, 사용 방법 — Promise 기반, 스트리밍, 자동 청크 분할, Node 및 Bun에서 실행됩니다.

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

공식 TypeScript SDK는 npm에 [`@supertone/supertone`](https://www.npmjs.com/package/@supertone/supertone)으로 공개되어 있습니다. 소스: [supertone-inc/supertone-ts](https://github.com/supertone-inc/supertone-ts).

## 한눈에 보기

|                    |                                                                                   |
| ------------------ | --------------------------------------------------------------------------------- |
| **패키지**            | npm의 [`@supertone/supertone`](https://www.npmjs.com/package/@supertone/supertone) |
| **저장소**            | [supertone-inc/supertone-ts](https://github.com/supertone-inc/supertone-ts)       |
| **언어**             | TypeScript 5+ / Node 18+                                                          |
| **모듈 포맷**          | ESM + CommonJS                                                                    |
| **인증**             | `new Supertone({ apiKey: ... })`                                                  |
| **동기 API**         | 해당 없음                                                                             |
| **비동기 API**        | 모든 메서드(Promise)                                                                   |
| **스트리밍**           | `ReadableStream` reader                                                           |
| **긴 텍스트 자동 청크 분할** | ✅ 300자, 순차                                                                        |
| **커스텀 재시도**        | ✅ `retryConfig`로 설정                                                               |
| **HTTP 백엔드**       | `fetch`                                                                           |

## 설치

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

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

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

  <Tab title="yarn">
    Yarn은 peer dependency를 수동으로 설치해야 합니다.

    ```bash theme={"dark"}
    yarn add @supertone/supertone zod
    ```
  </Tab>
</Tabs>

이 패키지는 **ESM**과 **CommonJS** 진입점을 모두 제공하며 TypeScript 타입을 포함합니다. Node 18+가 필요합니다(전역 `fetch`와 `ReadableStream`을 위해). Bun과 Deno에서도 동작하며, 브라우저용으로는 설계되지 않았습니다(API Key는 절대 클라이언트 측에 두면 안 됩니다).

## API Key 설정

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

```typescript theme={"dark"}
import { Supertone } from "@supertone/supertone";

const client = new Supertone({ apiKey: process.env.SUPERTONE_API_KEY });
```

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

## 음성 생성하기

```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: process.env.SUPERTONE_API_KEY });

const response = await client.textToSpeech.createSpeech({
  voiceId: VOICE_ID,
  apiConvertTextToSpeechUsingCharacterRequest: {
    text: "Hello from the TypeScript SDK.",
    language: "en",
    model: "sona_speech_1",
    outputFormat: "wav",
  },
});

if (response.result instanceof Uint8Array) {
  fs.writeFileSync("speech.wav", response.result);
} else if (response.result && "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("speech.wav", Buffer.concat(chunks));
}
```

모든 메서드는 비동기이며 Promise를 반환합니다. 동기 대안은 제공되지 않습니다.

## 음성 스트리밍

```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: process.env.SUPERTONE_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",
  },
});

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));
}
```

스트리밍은 현재 `sona_speech_1`에서만 지원됩니다.

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

`createSpeech`와 `streamSpeech` 모두 300자보다 긴 텍스트를 자동으로 청크 분할합니다. 텍스트를 그대로 전달하면 SDK가 분할하고, 각 세그먼트를 생성한 뒤 결과를 병합(또는 스트리밍)합니다.

```typescript theme={"dark"}
const response = await client.textToSpeech.createSpeech(
  {
    voiceId: VOICE_ID,
    apiConvertTextToSpeechUsingCharacterRequest: { text: longText, language: "en" },
  },
  {
    maxTextLength: 300, // optional override (default 300)
  },
);
```

`predictDuration`은 자동 청크 분할을 수행하지 **않습니다** — 300자 제한이 그대로 적용됩니다.

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

## 자주 사용하는 작업

```typescript theme={"dark"}
// List voices with pagination
const list = await client.voices.listVoices({ pageSize: 20 });

// Search voices
const search = await client.voices.searchVoices({
  language: "ko,en",
  style: "happy",
});

// Get a single voice
const voice = await client.voices.getVoice({ voiceId: VOICE_ID });

// Predict duration (no credits deducted)
const { duration } = await client.textToSpeech.predictDuration({
  voiceId: VOICE_ID,
  predictTTSDurationRequest: {
    text: "How long will this be?",
    language: "en",
  },
});

// Get credit balance
const balance = await client.usage.getCreditBalance();
```

## 타입 안전 enum(선택)

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

```typescript theme={"dark"}
import * as models from "@supertone/supertone/models";

models.APIConvertTextToSpeechUsingCharacterRequestLanguage.En;     // "en"
models.APIConvertTextToSpeechUsingCharacterRequestModel.SonaSpeech1; // "sona_speech_1"
```

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

## 오류 처리

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

```typescript theme={"dark"}
import { Supertone } from "@supertone/supertone";
import * as errors from "@supertone/supertone/models/errors";

const client = new Supertone({ apiKey: process.env.SUPERTONE_API_KEY });

try {
  const response = await client.textToSpeech.createSpeech({ /* ... */ });
} catch (err) {
  if (err instanceof errors.TooManyRequestsErrorResponse) {
    console.log("Rate limited:", err.message);
  } else if (err instanceof errors.UnauthorizedErrorResponse) {
    console.log("Auth failed:", err.message);
  } else if (err instanceof errors.PaymentRequiredErrorResponse) {
    console.log("Out of credits:", err.message);
  } else if (err instanceof errors.SupertoneError) {
    console.log(`HTTP ${err.statusCode}: ${err.message}`);
  } else {
    throw err;
  }
}
```

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

네트워크 계층 오류(`ConnectionError`, `RequestTimeoutError`, `RequestAbortedError` 등)는 `SupertoneError`가 아닌 `HTTPClientError`를 상속합니다.

## 설정

```typescript theme={"dark"}
const client = new Supertone({
  apiKey: process.env.SUPERTONE_API_KEY,
  timeoutMs: 30_000,
  retryConfig: {
    strategy: "backoff",
    backoff: { initialInterval: 500, maxInterval: 60_000, exponent: 1.5, maxElapsedTime: 3_600_000 },
    retryConnectionErrors: true,
  },
});
```

## 관련 문서

<CardGroup cols={2}>
  <Card title="Python SDK" icon="python" href="/ko/docs/developer-tools/python">
    Python을 위한 동등한 SDK입니다.
  </Card>

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