Metadata-Version: 2.4
Name: breeze-blue
Version: 0.2.1
Summary: Python SDK for the Breeze Blue Developer API.
Author-email: Breeze Blue <support@breeze.blue>
License-Expression: MIT
Project-URL: Homepage, https://breeze.blue
Project-URL: Documentation, https://breeze.blue/docs
Keywords: audio,breeze,breeze-blue,sdk,text-to-speech,tts,voice
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<1.0.0,>=0.28.0
Dynamic: license-file

# Breeze Blue Python SDK

Python SDK for the Breeze Blue Developer API. Covers text-to-speech, voice
management, voice preview generation, history audio, models, and account
usage.

## Install

```bash
uv add breeze-blue
```

or:

```bash
pip install breeze-blue
```

## API Key

Create an API key in the Breeze Blue Developer Console, then export it:

```bash
export BREEZE_API_KEY=brz_...
```

The SDK sends the key with the `xi-api-key` header.

## Quickstart

```python
from breeze_blue import BreezeBlue, save

client = BreezeBlue()

audio = client.text_to_speech.convert(
    voice_id="voc_...",
    text="Hello from Breeze Blue.",
    output_format="mp3",
)

save(audio, "hello.mp3")
print(audio.content_type)
print(audio.history_item_id)
```

`BreezeBlue()` reads `BREEZE_API_KEY` by default and sends requests to
`https://api.breeze.blue`. To point at another environment, pass `base_url=...`
or set `BREEZE_BASE_URL`.

```python
client = BreezeBlue(
    api_key="brz_...",
    base_url="https://api.breeze.blue",
    timeout=120.0,
)
```

All resource methods accept `timeout=<seconds>` to override the client default
for a single call.

## Text to Speech

```python
audio = client.text_to_speech.convert(
    voice_id="voc_...",
    text="Render this line.",
)

streamed_audio = client.text_to_speech.stream(
    voice_id="voc_...",
    text="Stream this line.",
)
```

The API uses the default text-to-speech model when `model_id` is omitted. If
you need to select a model explicitly, call `client.models.list()` and pass one
of the returned `model_id` values.

Audio responses are returned as `AudioResponse`:

```python
audio.content          # bytes
audio.content_type     # e.g. "audio/mpeg"
audio.history_item_id  # history item id when returned by the API

audio.save("speech.mp3")
```

Playback helpers are available for local scripts:

```python
from breeze_blue import play, stream

play(audio)    # ffplay, with macOS afplay fallback
stream(audio)  # mpv; accepts AudioResponse, bytes, or an iterable of byte chunks
```

`audio.stream()` is a buffered compatibility helper for `AudioResponse`.
Use the module-level `stream(audio_chunks)` helper when you already have chunked
audio data.

## Voices

Browse existing voices and inspect a single voice:

```python
voices = client.voices.search(search="narrator")
first_voice_id = voices["voices"][0]["voice_id"]

voice = client.voices.get(first_voice_id)
settings = client.voices.get_settings(first_voice_id)
```

Breeze voice creation is always two steps: produce a **preview**, let the
user accept it, then **save the preview** as a real voice. Two ways to
produce a preview:

```python
# Option A — clone preview from an audio sample
clone_preview = client.voices.create_clone_preview(
    name="Demo voice",
    file="sample.wav",
    text="This is a short preview script.",
)
generated_voice_id = clone_preview["generated_voice_id"]

# Option B — design preview from a text description (no audio)
design = client.voices.create_design_preview(
    voice_description="Warm documentary narrator with clear articulation.",
)
generated_voice_id = design["previews"][0]["generated_voice_id"]
```

Stream the preview so the user can audition it, then save the one they pick:

```python
audio = client.voices.stream_preview(generated_voice_id)
audio.save("preview.mp3")

saved = client.voices.save_preview(
    generated_voice_id=generated_voice_id,
    voice_name="Documentary narrator",
)
```

Edit, tune settings, or delete a saved voice:

```python
client.voices.edit(saved["voice_id"], name="Renamed narrator")
client.voices.edit_settings(saved["voice_id"], guidance_scale=1.2)
client.voices.delete(saved["voice_id"])
```

## History, Models, and Account

```python
models = client.models.list()
balance = client.account.balance()
usage = client.account.usage(days=7)

history = client.history.list(page_size=10)
item = client.history.get(history["history"][0]["history_item_id"])
audio = client.history.download_audio(item["history_item_id"])
```

Common response shapes are exported as `TypedDict` types from
`breeze_blue.types` and from the package root.

## Errors

All API errors inherit from `BreezeBlueError`. HTTP status codes and Breeze
error codes map to typed exceptions:

- `BadRequestError`
- `AuthenticationError`
- `ForbiddenError`
- `NotFoundError`
- `ConflictError`
- `ValidationError`
- `RateLimitError`
- `BillingInsufficientCreditsError`
- `UpstreamError`
- `ServiceUnavailableError`

```python
from breeze_blue import BreezeBlue, RateLimitError

try:
    BreezeBlue().models.list()
except RateLimitError as exc:
    print(exc.retry_after)
```

Each `ApiError` exposes `status_code`, `code`, `detail`, `meta`, and
`retry_after`.
