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

# Gere áudio em tempo real

O streaming por WebSocket é um método de envio e recebimento de dados em uma única conexão de longa duração. Esse método é útil para aplicações em tempo real nas quais você precisa transmitir dados de áudio assim que eles ficam disponíveis.

Se quiser testar rapidamente a latência (tempo até o primeiro byte) de uma conexão WebSocket com a API de conversão de texto em voz da ElevenLabs, você pode instalar `elevenlabs-latency` via `npm` e seguir as instruções [aqui](https://www.npmjs.com/package/elevenlabs-latency?activeTab=readme).

> **Note**
>
> Os WebSockets estão disponíveis para Text to Speech e para a Plataforma de Agentes. Este guia aborda o WebSocket de **Text
> to Speech** (`/v1/text-to-speech/{voice_id}/stream-input`). Esse endpoint **não** oferece suporte aos modelos
> `eleven_v3` nem `eleven_v4`. Para diálogos com **Eleven v3** ou **Eleven v4** por WebSocket, consulte [Texto em Tempo Real para Diálogo](/docs/pt/eleven-api/guides/how-to/websockets/realtime-tdd)
> e [WebSockets de Text to Speech vs. Texto para Diálogo](/docs/pt/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets).

## Requisitos

* Uma conta ElevenLabs com uma chave de API (veja como [encontrar sua chave de API](/docs/pt/api-reference/authentication)).
* Python ou Node.js (ou outro ambiente de execução JavaScript) instalado na sua máquina

## Configuração

Instale as dependências necessárias:

**`Python`**

```python Python
pip install python-dotenv
pip install websockets
```

**`TypeScript`**

```typescript TypeScript
npm install dotenv
npm install @types/dotenv --save-dev
npm install ws
```

Em seguida, crie um arquivo `.env` no diretório do projeto e adicione sua chave de API:

**`.env`**

```bash .env
ELEVENLABS_API_KEY=your_elevenlabs_api_key_here
```

## Inicie a conexão WebSocket

Depois de escolher uma voz na Voice Library e o modelo de conversão de texto em voz que deseja usar, inicie uma conexão WebSocket com a API de conversão de texto em voz.

**`text-to-speech-websocket.py`**

```python text-to-speech-websocket.py
import os
from dotenv import load_dotenv
import websockets

# Load the API key from the .env file
load_dotenv()
ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")

voice_id = 'Xb7hH8MSUJpSbSDYk0k2'

# For use cases where latency is important, we recommend using the 'eleven_flash_v2_5' model.
model_id = 'eleven_flash_v2_5'

async def text_to_speech_ws_streaming(voice_id, model_id):
    uri = f"wss://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream-input?model_id={model_id}"

    async with websockets.connect(uri) as websocket:
       ...
```

**`text-to-speech-websocket.ts`**

```typescript text-to-speech-websocket.ts
import * as dotenv from "dotenv";
import * as fs from "node:fs";
import WebSocket from "ws";

// Load the API key from the .env file
dotenv.config();
const ELEVENLABS_API_KEY = process.env.ELEVENLABS_API_KEY;

const voiceId = "Xb7hH8MSUJpSbSDYk0k2";

// For use cases where latency is important, we recommend using the 'eleven_flash_v2_5' model.
const model = "eleven_flash_v2_5";

const uri = `wss://api.elevenlabs.io/v1/text-to-speech/${voiceId}/stream-input?model_id=${model}`;
const websocket = new WebSocket(uri, {
  headers: { "xi-api-key": `${ELEVENLABS_API_KEY}` },
});

// Create a directory for saving the audio
const outputDir = "./output";

try {
  fs.accessSync(outputDir, fs.constants.R_OK | fs.constants.W_OK);
} catch (err) {
  fs.mkdirSync(outputDir);
}

// Create a write stream for saving the audio into mp3
const writeStream = fs.createWriteStream(outputDir + "/test.mp3", {
  flags: "a",
});
```

## Envie o texto de entrada

Quando a conexão WebSocket estiver aberta, configure primeiro as definições de voz. Em seguida, envie a mensagem de texto para a API.

**`text-to-speech-websocket.py`**

```python text-to-speech-websocket.py
async def text_to_speech_ws_streaming(voice_id, model_id):
    async with websockets.connect(uri) as websocket:
        await websocket.send(json.dumps({
            "text": " ",
            "voice_settings": {"stability": 0.5, "similarity_boost": 0.8, "use_speaker_boost": False},
            "generation_config": {
                "chunk_length_schedule": [120, 160, 250, 290]
            },
            "xi_api_key": ELEVENLABS_API_KEY,
        }))

        text = "The twilight sun cast its warm golden hues upon the vast rolling fields, saturating the landscape with an ethereal glow. Silently, the meandering brook continued its ceaseless journey, whispering secrets only the trees seemed privy to."
        await websocket.send(json.dumps({"text": text}))

        # Send empty string to indicate the end of the text sequence which will close the WebSocket connection
        await websocket.send(json.dumps({"text": ""}))
```

**`text-to-speech-websocket.ts`**

```typescript text-to-speech-websocket.ts
const text =
  "The twilight sun cast its warm golden hues upon the vast rolling fields, saturating the landscape with an ethereal glow. Silently, the meandering brook continued its ceaseless journey, whispering secrets only the trees seemed privy to.";

websocket.on("open", async () => {
  websocket.send(
    JSON.stringify({
      text: " ",
      voice_settings: {
        stability: 0.5,
        similarity_boost: 0.8,
        use_speaker_boost: false,
      },
      generation_config: { chunk_length_schedule: [120, 160, 250, 290] },
    })
  );

  websocket.send(JSON.stringify({ text: text }));

  // Send empty string to indicate the end of the text sequence which will close the websocket connection
  websocket.send(JSON.stringify({ text: "" }));
});
```

## Salve o áudio em um arquivo

Leia a mensagem recebida da conexão WebSocket e grave os blocos de áudio em um arquivo local.

**`text-to-speech-websocket.py`**

```python text-to-speech-websocket.py
import asyncio

async def write_to_local(audio_stream):
    """Write the audio encoded in base64 string to a local mp3 file."""

    with open(f'./output/test.mp3', "wb") as f:
        async for chunk in audio_stream:
            if chunk:
                f.write(chunk)

async def listen(websocket):
    """Listen to the websocket for audio data and stream it."""

    while True:
        try:
            message = await websocket.recv()
            data = json.loads(message)
            if data.get("audio"):
                yield base64.b64decode(data["audio"])
            elif data.get('isFinal'):
                break

        except websockets.exceptions.ConnectionClosed:
            print("Connection closed")
            break

async def text_to_speech_ws_streaming(voice_id, model_id):
    async with websockets.connect(uri) as websocket:
          ...
          # Add listen task to submit the audio chunks to the write_to_local function
          listen_task = asyncio.create_task(write_to_local(listen(websocket)))

          await listen_task

asyncio.run(text_to_speech_ws_streaming(voice_id, model_id))
```

**`text-to-speech-websocket.ts`**

```typescript text-to-speech-websocket.ts
// Helper function to write the audio encoded in base64 string into local file
function writeToLocal(base64str: any, writeStream: fs.WriteStream) {
  const audioBuffer: Buffer = Buffer.from(base64str, "base64");
  writeStream.write(audioBuffer, (err) => {
    if (err) {
      console.error("Error writing to file:", err);
    }
  });
}

// Listen to the incoming message from the websocket connection
websocket.on("message", function incoming(event) {
  const data = JSON.parse(event.toString());
  if (data["audio"]) {
    writeToLocal(data["audio"], writeStream);
  }
});

// Close the writeStream when the websocket connection closes
websocket.on("close", () => {
  writeStream.end();
});
```

## Execute o script

Você pode executar o script rodando o comando a seguir no terminal. Um arquivo de áudio mp3 será salvo no diretório `output`.

**`Python`**

```python Python
python text-to-speech-websocket.py
```

**`TypeScript`**

```typescript TypeScript
npx tsx text-to-speech-websocket.ts
```

## Configuração avançada

O uso de WebSockets oferece algumas configurações avançadas que você pode usar para ajustar a geração de áudio em tempo real.

### Bufferização

Ao gerar áudio em tempo real, é importante considerar dois conceitos: Tempo Até o Primeiro Byte (TTFB) e bufferização. Para produzir áudio de alta qualidade e deduzir o contexto, o modelo exige uma determinada quantidade mínima de texto de entrada. Quanto mais texto for enviado em uma conexão WebSocket, melhor será a qualidade do áudio. Se essa quantidade mínima não for atingida, o modelo adicionará o texto a um buffer e gerará o áudio quando o buffer estiver cheio.

Em termos de latência, o TTFB é o tempo necessário para que o primeiro byte de áudio seja enviado ao cliente. Isso é importante porque afeta a latência percebida do áudio. Portanto, talvez você queira controlar o tamanho do buffer para equilibrar qualidade e latência.

Para gerenciar isso, você pode usar o parâmetro `chunk_length_schedule` ao inicializar a conexão WebSocket ou ao enviar texto. Esse parâmetro é uma matriz de números inteiros que representa a quantidade de caracteres que será enviada ao modelo antes da geração do áudio. Por exemplo, se você definir `chunk_length_schedule` como `[120, 160, 250, 290]`, o modelo gerará áudio depois que 120, 160, 250 e 290 caracteres forem enviados, respectivamente.

Veja como isso funciona com as configurações padrão de `chunk_length_schedule`:

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

No diagrama acima, o áudio só é gerado após a segunda mensagem ser enviada ao servidor. Isso acontece porque a primeira mensagem está abaixo do limite de 120 caracteres, enquanto a segunda eleva o total de caracteres acima desse limite. A terceira mensagem está acima do limite de 160 caracteres, então o áudio é gerado imediatamente e retornado ao cliente.

Você pode especificar um valor personalizado para `chunk_length_schedule` ao inicializar a conexão WebSocket ou ao enviar texto.

```python
await websocket.send(json.dumps({
    "text": text,
    "generation_config": {
        # Generate audio after 50, 120, 160, and 290 characters have been sent
        "chunk_length_schedule": [50, 120, 160, 290]
    },
    "xi_api_key": ELEVENLABS_API_KEY,
}))
```

```typescript
websocket.send(
  JSON.stringify({
    text: text,
    // Generate audio after 50, 120, 160, and 290 characters have been sent
    generation_config: { chunk_length_schedule: [50, 120, 160, 290] },
    xi_api_key: ELEVENLABS_API_KEY,
  })
);
```

Caso queira forçar o retorno imediato do áudio, você pode usar `flush: true` para limpar o buffer e forçar a geração de qualquer texto armazenado nele. Isso pode ser útil, por exemplo, quando você chega ao fim de um documento e quer gerar o áudio da seção final.

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

Isso pode ser especificado por mensagem ao definir `flush: true` na mensagem.

```python
await websocket.send(json.dumps({"text": "Generate this audio immediately.", "flush": True}))
```

```typescript
websocket.send(JSON.stringify({ text: "Generate this audio immediately.", flush: true }));
```

Além disso, fechar o websocket forçará automaticamente a geração de qualquer texto armazenado no buffer.

### Definições de voz

Ao inicializar as conexões WebSocket, você pode especificar as definições de voz para as gerações subsequentes. Isso permite controlar a velocidade, a estabilidade e outras características de voz do áudio gerado.

```python
await websocket.send(json.dumps({
    "text": text,
    "voice_settings": {"stability": 0.5, "similarity_boost": 0.8, "use_speaker_boost": False},
}))
```

```typescript
websocket.send(
  JSON.stringify({
    text: text,
    voice_settings: { stability: 0.5, similarity_boost: 0.8, use_speaker_boost: false },
  })
);
```

Isso pode ser substituído por mensagem ao especificar `voice_settings` diferente na mensagem.

### Dicionários de pronúncia

Você pode usar dicionários de pronúncia para controlar a pronúncia de palavras ou frases específicas. Isso pode ser útil para garantir que certas palavras sejam pronunciadas corretamente ou para dar ênfase a determinadas palavras ou frases.

Diferentemente de `voice_settings` e `generation_config`, os dicionários de pronúncia devem ser especificados na mensagem "Initialize Connection". Consulte a [referência da API](/docs/pt/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#send.Initialize%20Connection.pronunciation_dictionary_locators) para mais informações.

> **Tip**
>
> Ao usar dicionários de pronúncia baseados em fonemas com WebSockets, você deve adicionar `enable_ssml_parsing=true` como parâmetro de consulta ao URI do WebSocket. Por exemplo:
>
> ```
> wss://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream-input?model_id={model_id}&enable_ssml_parsing=true
> ```

## Boas práticas

* Sugerimos usar a configuração padrão de `chunk_length_schedule` em `generation_config`.
* Ao desenvolver uma aplicação de agente conversacional em tempo real, recomendamos usar `flush: true` junto ao texto no fim de cada turno da conversa para garantir a geração de áudio no momento certo.
* Se a configuração padrão não oferecer a latência ideal para seu caso de uso, você pode modificar `chunk_length_schedule`. No entanto, lembre-se de que reduzir a latência com esse ajuste pode comprometer a qualidade.

## Dicas

* A conexão WebSocket será fechada automaticamente após 20 segundos de inatividade. Para mantê-la aberta, você pode enviar um único caractere de espaço `" "`. Observe que essa string deve incluir um espaço, pois enviar uma string totalmente vazia, `""`, fechará o WebSocket.
* Envie uma string vazia para fechar a conexão WebSocket após enviar a última mensagem de texto.
* Você pode usar `alignment` para obter os timestamps de cada palavra no texto. Isso pode ser útil para alinhar o áudio ao texto em um vídeo ou em outras aplicações que exigem temporização precisa. Consulte a [referência da API](/docs/pt/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#receive.Audio%20Output.alignment) para mais informações.

## Próximos passos

#### [Streaming de TTS](/docs/pt/eleven-api/guides/how-to/text-to-speech/streaming)

Use o streaming HTTP quando o texto de entrada estiver disponível antecipadamente, em vez de ser gerado em tempo real.

#### [Otimização de latência](/docs/pt/eleven-api/guides/how-to/best-practices/latency-optimization)

Reduza o tempo até o primeiro áudio com a seleção do modelo, a escolha da voz e o roteamento geográfico.