Typed async wrappers for OpenAI speech-to-text and text-to-speech APIs
Project description
🎙️ vocalbin
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 text — gpt-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 speech — gpt-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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ffa881e6e8a3415c6ba38987b94ab13c77d48f73741503726a7bd2639f121d15
|
|
| MD5 |
1e05c2e544317161d6b1631538959b2b
|
|
| BLAKE2b-256 |
1e28c600b1b99dff8a5a4da04e64e59f8d0baede62bd23689850e1997fb13329
|
Provenance
The following attestation bundles were made for vocalbin-0.1.0.tar.gz:
Publisher:
release.yml on mathisarends/vocalbin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vocalbin-0.1.0.tar.gz -
Subject digest:
ffa881e6e8a3415c6ba38987b94ab13c77d48f73741503726a7bd2639f121d15 - Sigstore transparency entry: 2213857439
- Sigstore integration time:
-
Permalink:
mathisarends/vocalbin@f26432af3483cbbfbdcf527275a0be8e5afe1100 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mathisarends
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f26432af3483cbbfbdcf527275a0be8e5afe1100 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cbc94d8b3c53a1ca915411dedeb25112433e3ec3c4523c155e84ff8d22abb6b9
|
|
| MD5 |
3c46ed4db2d029bfa05ba7b8eb950037
|
|
| BLAKE2b-256 |
86428e942378155ef5ec0111b4146679ac47e8d2ee1896edacfa8193ece83dc4
|
Provenance
The following attestation bundles were made for vocalbin-0.1.0-py3-none-any.whl:
Publisher:
release.yml on mathisarends/vocalbin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vocalbin-0.1.0-py3-none-any.whl -
Subject digest:
cbc94d8b3c53a1ca915411dedeb25112433e3ec3c4523c155e84ff8d22abb6b9 - Sigstore transparency entry: 2213857480
- Sigstore integration time:
-
Permalink:
mathisarends/vocalbin@f26432af3483cbbfbdcf527275a0be8e5afe1100 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mathisarends
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f26432af3483cbbfbdcf527275a0be8e5afe1100 -
Trigger Event:
push
-
Statement type: