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

# 音声ストリーミング

> 合成中のオーディオチャンクを受信します — 1 つのクリップが長く、生成完了前に再生を開始したい場合に有用です。

<Note>
  このドキュメントは英語の原文から自動翻訳されています。表現に不自然な箇所がある場合があります。正確な内容は[英語の原文](/en/docs/text-to-speech/stream-speech)もあわせてご確認ください。
</Note>

`stream_speech` はオーディオをチャンク単位で返すため、クリップ全体の生成完了 **前** に再生や転送を開始できます。パスは `/v1/text-to-speech/{voice_id}/stream` です。

<Note>
  ストリーミングは現時点では **`sona_speech_1`** のみ対応しています。
</Note>

## ストリーミングを使うべき場面

ストリーミングは、**1 つの** TTS クリップが、最後まで待つと体感できるほど長い場合にもっとも有効です — たとえば、複数文からなる段落を 1 回の呼び出しで合成するケースです。

**対話型エージェントやチャットボット** のように、各発話が短い 1 文である場合は、高速な非ストリーミングモデルを使うほうがトータルのレイテンシが小さくなるのが一般的です。

* **`sona_speech_2_flash`** — 速度と品質のバランスが取れています。
* **`supertonic_api_3`** — 推論がもっとも高速で、発話の安定性も高いモデルです。time-to-first-audio が最優先のときに利用してください。

詳しい議論は [レイテンシ最適化](/ja/docs/production/latency-optimization) をご覧ください。[LLM レスポンスから TTS をストリーミングする](/ja/docs/examples/llm-streaming-tts) で紹介している文単位のパターンは、`stream_speech` を一切使いません — 文ごとに高速な非ストリーミングモデルを呼び出す方式に基づいています。

## 基本のストリーミング

<Tabs>
  <Tab title="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)
    ```
  </Tab>

  <Tab title="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())
    ```
  </Tab>

  <Tab title="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));
    }
    ```
  </Tab>

  <Tab title="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` は受信したチャンクをそのままファイルに書き込みます。
  </Tab>
</Tabs>

## リクエストフィールド

[Create speech](/ja/docs/text-to-speech/create-speech) と同じです。ただし `model` は `sona_speech_1`（現在ストリーミングに対応している唯一のモデル）に固定されます。パスは `/v1/text-to-speech/{voice_id}/stream` です。

## レスポンス

デフォルトでは、レスポンスボディは **バイナリオーディオストリーム** で、`Content-Type` は `output_format` に対応します。

* `audio/wav` — WAV ファイルのチャンク（最初のチャンクに WAV ヘッダーが含まれます）。
* `audio/mpeg` — MP3 ファイルのチャンク。

`include_phonemes=true` の場合、レスポンスは **NDJSON** に切り替わり、1 行ごとに 1 つの JSON オブジェクト（Base64 オーディオチャンクと対応する音素データを含む）が返されます。

## 長い入力のストリーミング

SDK はストリーミング時でも 300 文字を超えるテキストを自動的にチャンク分割します。内部ではテキストを分割し、順次ストリーミングリクエストを送信し、呼び出し側のイテレータにチャンクを転送します — そのため、読み取りループ側のコードは変わりません。

詳細は [Long text](/ja/docs/text-to-speech/long-text) をご覧ください。

## ヒント

* **プレイヤーのバッファリング。** ほとんどのプレイヤーは再生開始前にある程度のバッファを必要とします。最初のチャンクをすぐ再生するより、1〜2 秒バッファリングしてから再生したほうがスムーズに感じられます。
* **WAV と MP3。** WAV チャンクはサイズが大きくなりますが連結しやすく、MP3 ストリームはサイズが小さく低速ネットワークでの配信に向いています。
* **エラーハンドリング。** ストリームエラーは読み取りの途中で発生することがあります — 通常のエラーハンドラでイテレーションを包み、特に一時的な `429` や `5xx` レスポンスに対してはリトライできるようにしてください。[リトライとバックオフ](/ja/docs/production/retries-and-backoff) を参照してください。

## 関連項目

<CardGroup cols={2}>
  <Card title="LLM ストリーミング TTS" icon="robot" href="/ja/docs/examples/llm-streaming-tts">
    ボイスエージェント向けの文単位パターン。
  </Card>

  <Card title="レイテンシ最適化" icon="gauge-high" href="/ja/docs/production/latency-optimization">
    低レイテンシのためのモデルとパターンの選び方。
  </Card>
</CardGroup>
