> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# テキスト読み上げのストリーミング

このガイドでは、ファイルとして音声を生成する方法、オーディオレスポンスを直接ストリーミングする方法、さらに必要に応じて生成したオーディオをAWS S3バケットにアップロードして署名付きURLで共有する方法の3つを紹介します。

> **Note**
>
> このガイドでは、[APIキーとSDKのセットアップ](/docs/ja/eleven-api/quickstart) が完了していることを前提としています。まだの場合は、先に
> クイックスタートを完了してください。S3へのアップロードは任意ですが、S3にアクセスできるAWSアカウントも
> 必要です。

> **Tip**
>
> ストリーミングの仕組みに興味がありますか？[オーディオストリーミングの 仕組み](/docs/ja/eleven-api/concepts/audio-streaming)では、プロトコル、バッファリング、
> レイテンシーのトレードオフを詳しく解説しています。

## テキストを音声に変換する（ファイル）

テキストを音声に変換してファイルとして保存するには、ElevenLabs SDKの`convert`メソッドを使用し、ローカルに`.mp3`ファイルとして保存します。

**`Python`**

```python Python

import os
import uuid
from dotenv import load_dotenv
from elevenlabs import VoiceSettings
from elevenlabs.client import ElevenLabs

load_dotenv()

ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
elevenlabs = ElevenLabs(
    api_key=ELEVENLABS_API_KEY,
)


def text_to_speech_file(text: str) -> str:
    # Calling the text_to_speech conversion API with detailed parameters
    response = elevenlabs.text_to_speech.convert(
        voice_id="pNInz6obpgDQGcFmaJgB", # Adam pre-made voice
        output_format="mp3_22050_32",
        text=text,
        model_id="eleven_flash_v2_5", # use the flash model for low latency
        # Optional voice settings that allow you to customize the output
        voice_settings=VoiceSettings(
            stability=0.0,
            similarity_boost=1.0,
            style=0.0,
            use_speaker_boost=True,
            speed=1.0,
        ),
    )

    # uncomment the line below to play the audio back
    # play(response)

    # Generating a unique file name for the output MP3 file
    save_file_path = f"{uuid.uuid4()}.mp3"

    # Writing the audio to a file
    with open(save_file_path, "wb") as f:
        for chunk in response:
            if chunk:
                f.write(chunk)

    print(f"{save_file_path}: A new audio file was saved successfully!")

    # Return the path of the saved audio file
    return save_file_path

```

**`TypeScript`**

```typescript TypeScript
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import * as dotenv from "dotenv";
import { createWriteStream } from "fs";
import { v4 as uuid } from "uuid";

dotenv.config();

const ELEVENLABS_API_KEY = process.env.ELEVENLABS_API_KEY;

const elevenlabs = new ElevenLabsClient({
  apiKey: ELEVENLABS_API_KEY,
});

export const createAudioFileFromText = async (text: string): Promise<string> => {
  return new Promise<string>(async (resolve, reject) => {
    try {
      const audio = await elevenlabs.textToSpeech.convert("JBFqnCBsd6RMkjVDRZzb", {
        modelId: "eleven_v4",
        text,
        outputFormat: "mp3_44100_128",
        // Optional voice settings that allow you to customize the output
        voiceSettings: {
          stability: 0,
          similarityBoost: 0,
          useSpeakerBoost: true,
          speed: 1.0,
        },
      });

      const fileName = `${uuid()}.mp3`;
      const fileStream = createWriteStream(fileName);

      audio.pipe(fileStream);
      fileStream.on("finish", () => resolve(fileName)); // Resolve with the fileName
      fileStream.on("error", reject);
    } catch (error) {
      reject(error);
    }
  });
};
```

続けて、次のようにこの関数を実行できます。

**`Python`**

```python Python
text_to_speech_file("Hello World")
```

**`TypeScript`**

```typescript TypeScript
await createAudioFileFromText("Hello World");
```

## テキストを音声に変換する（ストリーミング）

ファイルに保存せずオーディオを直接ストリーミングしたい場合は、ストリーミング機能を使用できます。

**`Python`**

```python Python

import os
from typing import IO
from io import BytesIO
from dotenv import load_dotenv
from elevenlabs import VoiceSettings
from elevenlabs.client import ElevenLabs

load_dotenv()

ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
elevenlabs = ElevenLabs(
    api_key=ELEVENLABS_API_KEY,
)


def text_to_speech_stream(text: str) -> IO[bytes]:
    # Perform the text-to-speech conversion
    response = elevenlabs.text_to_speech.stream(
        voice_id="pNInz6obpgDQGcFmaJgB", # Adam pre-made voice
        output_format="mp3_22050_32",
        text=text,
        model_id="eleven_multilingual_v2",
        # Optional voice settings that allow you to customize the output
        voice_settings=VoiceSettings(
            stability=0.0,
            similarity_boost=1.0,
            style=0.0,
            use_speaker_boost=True,
            speed=1.0,
        ),
    )

    # Create a BytesIO object to hold the audio data in memory
    audio_stream = BytesIO()

    # Write each chunk of audio data to the stream
    for chunk in response:
        if chunk:
            audio_stream.write(chunk)

    # Reset stream position to the beginning
    audio_stream.seek(0)

    # Return the stream for further use
    return audio_stream

```

**`TypeScript`**

```typescript TypeScript
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import * as dotenv from "dotenv";

dotenv.config();

const ELEVENLABS_API_KEY = process.env.ELEVENLABS_API_KEY;

if (!ELEVENLABS_API_KEY) {
  throw new Error("Missing ELEVENLABS_API_KEY in environment variables");
}

const elevenlabs = new ElevenLabsClient({
  apiKey: ELEVENLABS_API_KEY,
});

export const createAudioStreamFromText = async (text: string): Promise<Buffer> => {
  const audioStream = await elevenlabs.textToSpeech.stream("JBFqnCBsd6RMkjVDRZzb", {
    modelId: "eleven_v4",
    text,
    outputFormat: "mp3_44100_128",
    // Optional voice settings that allow you to customize the output
    voiceSettings: {
      stability: 0,
      similarityBoost: 1.0,
      useSpeakerBoost: true,
      speed: 1.0,
    },
  });

  const chunks: Buffer[] = [];
  for await (const chunk of audioStream) {
    chunks.push(chunk);
  }

  const content = Buffer.concat(chunks);
  return content;
};
```

続けて、次のようにこの関数を実行できます。

**`Python`**

```python Python
text_to_speech_stream("This is James")
```

**`TypeScript`**

```typescript TypeScript
await createAudioStreamFromText("This is James");
```

## ボーナス：AWS S3へのアップロードと安全な共有リンクの取得

オーディオデータをファイルまたはストリームとして作成したら、ユーザーと共有したくなるかもしれません。その方法の1つは、AWS S3バケットにアップロードして安全な共有リンクを生成することです。

#### AWS認証情報を作成する

データをS3にアップロードするには、AWSアクセスキーID、シークレットアクセスキー、AWSリージョン名を`.env`ファイルに追加する必要があります。認証情報を確認するには、次の手順に従ってください。

1. AWS Management Consoleにログインします。AWSホームページにアクセスし、アカウントでサインインします。

![](/docs/_fern-img/e9f1f1b1950962c3d67ea25a0593ca989d33c9f49b641e22eb3f861fc72735e3.webp)

2. IAM（Identity and Access Management）ダッシュボードにアクセスします。サービスメニューの「Security, Identity, & Compliance」からIAMを見つけられます。IAMダッシュボードでは、AWSサービスへのアクセスを安全に管理できます。

![](/docs/_fern-img/d6fa7e75879e7537693c4edde16d0ac5face78d72b00de50743a754c0681a5e3.webp)

3. 新しいユーザーを作成します（必要な場合）。IAMダッシュボードで「Users」を選択し、「Add user」を選択します。ユーザー名を入力します。

![](/docs/_fern-img/47b05ffda6925e4e14147aadc296d7c86cbd3340aaa1025083f1e1464b230f51.webp)

4. 権限を設定します。付与したいアクセスレベルに応じて、ポリシーをユーザーに直接アタッチします。S3へのアップロードには、AmazonS3FullAccessポリシーを使用できます。ただし、タスクの実行に必要な最小限の権限だけを付与する、最小権限の原則に従うことをおすすめします。S3バケットに対して必要なアクションのみを許可するカスタムポリシーを作成するとよいでしょう。

![](/docs/_fern-img/4b88bba4f5bb1509aa087a1ab5cc8068a274b17d8887c563f050b77e8438bb94.webp)

5. ユーザーを確認して作成します。設定を確認してユーザーを作成します。作成すると、アクセスキーIDとシークレットアクセスキーが表示されます。これらの認証情報は必ずダウンロードして安全に保存してください。この手順以降、シークレットアクセスキーを再取得することはできません。

![](/docs/_fern-img/27dcdff3681522cf936ff6bfb81cf216ada1fe401c7c1dbd10e58cead8a48abc.webp)

6. AWSリージョン名を取得します。例：us-east-1

![](/docs/_fern-img/016bc11c2f040942b215366c5fc9ac8e01f6261f5ebd44a3456d4b7ba97e9ae8.webp)

AWS S3バケットがない場合は、次の手順で新しく作成する必要があります。

1. S3ダッシュボードにアクセスします。サービスメニューの「Storage」からS3を見つけられます。

![](/docs/_fern-img/d2455fa92ce6dfa705c3b91144fe22539fae1611848cb8e3cc2dac20e57db4e7.webp)

2. 新しいバケットを作成します。S3ダッシュボードで「Create bucket」ボタンをクリックします。

![](/docs/_fern-img/3b7d5bdb6559e8511445b41b1bbdeed3f6674791cf23021a30ccb5aa8143be28.webp)

3. バケット名を入力し、「Create bucket」ボタンをクリックします。その他のバケットオプションはデフォルトのままで構いません。追加したバケットが一覧に表示されます。

![](/docs/_fern-img/68d23f21bec1e3aa70b18f09c40c9bdace5ff0dd63edc17c6807e7ddac75758d.webp)![](/docs/_fern-img/63f7af93d4a73fab3011853c8393c954400d9f344a5811ec90b86d6c69b2ec16.webp)

#### AWS SDKをインストールして認証情報を追加する

`pip`と`npm`を使用して、AWSサービスと連携するための`boto3`をインストールします。

**`Python`**

```bash Python
pip install boto3
```

**`TypeScript`**

```bash TypeScript
npm install @aws-sdk/client-s3
npm install @aws-sdk/s3-request-presigner
```

次に、以下のように環境変数を`.env`ファイルに追加します。

```
AWS_ACCESS_KEY_ID=your_aws_access_key_id_here
AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key_here
AWS_REGION_NAME=your_aws_region_name_here
AWS_S3_BUCKET_NAME=your_s3_bucket_name_here
```

#### AWS S3にアップロードして署名付きURLを生成する

オーディオストリームをS3にアップロードし、署名付きURLを生成するために、次の関数を追加します。

**`s3_uploader.py (Python)`**

```python s3_uploader.py (Python)

import os
import boto3
import uuid

AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
AWS_REGION_NAME = os.getenv("AWS_REGION_NAME")
AWS_S3_BUCKET_NAME = os.getenv("AWS_S3_BUCKET_NAME")

session = boto3.Session(
    aws_access_key_id=AWS_ACCESS_KEY_ID,
    aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
    region_name=AWS_REGION_NAME,
)
s3 = session.client("s3")


def generate_presigned_url(s3_file_name: str) -> str:
    signed_url = s3.generate_presigned_url(
        "get_object",
        Params={"Bucket": AWS_S3_BUCKET_NAME, "Key": s3_file_name},
        ExpiresIn=3600,
    )  # URL expires in 1 hour
    return signed_url


def upload_audiostream_to_s3(audio_stream) -> str:
    s3_file_name = f"{uuid.uuid4()}.mp3"  # Generates a unique file name using UUID
    s3.upload_fileobj(audio_stream, AWS_S3_BUCKET_NAME, s3_file_name)

    return s3_file_name

```

**`s3_uploader.ts (TypeScript)`**

```typescript s3_uploader.ts (TypeScript)
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import * as dotenv from "dotenv";
import { v4 as uuid } from "uuid";

dotenv.config();

const { AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION_NAME, AWS_S3_BUCKET_NAME } =
  process.env;

if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY || !AWS_REGION_NAME || !AWS_S3_BUCKET_NAME) {
  throw new Error("One or more environment variables are not set. Please check your .env file.");
}

const s3 = new S3Client({
  credentials: {
    accessKeyId: AWS_ACCESS_KEY_ID,
    secretAccessKey: AWS_SECRET_ACCESS_KEY,
  },
  region: AWS_REGION_NAME,
});

export const generatePresignedUrl = async (objectKey: string) => {
  const getObjectParams = {
    Bucket: AWS_S3_BUCKET_NAME,
    Key: objectKey,
    Expires: 3600,
  };
  const command = new GetObjectCommand(getObjectParams);
  const url = await getSignedUrl(s3, command, { expiresIn: 3600 });
  return url;
};

export const uploadAudioStreamToS3 = async (audioStream: Buffer) => {
  const remotePath = `${uuid()}.mp3`;
  await s3.send(
    new PutObjectCommand({
      Bucket: AWS_S3_BUCKET_NAME,
      Key: remotePath,
      Body: audioStream,
      ContentType: "audio/mpeg",
    })
  );
  return remotePath;
};
```

テキストから作成したオーディオストリームを使用して、アップロード関数を呼び出せます。

**`Python`**

```python Python
s3_file_name = upload_audiostream_to_s3(audio_stream)
```

**`TypeScript`**

```typescript TypeScript
const s3path = await uploadAudioStreamToS3(stream);
```

オーディオファイルをS3にアップロードした後、ファイルへのアクセスを共有するための署名付きURLを生成します。このURLには有効期限があるため、一定時間後に期限切れとなり、一時的な共有を安全に行えます。

次のようにファイルからURLを生成できます。

**`Python`**

```python Python
signed_url = generate_presigned_url(s3_file_name)
print(f"Signed URL to access the file: {signed_url}")
```

**`TypeScript`**

```typescript TypeScript
const presignedUrl = await generatePresignedUrl(s3path);
console.log("Presigned URL:", presignedUrl);
```

ファイルを複数回使用する場合は、期限切れになる署名付きURLを直接保存するのではなく、S3ファイルパスをデータベースに保存し、必要になるたびに署名付きURLを再生成してください。

#### すべてを組み合わせる

すべてを組み合わせるには、次のスクリプトを使用できます。

**`main.py (Python)`**

```python main.py (Python)

import os

from dotenv import load_dotenv

load_dotenv()

from text_to_speech_stream import text_to_speech_stream
from s3_uploader import upload_audiostream_to_s3, generate_presigned_url


def main():
    text = "This is James"

    audio_stream = text_to_speech_stream(text)
    s3_file_name = upload_audiostream_to_s3(audio_stream)
    signed_url = generate_presigned_url(s3_file_name)

    print(f"Signed URL to access the file: {signed_url}")


if __name__ == "__main__":
    main()

```

**`index.ts (Typescript)`**

```typescript index.ts (Typescript)
import "dotenv/config";

import { generatePresignedUrl, uploadAudioStreamToS3 } from "./s3_uploader";
import { createAudioFileFromText } from "./text_to_speech_file";
import { createAudioStreamFromText } from "./text_to_speech_stream";

(async () => {
  // save the audio file to disk
  const fileName = await createAudioFileFromText(
    "Today, the sky is exceptionally clear, and the sun shines brightly."
  );

  console.log("File name:", fileName);

  // OR stream the audio, upload to S3, and get a presigned URL
  const stream = await createAudioStreamFromText(
    "Today, the sky is exceptionally clear, and the sun shines brightly."
  );

  const s3path = await uploadAudioStreamToS3(stream);

  const presignedUrl = await generatePresignedUrl(s3path);

  console.log("Presigned URL:", presignedUrl);
})();
```

## まとめ

これで、テキストを音声に変換し、オーディオファイルを共有するための署名付きURLを生成する方法がわかりました。この機能により、コンテンツを動的に作成・共有するための多くの可能性が広がります。

この機能で構築できるものの例を紹介します。

1. **教育ポッドキャスト**：生徒が必要なときにアクセスできる、パーソナライズされた教育コンテンツを作成できます。教師は授業をオーディオ形式に変換してS3にアップロードし、リンクを生徒と共有することで、従来の教室外でもより魅力的な学習体験を提供できます。

2. **Webサイトのアクセシビリティ機能**：テキストコンテンツをオーディオ形式で提供することで、Webサイトのアクセシビリティを向上できます。視覚障害のある方や、聴覚による学習を好む方にとって、Webサイト上の情報がより利用しやすくなります。

3. **自動カスタマーサポートメッセージ**：FAQや注文状況の更新など、カスタマーサポート向けの自動化されたパーソナライズ音声メッセージを作成できます。従来のテキストメールよりも魅力的な顧客体験を提供できます。

4. **オーディオブックとナレーション**：書籍全体や短編小説をオーディオ形式に変換し、読者に文学を楽しむ新たな方法を提供できます。著者や出版社はコンテンツの提供方法を多様化し、読むより聴くことを好むユーザーにも届けられます。

5. **語学学習ツール**：学習者にオーディオレッスンや演習を提供する語学学習支援ツールを開発できます。発音やリスニングスキルを目的に合わせて練習できます。

## 次のステップ

#### [WebSocketストリーミング](/docs/ja/eleven-api/guides/how-to/websockets/realtime-tts)

LLMによる生成と同時に、WebSocketを使用してテキスト読み上げをリアルタイムでストリーミングします。

#### [レイテンシーを理解する](/docs/ja/eleven-api/concepts/latency)

レイテンシーに影響する要因と、最初のオーディオが届くまでの時間を最小限に抑える方法を学びます。