Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,6 @@ cython_debug/

# PyPI configuration file
.pypirc

# Examples
**/output.wav
44 changes: 32 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Makefile for Speechmatics Python SDKs

.PHONY: help
.PHONY: test-all test-rt test-batch test-flow
.PHONY: format-all format-rt format-batch format-flow
.PHONY: lint-all lint-rt lint-batch lint-flow
.PHONY: type-check-all type-check-rt type-check-batch type-check-flow
.PHONY: build-all build-rt build-batch build-flow
.PHONY: clean-all clean-rt clean-batch clean-flow clean-flow
.PHONY: test-all test-rt test-batch test-flow test-tts
.PHONY: format-all format-rt format-batch format-flow format-tts
.PHONY: lint-all lint-rt lint-batch lint-flow lint-tts
.PHONY: type-check-all type-check-rt type-check-batch type-check-flow type-check-tts
.PHONY: build-all build-rt build-batch build-flow build-tts
.PHONY: clean-all clean-rt clean-batch clean-flow clean-tts

help:
@echo "Available commands:"
Expand Down Expand Up @@ -40,16 +40,18 @@ help:
@echo " build-rt Build RT SDK"
@echo " build-batch Build Batch SDK"
@echo " build-flow Build Flow SDK"
@echo " build-tts Build TTS SDK"
@echo ""
@echo "Cleaning:"
@echo " clean-all Clean all SDKs"
@echo " clean-rt Clean RT SDK build artifacts"
@echo " clean-batch Clean Batch SDK build artifacts"
@echo " clean-flow Clean Flow SDK build artifacts"
@echo " clean-tts Clean TTS SDK build artifacts"
@echo ""

# Testing targets
test-all: test-rt test-batch test-flow
test-all: test-rt test-batch test-flow test-tts

test-rt:
pytest tests/rt/ -v
Expand All @@ -61,7 +63,7 @@ test-flow:
pytest tests/flow/ -v

# Formatting targets
format-all: format-rt format-batch format-flow
format-all: format-rt format-batch format-flow format-tts

format-rt:
cd sdk/rt/speechmatics && black .
Expand All @@ -75,8 +77,12 @@ format-flow:
cd sdk/flow/speechmatics && black .
cd sdk/flow/speechmatics && ruff check --fix .

format-tts:
cd sdk/tts/speechmatics && black .
cd sdk/tts/speechmatics && ruff check --fix .

# Linting targets
lint-all: lint-rt lint-batch lint-flow
lint-all: lint-rt lint-batch lint-flow lint-tts

lint-rt:
cd sdk/rt/speechmatics && ruff check .
Expand All @@ -87,8 +93,11 @@ lint-batch:
lint-flow:
cd sdk/flow/speechmatics && ruff check .

lint-tts:
cd sdk/tts/speechmatics && ruff check .

# Type checking targets
type-check-all: type-check-rt type-check-batch type-check-flow
type-check-all: type-check-rt type-check-batch type-check-flow type-check-tts

type-check-rt:
cd sdk/rt/speechmatics && mypy .
Expand All @@ -99,18 +108,22 @@ type-check-batch:
type-check-flow:
cd sdk/flow/speechmatics && mypy .

type-check-tts:
cd sdk/tts/speechmatics && mypy .

# Installation targets
install-dev:
python -m pip install --upgrade pip
python -m pip install -e sdk/rt[dev]
python -m pip install -e sdk/batch[dev]
python -m pip install -e sdk/flow[dev]
python -m pip install -e sdk/tts[dev]

install-build:
python -m pip install --upgrade build

# Building targets
build-all: build-rt build-batch build-flow
build-all: build-rt build-batch build-flow build-tts

build-rt: install-build
cd sdk/rt && python -m build
Expand All @@ -121,8 +134,11 @@ build-batch: install-build
build-flow: install-build
cd sdk/flow && python -m build

build-tts: install-build
cd sdk/tts && python -m build

# Cleaning targets
clean-all: clean-rt clean-batch clean-flow
clean-all: clean-rt clean-batch clean-flow clean-tts

clean-rt:
rm -rf sdk/rt/dist sdk/rt/build sdk/rt/*.egg-info
Expand All @@ -135,3 +151,7 @@ clean-batch:
clean-flow:
rm -rf sdk/flow/dist sdk/flow/build sdk/flow/*.egg-info
find sdk/flow -name __pycache__ -exec rm -rf {} + 2>/dev/null || true

clean-tts:
rm -rf sdk/tts/dist sdk/tts/build sdk/tts/*.egg-info
find sdk/tts -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
55 changes: 55 additions & 0 deletions examples/tts/tts_async_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import os
import asyncio

import wave
from pathlib import Path

from speechmatics.tts import AsyncClient, Voice, OutputFormat


# Set configuration
TEXT = "Welcome to the future of audio generation from text!"
VOICE = Voice.SARAH
OUTPUT_FORMAT = OutputFormat.RAW_PCM_16000
OUTPUT_FILE = "output.wav"

# Set Format Parameters for WAV output file
SAMPLE_RATE = 16000 #Hz
SAMPLE_WIDTH = 2 # 16-bit audio
CHANNELS = 1 # Mono audio

# Save audio to WAV file
async def save_audio_to_wav(audio_data: bytes,
output_file_name: str) -> None:
with wave.open(output_file_name, "wb") as wav_file:
wav_file.setnchannels(CHANNELS)
wav_file.setsampwidth(SAMPLE_WIDTH)
wav_file.setframerate(SAMPLE_RATE)
wav_file.writeframes(audio_data)

# Generate speech from text and save to WAV file
async def main():
print(f"Generating speech from text: {TEXT}")

try:
async with AsyncClient() as client:
async with await client.generate(
text=TEXT,
voice=VOICE,
output_format=OUTPUT_FORMAT
) as response:
# Process the response in chunks and save to WAV
audio_chunks = []
async for chunk in response.content.iter_chunked(1024):
audio_chunks.append(chunk)

# Combine chunks and save to WAV
audio_data = b''.join(audio_chunks)
await save_audio_to_wav(audio_data, OUTPUT_FILE)
print(f"Speech saved to {Path(OUTPUT_FILE).resolve()}")
except Exception as e:
print(f"An error occurred: {e}")

# Run the async main function
if __name__ == "__main__":
asyncio.run(main())
128 changes: 128 additions & 0 deletions sdk/tts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Speechmatics TTS API Client

[![PyPI](https://img.shields.io/pypi/v/speechmatics-tts)](https://pypi.org/project/speechmatics-tts/)
![PythonSupport](https://img.shields.io/badge/Python-3.9%2B-green)

Async Python client for Speechmatics TTS API.

## Features

- Async API client with comprehensive error handling
- Type hints throughout for better IDE support
- Environment variable support for credentials

## Installation

```bash
pip install speechmatics-tts
```

## Usage

### Quick Start

```python
import asyncio

import wave
from pathlib import Path

from speechmatics.tts import AsyncClient, Voice, OutputFormat

async def save_audio(audio_data: bytes, filename: str) -> None:
with wave.open(filename, "wb") as wav:
wav.setnchannels(1) # Mono
wav.setsampwidth(2) # 16-bit
wav.setframerate(16000) # 16kHz
wav.writeframes(audio_data)

# Generate speech data from text and save to WAV file
async def main():
async with AsyncClient() as client:
async with await client.generate(
text="Welcome to the future of audio generation from text!",
voice=Voice.SARAH,
output_format=OutputFormat.RAW_PCM_16000
) as response:
audio = b''.join([chunk async for chunk in response.content.iter_chunked(1024)])
await save_audio(audio, "output.wav")


# Run the async main function
if __name__ == "__main__":
asyncio.run(main())

```

### Error Handling

```python
import asyncio
from speechmatics.tts import (
AsyncClient,
AuthenticationError,
TimeoutError
)

async def main():
try:
async with AsyncClient() as client:
response = await client.generate(text="Hello, this is the Speechmatics TTS API. We are excited to have you here!")

except AuthenticationError:
print("Invalid API key")
except JobError as e:
print(f"Job processing failed: {e}")
except TimeoutError as e:
print(f"Job timed out: {e}")
except FileNotFoundError:
print("Audio file not found")

asyncio.run(main())
```

### Connection Configuration

```python
import asyncio
from speechmatics.tts import AsyncClient, ConnectionConfig

async def main():
# Custom connection settings
config = ConnectionConfig(
url="https://preview.tts.speechmatics.com",
api_key="your-api-key",
connect_timeout=30.0,
operation_timeout=600.0
)

async with AsyncClient(conn_config=config) as client:
response = await client.generate(text="Hello World")


asyncio.run(main())
```

## Logging

The client supports logging with job id tracing for debugging. To increase logging verbosity, set `DEBUG` level in your example code:

```python
import logging
import sys

logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(sys.stdout)
]
)
```

## Environment Variables

The client supports the following environment variables:

- `SPEECHMATICS_API_KEY`: Your Speechmatics API key
- `SPEECHMATICS_TTS_URL`: Custom API endpoint URL (optional)
52 changes: 52 additions & 0 deletions sdk/tts/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[build-system]
requires = ["setuptools>=61.0.0"]
build-backend = "setuptools.build_meta"

[project]
name = "speechmatics-tts"
dynamic = ["version"]
description = "Speechmatics TTS API Client"
readme = "README.md"
authors = [{ name = "Speechmatics", email = "[email protected]" }]
license = "MIT"
requires-python = ">=3.9"
dependencies = ["aiohttp", "aiofiles"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Operating System :: OS Independent",
"Topic :: Multimedia :: Sound/Audio :: Speech",
"Topic :: Software Development :: Libraries :: Python Modules",
]
keywords = ["speechmatics", "speech-to-text", "tts", "transcription", "api"]

[project.optional-dependencies]
dev = [
"black",
"ruff",
"mypy",
"types-aiofiles",
"pre-commit",
"pytest",
"pytest-asyncio",
"pytest-cov",
"pytest-mock",
"build",
]

[project.urls]
homepage = "https://github.com/speechmatics/speechmatics-python-sdk"
documentation = "https://docs.speechmatics.com/"
repository = "https://github.com/speechmatics/speechmatics-python-sdk"
issues = "https://github.com/speechmatics/speechmatics-python-sdk/issues"

[tool.setuptools.dynamic]
version = { attr = "speechmatics.tts.__version__" }

[tool.setuptools.packages.find]
where = ["."]
29 changes: 29 additions & 0 deletions sdk/tts/speechmatics/tts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
__version__ = "0.0.0"

from ._async_client import AsyncClient
from ._auth import AuthBase
from ._auth import JWTAuth
from ._auth import StaticKeyAuth
from ._exceptions import AuthenticationError
from ._exceptions import ConfigurationError
from ._exceptions import ConnectionError
from ._exceptions import TimeoutError
from ._exceptions import TransportError
from ._models import ConnectionConfig
from ._models import OutputFormat
from ._models import Voice

__all__ = [
"AsyncClient",
"AuthBase",
"JWTAuth",
"StaticKeyAuth",
"ConfigurationError",
"AuthenticationError",
"ConnectionError",
"TransportError",
"TimeoutError",
"ConnectionConfig",
"Voice",
"OutputFormat",
]
Loading