> ## Documentation Index
> Fetch the complete documentation index at: https://daily-main.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Bland Text-to-Speech

> Realtime TTS with BlandTTSService (WebSocket streaming) and BlandHttpTTSService for complete-text synthesis.

## Overview

Bland provides two TTS service implementations:

* `BlandTTSService` for real-time synthesis using Bland's WebSocket API at `/v2/tts/ws`. Streams LLM tokens as they arrive and maintains a single connection for the whole conversation, with support for interruptions via Bland's `cancel` message.
* `BlandHttpTTSService` for complete-text synthesis using Bland's HTTP API at `/v2/tts`. Takes the complete text in one request. Voice agents should prefer `BlandTTSService` for streaming.

<CardGroup cols={2}>
  <Card title="Bland TTS API Reference" icon="code" href="https://reference-server.pipecat.ai/en/latest/api/pipecat.services.bland.tts.html">
    Pipecat's API methods for Bland TTS integration
  </Card>

  <Card title="WebSocket Example" icon="play" href="https://github.com/pipecat-ai/pipecat/blob/main/examples/voice/voice-bland.py">
    Complete streaming example with token-level streaming
  </Card>

  <Card title="HTTP Example" icon="play" href="https://github.com/pipecat-ai/pipecat/blob/main/examples/voice/voice-bland-http.py">
    Complete HTTP example with batch synthesis
  </Card>

  <Card title="Bland Documentation" icon="book" href="https://docs.bland.ai/api-v2/post/tts-ws">
    Official Bland TTS API documentation
  </Card>
</CardGroup>

## Installation

To use Bland TTS services, install the required dependencies:

```bash theme={null}
uv add "pipecat-ai[bland]"
```

## Prerequisites

### Bland Account Setup

Before using Bland TTS services, you need:

1. **Bland Account**: Sign up at [Bland AI](https://www.bland.ai/)
2. **API Key**: Generate an API key from your account dashboard
3. **Voice Selection**: Choose voice IDs from available Bland voices

### Required Environment Variables

* `BLAND_API_KEY`: Your Bland API key for authentication

## Configuration

### BlandTTSService

<ParamField path="api_key" type="str" required>
  Bland API key for authentication.
</ParamField>

<ParamField path="url" type="str" default="wss://api.bland.ai/v2/tts/ws">
  WebSocket URL for the Bland realtime TTS API.
</ParamField>

<ParamField path="sample_rate" type="int" default="None">
  Output sample rate in Hz. When `None`, uses the pipeline default. A rate Bland
  does not render (8000, 16000, 24000, 44100, 48000) is replaced with 48000 and
  resampled by the output transport.
</ParamField>

<ParamField path="text_aggregation_mode" type="TextAggregationMode" default="TextAggregationMode.TOKEN">
  How to aggregate incoming text before sending. Defaults to `TOKEN`, streaming
  LLM tokens straight to Bland for the lowest latency. Pass
  `TextAggregationMode.SENTENCE` to aggregate text into sentences before
  synthesis.
</ParamField>

<ParamField path="settings" type="BlandTTSService.Settings" default="None">
  Runtime-configurable settings. See [BlandTTSService
  Settings](#blandttsservice-settings) below.
</ParamField>

#### BlandTTSService Settings

Runtime-configurable settings passed via the `settings` constructor argument using `BlandTTSService.Settings(...)`. These can be updated mid-conversation with `TTSUpdateSettingsFrame`. See [Service Settings](/pipecat/fundamentals/service-settings) for details.

| Parameter        | Type              | Default                                | Description                                                                                  |
| ---------------- | ----------------- | -------------------------------------- | -------------------------------------------------------------------------------------------- |
| `voice`          | `str`             | `2f29fdbb-c55e-4add-9c7c-93437ebf379d` | Voice identifier.                                                                            |
| `expressiveness` | `float \| None`   | `None`                                 | 0.0-1.0. Higher values produce more varied intonation. `None` leaves Bland at its default.   |
| `stability`      | `float \| None`   | `None`                                 | 0.0-1.0. Higher values produce more consistent delivery. `None` leaves Bland at its default. |
| `model`          | `str`             | `None`                                 | Model identifier. *(Inherited.)*                                                             |
| `language`       | `Language \| str` | `None`                                 | Language for synthesis. *(Inherited.)*                                                       |

<Note>
  The voice sets the model; `expressiveness` and `stability` are calibrated for
  `BTTS_V3`.
</Note>

### BlandHttpTTSService

<ParamField path="api_key" type="str" required>
  Bland API key for authentication.
</ParamField>

<ParamField path="base_url" type="str" default="https://api.bland.ai/v2">
  Base URL for the Bland API.
</ParamField>

<ParamField path="sample_rate" type="int" default="None">
  Output sample rate in Hz. When `None`, uses the pipeline default.
</ParamField>

<ParamField path="aiohttp_session" type="aiohttp.ClientSession" default="None">
  Optional shared aiohttp session. When omitted, the service creates and owns
  one.
</ParamField>

<ParamField path="settings" type="BlandHttpTTSService.Settings" default="None">
  Runtime-configurable settings. See [BlandHttpTTSService
  Settings](#blandhttpttsservice-settings) below.
</ParamField>

#### BlandHttpTTSService Settings

Runtime-configurable settings passed via the `settings` constructor argument using `BlandHttpTTSService.Settings(...)`. These can be updated mid-conversation with `TTSUpdateSettingsFrame`. See [Service Settings](/pipecat/fundamentals/service-settings) for details.

| Parameter        | Type              | Default                                | Description                                              |
| ---------------- | ----------------- | -------------------------------------- | -------------------------------------------------------- |
| `voice`          | `str`             | `2f29fdbb-c55e-4add-9c7c-93437ebf379d` | Voice identifier.                                        |
| `expressiveness` | `float \| None`   | `None`                                 | 0.0-1.0. Higher values produce more varied intonation.   |
| `stability`      | `float \| None`   | `None`                                 | 0.0-1.0. Higher values produce more consistent delivery. |
| `model`          | `str`             | `None`                                 | Model identifier. *(Inherited.)*                         |
| `language`       | `Language \| str` | `None`                                 | Language for synthesis. *(Inherited.)*                   |

## Usage

### WebSocket Service

```python theme={null}
from pipecat.services.bland.tts import BlandTTSService

tts = BlandTTSService(
    api_key=os.getenv("BLAND_API_KEY"),
    settings=BlandTTSService.Settings(
        voice="2f29fdbb-c55e-4add-9c7c-93437ebf379d"
    ),
)
```

To aggregate text into sentences before synthesis instead of streaming tokens:

```python theme={null}
from pipecat.services.tts_service import TextAggregationMode

tts = BlandTTSService(
    api_key=os.getenv("BLAND_API_KEY"),
    text_aggregation_mode=TextAggregationMode.SENTENCE,
    settings=BlandTTSService.Settings(
        voice="2f29fdbb-c55e-4add-9c7c-93437ebf379d"
    ),
)
```

### HTTP Service

```python theme={null}
import aiohttp
from pipecat.services.bland.tts import BlandHttpTTSService

async with aiohttp.ClientSession() as session:
    tts = BlandHttpTTSService(
        api_key=os.getenv("BLAND_API_KEY"),
        settings=BlandHttpTTSService.Settings(
            voice="2f29fdbb-c55e-4add-9c7c-93437ebf379d"
        ),
        aiohttp_session=session,
    )
```

## Notes

* **Choosing a service**: `BlandTTSService` maintains a single WebSocket connection for the whole conversation and streams LLM tokens as they arrive, making it suitable for interactive voice agents. `BlandHttpTTSService` processes each request as a complete batch.
* **Token Streaming**: By default (`TextAggregationMode.TOKEN`), LLM tokens are sent to Bland immediately. Bland buffers them server-side and chooses its own synthesis boundaries, so no sentence tokenizer or character threshold is needed.
* **Interruption Handling**: Interruptions send Bland's `cancel` message without closing the connection, so barge-in preserves the session.
* **Sample Rate**: Bland renders 8000, 16000, 24000, 44100, and 48000 Hz directly. A pipeline running at any other rate is served at 48000 Hz and resampled by the output transport.

## Event Handlers

`BlandTTSService` supports the standard [service connection events](/api-reference/server/events/service-events):

| Event                 | Description                  |
| --------------------- | ---------------------------- |
| `on_connected`        | Connected to Bland WebSocket |
| `on_disconnected`     | Disconnected from Bland      |
| `on_connection_error` | Connection error occurred    |

```python theme={null}
@tts.event_handler("on_connected")
async def on_connected(service):
    print("Connected to Bland")
```
