Skip to main content

Typed async wrappers for OpenAI speech-to-text and text-to-speech APIs

Project description

🎙️ vocalbin

vocalbin — typed, async voice for OpenAI

vocalbin is a small, typed, asynchronous wrapper around OpenAI's speech-to-text and text-to-speech endpoints. It validates model capabilities up front, normalizes responses without discarding raw data, and stays independent of any application-specific settings or domain code.

Installation

uv add vocalbin

Set OPENAI_API_KEY in the environment, or pass an API key directly when creating a service. The default path reads the environment through OpenAICredentials:

from vocalbin import OpenAICredentials

credentials = OpenAICredentials()
api_key = credentials.api_key.get_secret_value()

An explicit api_key takes precedence over the environment. An injected AsyncOpenAI client does not load credentials at all.

Speech to text

from pathlib import Path

from vocalbin import OpenAISpeechToText, SpeechToTextRequest


async def transcribe() -> str:
    async with OpenAISpeechToText() as speech_to_text:
        response = await speech_to_text.transcribe(
            SpeechToTextRequest(audio_path=Path("speech.wav"), language="de")
        )
    return response.text

Audio can also be supplied directly as bytes; filename only sets the multipart upload name:

request = SpeechToTextRequest(audio=audio_bytes, filename="speech.wav")

Every request carries the transcript on response.text and the untouched provider payload on response.raw (a dict for JSON-like formats, a str for text, srt and vtt).

Text to speech

from vocalbin import (
    OpenAITextToSpeech,
    TextToSpeechFormat,
    TextToSpeechRequest,
    TextToSpeechVoice,
)


async def synthesize() -> bytes:
    async with OpenAITextToSpeech() as text_to_speech:
        response = await text_to_speech.synthesize(
            TextToSpeechRequest(
                text="Hallo aus vocalbin!",
                voice=TextToSpeechVoice.MARIN,
                response_format=TextToSpeechFormat.MP3,
                instructions="Sprich ruhig und freundlich.",
            )
        )
    return response.audio

response.content_type gives the matching MIME type (e.g. audio/mpeg).

Supported models, voices and formats

Speech to textgpt-4o-transcribe, gpt-4o-mini-transcribe, gpt-4o-transcribe-diarize, whisper-1. Response formats and options are validated per model (for example, timestamp_granularities require whisper-1 with verbose_json, and include=["logprobs"] requires a GPT transcription model with json).

Text to speechgpt-4o-mini-tts, tts-1, tts-1-hd; output formats mp3, opus, aac, flac, wav, pcm. The legacy tts-1/tts-1-hd models accept only the legacy voices and do not support instructions.

Examples

The examples/ directory holds runnable, integration-testable scripts that exercise every model/voice/format combination and double as documentation. With a valid OPENAI_API_KEY set:

uv run python examples/text_to_speech.py   # every TTS model, voice and format
uv run python examples/speech_to_text.py   # every STT model and response format
uv run python examples/round_trip.py       # synthesize -> transcribe, self-checking
uv run python examples/shared_client.py    # one AsyncOpenAI client for both services

Generated audio and transcripts are written to examples/output/ (git-ignored). speech_to_text.py synthesizes its own sample.wav on first run, so it needs no external audio file.

Bring your own client

Both concrete services accept an existing AsyncOpenAI instance via client=, which lets you share one configured client (custom base_url, timeouts, retries) across both services. Injected clients remain owned by the caller and are not closed by vocalbin:

from openai import AsyncOpenAI

from vocalbin import OpenAISpeechToText, OpenAITextToSpeech

client = AsyncOpenAI()
tts = OpenAITextToSpeech(client=client)
stt = OpenAISpeechToText(client=client)
# ... use both, then close it yourself:
await client.close()

Ports

The provider-independent SpeechToText and TextToSpeech ports are abstract base classes (vocalbin/ports.py). They mark the boundary of the library, so callers can depend on the interface rather than the OpenAI implementation.

Development

uv sync
uv run pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vocalbin-0.1.0.tar.gz (5.2 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vocalbin-0.1.0-py3-none-any.whl (8.1 kB view details)

Uploaded Python 3

File details

Details for the file vocalbin-0.1.0.tar.gz.

File metadata

  • Download URL: vocalbin-0.1.0.tar.gz
  • Upload date:
  • Size: 5.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for vocalbin-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ffa881e6e8a3415c6ba38987b94ab13c77d48f73741503726a7bd2639f121d15
MD5 1e05c2e544317161d6b1631538959b2b
BLAKE2b-256 1e28c600b1b99dff8a5a4da04e64e59f8d0baede62bd23689850e1997fb13329

See more details on using hashes here.

Provenance

The following attestation bundles were made for vocalbin-0.1.0.tar.gz:

Publisher: release.yml on mathisarends/vocalbin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file vocalbin-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: vocalbin-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for vocalbin-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cbc94d8b3c53a1ca915411dedeb25112433e3ec3c4523c155e84ff8d22abb6b9
MD5 3c46ed4db2d029bfa05ba7b8eb950037
BLAKE2b-256 86428e942378155ef5ec0111b4146679ac47e8d2ee1896edacfa8193ece83dc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for vocalbin-0.1.0-py3-none-any.whl:

Publisher: release.yml on mathisarends/vocalbin

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page