Skip to main content

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.

이 문서는 영어 원문을 기반으로 자동 번역되었습니다. 표현이 어색하거나 모호한 부분이 있을 수 있으니, 정확한 내용은 영어 원문을 함께 확인해 주세요.
이 예제는 여러 문단으로 이루어진 스크립트를 받아 하나의 오디오 파일로 만들어 줍니다. SDK의 자동 청크 분할을 보여줍니다. 전체 스크립트를 create_speech에 그대로 전달하면, SDK가 문장 경계에서 분할하여 각 세그먼트를 생성하고, 결과를 하나로 병합합니다.

Python

import os
from supertone import Supertone

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

SCRIPT = """
Chapter one. The clocktower struck midnight, and the wind through the old
square carried whispers from the workshops below. Hana adjusted her coat,
checked the address one more time, and stepped through the iron gate.

Inside, the air smelled of copper and lemon polish. Rows of half-finished
automatons stared back from the shelves, each one waiting for a name. She
set her satchel on the bench and opened her notebook to a fresh page.

By dawn, the room had changed. One of the figures by the window was no
longer half-finished, and Hana, very quietly, was no longer alone.
""".strip()

with Supertone(api_key=os.environ["SUPERTONE_API_KEY"]) as client:
    response = client.text_to_speech.create_speech(
        voice_id=VOICE_ID,
        text=SCRIPT,
        language="en",
        model="sona_speech_2",
        voice_settings={"pitch_variance": 0.9, "speed": 0.95},
    )

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

print("Saved narration.wav")

TypeScript

import { Supertone } from "@supertone/supertone";
import * as fs from "node:fs";

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

const SCRIPT = `
Chapter one. The clocktower struck midnight, and the wind through the old
square carried whispers from the workshops below. Hana adjusted her coat,
checked the address one more time, and stepped through the iron gate.

Inside, the air smelled of copper and lemon polish. Rows of half-finished
automatons stared back from the shelves, each one waiting for a name. She
set her satchel on the bench and opened her notebook to a fresh page.

By dawn, the room had changed. One of the figures by the window was no
longer half-finished, and Hana, very quietly, was no longer alone.
`.trim();

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

const response = await client.textToSpeech.createSpeech({
  voiceId: VOICE_ID,
  apiConvertTextToSpeechUsingCharacterRequest: {
    text: SCRIPT,
    language: "en",
    model: "sona_speech_2",
    voiceSettings: { pitchVariance: 0.9, speed: 0.95 },
  },
});

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

console.log("Saved narration.wav");

내부에서 일어나는 일

  1. SDK는 SCRIPT.length > 300임을 감지합니다.
  2. 우선 문장 부호를 기준으로 분할하고, 한 문장 자체가 너무 길면 단어 경계로 다시 분할합니다.
  3. Python SDK는 최대 3개의 create_speech 요청을 병렬로 실행하며, TypeScript SDK는 순차적으로 실행합니다.
  4. 각 세그먼트는 완전한 오디오 파일을 반환합니다.
  5. SDK는 첫 세그먼트 이후의 모든 세그먼트에서 WAV 헤더를 제거한 뒤, 바이트를 이어 붙여 하나의 연속된 클립으로 만듭니다.
  6. 그 결과 단일 세그먼트 응답과 동일한 형식의 재생 가능한 파일 하나를 받게 됩니다.

  • 문장 부호가 효과적입니다. 문장 부호가 잘 표기된 원문일수록 더 깔끔하게 분할됩니다. 스크립트가 기계 번역이나 음성 인식 결과라면 . / ? / !를 추가하는 것만으로 결과가 좋아집니다.
  • 보이스 설정은 그대로 전파됩니다. 동일한 voice_settings가 모든 세그먼트에 적용되므로, 병합된 오디오의 톤이 일관되게 유지됩니다.
  • 먼저 예측해 보세요. predict_duration은 자동 청크 분할을 하지 않지만, 스크립트를 몇 개의 문장으로 직접 나누어 각각에 대해 predict_duration을 호출하고 결과를 합산하면 비용을 예측할 수 있습니다.
  • 적합한 모델을 선택하세요. 긴 내레이션에서는 sona_speech_2가 가장 자연스러운 발화를 만들어 냅니다. 많은 내레이션을 빠르게 생성해야 한다면 sona_speech_2_flash로 전환하세요.

관련 문서

장문 텍스트

300자 제한과 청크 분할 동작에 대한 전체 레퍼런스입니다.

보이스 설정

내레이션의 발화 방식을 세밀하게 조정하세요.