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

# Streaming de texto a voz

Esta guía explica tres enfoques: generar voz como archivo, transmitir la respuesta de audio directamente y, de forma opcional, subir el audio generado a un bucket de AWS S3 para compartirlo mediante una URL firmada.

> **Note**
>
> Esta guía presupone que ya has [configurado tu clave de API y el SDK](/docs/es/eleven-api/quickstart). Completa
> primero la guía de inicio rápido si aún no lo has hecho. La sección opcional de carga a S3 también requiere una cuenta de AWS
> con acceso a S3.

> **Tip**
>
> ¿Tienes curiosidad por saber cómo funciona el streaming? [Entender el streaming de audio](/docs/es/eleven-api/concepts/audio-streaming) explica en detalle el protocolo, el almacenamiento en búfer y las
> compensaciones de latencia.

## Convierte texto en voz (archivo)

Para convertir texto en voz y guardarlo como archivo, usaremos el método `convert` del SDK de ElevenLabs y después lo guardaremos localmente como archivo `.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);
    }
  });
};
```

Después puedes ejecutar esta función con:

**`Python`**

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

**`TypeScript`**

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

## Convierte texto en voz (streaming)

Si prefieres transmitir el audio directamente sin guardarlo en un archivo, puedes usar nuestra función de streaming.

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

Después puedes ejecutar esta función con:

**`Python`**

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

**`TypeScript`**

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

## Extra: subir a AWS S3 y obtener un enlace seguro para compartir

Una vez que tus datos de audio se hayan creado como archivo o como flujo, quizá quieras compartirlos con tus usuarios. Una forma de hacerlo es subirlos a un bucket de AWS S3 y generar un enlace seguro para compartirlos.

#### Crear tus credenciales de AWS

Para subir los datos a S3, tendrás que añadir el ID de la clave de acceso de AWS, la clave de acceso secreta y el nombre de la región de AWS a tu archivo `.env`. Sigue estos pasos para encontrar las credenciales:

1. Inicia sesión en la consola de administración de AWS: ve a la página de inicio de AWS e inicia sesión con tu cuenta.

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

2. Accede al panel de IAM (Identity and Access Management): puedes encontrar IAM en «Security, Identity, & Compliance» en el menú de servicios. El panel de IAM gestiona de forma segura el acceso a tus servicios de AWS.

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

3. Crea un usuario nuevo (si es necesario): en el panel de IAM, selecciona «Users» y después «Add user». Introduce un nombre de usuario.

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

4. Configura los permisos: asocia políticas directamente al usuario según el nivel de acceso que quieras conceder. Para las cargas en S3, puedes usar la política AmazonS3FullAccess. Sin embargo, se recomienda conceder el mínimo privilegio o los permisos mínimos necesarios para realizar una tarea. Puede que quieras crear una política personalizada que permita específicamente solo las acciones necesarias en tu bucket de S3.

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

5. Revisa y crea el usuario: revisa la configuración y crea el usuario. Al crearlo, se te mostrarán un ID de clave de acceso y una clave de acceso secreta. Asegúrate de descargar y guardar estas credenciales de forma segura; la clave de acceso secreta no se podrá recuperar después de este paso.

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

6. Obtén el nombre de la región de AWS: p. ej., us-east-1

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

Si no tienes un bucket de AWS S3, tendrás que crear uno nuevo siguiendo estos pasos:

1. Accede al panel de S3: puedes encontrar S3 en «Storage» en el menú de servicios.

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

2. Crea un bucket nuevo: en el panel de S3, haz clic en el botón «Create bucket».

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

3. Introduce un nombre de bucket y haz clic en el botón «Create bucket». Puedes dejar el resto de opciones del bucket con los valores predeterminados. El bucket recién añadido aparecerá en la lista.

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

#### Instalar el SDK de AWS y añadir las credenciales

Instala `boto3` para interactuar con los servicios de AWS mediante `pip` y `npm`.

**`Python`**

```bash Python
pip install boto3
```

**`TypeScript`**

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

A continuación, añade las variables de entorno al archivo `.env` de esta forma:

```
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
```

#### Subir a AWS S3 y generar la URL firmada

Añade las siguientes funciones para subir el flujo de audio a S3 y generar una URL firmada.

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

Después puedes llamar a la función de carga con el flujo de audio del texto.

**`Python`**

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

**`TypeScript`**

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

Después de subir el archivo de audio a S3, genera una URL firmada para compartir el acceso al archivo. Esta URL tendrá una duración limitada, es decir, caducará después de un periodo determinado, lo que la hace segura para compartirla temporalmente.

Ahora puedes generar una URL a partir de un archivo con:

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

Si quieres usar el archivo varias veces, debes guardar la ruta del archivo de S3 en tu base de datos y regenerar la URL firmada cada vez que la necesites, en lugar de guardar directamente la URL firmada, ya que caducará.

#### Unirlo todo

Para unirlo todo, puedes usar el siguiente script:

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

## Conclusión

Ahora ya sabes cómo convertir texto en voz y generar una URL firmada para compartir el archivo de audio. Esta funcionalidad abre numerosas posibilidades para crear y compartir contenido de forma dinámica.

Estos son algunos ejemplos de lo que podrías crear con ella.

1. **Podcasts educativos**: crea contenido educativo personalizado al que el alumnado pueda acceder bajo demanda. El profesorado puede convertir sus lecciones a formato de audio, subirlas a S3 y compartir los enlaces con el alumnado para ofrecer una experiencia de aprendizaje más atractiva fuera del entorno tradicional del aula.

2. **Funciones de accesibilidad para sitios web**: mejora la accesibilidad de los sitios web ofreciendo contenido de texto en formato de audio. Esto puede hacer que la información de los sitios web sea más accesible para personas con discapacidad visual o para quienes prefieren el aprendizaje auditivo.

3. **Mensajes automatizados de atención al cliente**: crea mensajes de audio automatizados y personalizados para atención al cliente, como preguntas frecuentes o actualizaciones de pedidos. Esto puede ofrecer una experiencia de cliente más atractiva que los correos electrónicos de texto tradicionales.

4. **Audiolibros y narración**: convierte libros completos o relatos cortos a formato de audio, ofreciendo al público una nueva forma de disfrutar de la literatura. Autores y editoriales pueden diversificar su oferta de contenido y llegar a quienes prefieren escuchar en lugar de leer.

5. **Herramientas de aprendizaje de idiomas**: desarrolla recursos para el aprendizaje de idiomas que proporcionen lecciones y ejercicios de audio. Así es posible practicar la pronunciación y la comprensión auditiva de forma específica.

## Próximos pasos

#### [Streaming con WebSocket](/docs/es/eleven-api/guides/how-to/websockets/realtime-tts)

Usa WebSockets para transmitir texto a voz en tiempo real a medida que lo genera un LLM.

#### [Entender la latencia](/docs/es/eleven-api/concepts/latency)

Descubre qué contribuye a la latencia y cómo reducir el tiempo hasta el primer audio.