Skip to main content

voxport

Small Python interfaces for text-to-speech and speech-to-text, with swappable engine adapters. Your code calls one method, synthesize() or transcribe(), and never touches an engine's API directly, so switching engines means changing one line where the adapter is created.

TTSEngine.synthesize(text, voice) -> audio
STTEngine.transcribe(audio) -> text

Included adapters:

  • KokoroDirectTTS: runs the Kokoro TTS model in your own process. The model loads once and stays in memory, with no server and no network hop.
  • WyomingWhisperSTT: a client for a Wyoming protocol Whisper server, the same kind of server Home Assistant's voice pipeline uses. It loads no model itself; transcription happens on the server.

voxport is a library only: it has no command-line tool or app of its own. It is pre-1.0, so the API may still change between minor versions (see the changelog).

Installation

Requires Python 3.10+. Each adapter's dependencies are an optional extra, so you install only what you use:

pip install "voxport[kokoro]"    # KokoroDirectTTS
pip install "voxport[wyoming]"   # WyomingWhisperSTT
pip install "voxport[all]"       # both
Extra Adds For
kokoro Kokoro, torch (about 2 GB) KokoroDirectTTS
wyoming wyoming WyomingWhisperSTT
all both of the above everything

A plain pip install voxport includes only the interfaces and numpy. Importing an adapter without its extra raises an ImportError that names the extra to install.

Things voxport doesn't install for you:

  • WyomingWhisperSTT needs a running Wyoming Whisper server. See Running a Wyoming Whisper server.
  • On first use, Kokoro downloads its model weights and voice packs from Hugging Face, and spaCy's en_core_web_sm English model. See Offline use for machines that can't reach those.
  • soundfile, used in the examples below to write WAV files.

Usage

Text to speech

import soundfile as sf
from voxport.tts.kokoro_direct import KokoroDirectTTS

tts = KokoroDirectTTS()  # reuse one instance; models load once per accent
audio = tts.synthesize("Hello from voxport.", voice="af_heart", speed=1.0)
sf.write("hello.wav", audio, tts.sample_rate)  # 24 kHz mono

synthesize() returns a 1-D numpy array. The first letter of the voice name picks the accent (a American, b British, ...), following Kokoro's voice naming; pass lang_code= to override it. Kokoro splits long text into segments itself, so there is no length limit.

Speech to text

from voxport.stt.wyoming_whisper import WyomingWhisperSTT

stt = WyomingWhisperSTT(host="localhost", port=10300)  # the defaults
text = stt.transcribe(audio_16k, language="en")

audio_16k is a 1-D numpy array of mono audio at stt.sample_rate (16 kHz), either int16 samples or floats in [-1, 1]. Resample first if your audio has a different rate; Kokoro's output, for example, is 24 kHz. Each call opens a new connection to the server.

From async code

Both calls block, and transcribe() runs its own asyncio event loop, so from code that already has a running loop, call them in a worker thread:

audio = await asyncio.to_thread(tts.synthesize, text, "bm_george")
text = await asyncio.to_thread(stt.transcribe, audio_16k, "en")

Logging

voxport reports progress through Python's logging module, under the voxport logger, and never prints. KokoroDirectTTS logs model loads and each synthesis at INFO and per-segment progress at DEBUG. Python hides messages below WARNING by default, so to see them:

import logging

logging.basicConfig(level=logging.WARNING)            # your app's setup
logging.getLogger("voxport").setLevel(logging.INFO)   # voxport progress

Writing your own adapter

An adapter subclasses TTSEngine or STTEngine, sets sample_rate, and implements the one abstract method:

import numpy as np
from voxport.tts.base import TTSEngine

class SilenceTTS(TTSEngine):
    """A toy engine: one second of silence, whatever the text."""

    sample_rate = 16000

    def synthesize(self, text: str, voice: str, speed: float = 1.0):
        return np.zeros(self.sample_rate, dtype=np.float32)

Code written against TTSEngine works with SilenceTTS and KokoroDirectTTS unchanged. Adapters may accept extra, engine-specific keyword arguments (like KokoroDirectTTS's lang_code), as long as the base signature still works.

Offline use

By default, Kokoro's weights and voice packs download to Hugging Face's standard cache (~/.cache/huggingface, or wherever HF_HOME points). To run on a machine that can't reach huggingface.co:

  1. On a machine with internet access, synthesize once with each voice you plan to use, so the model and those voice packs are cached.
  2. Copy that cache to the offline machine, keeping Hugging Face's hub/models--<org>--<name>/... layout, and point HF_HOME at it.
  3. Set HF_HUB_OFFLINE=1 on the offline machine. voxport never sets this for you. With it set, only voices already in the cache work; an uncached voice fails with a Hub connection error instead of downloading.

Kokoro's English phonemizer also needs spaCy's en_core_web_sm model, which downloads from GitHub, not Hugging Face, so HF_HUB_OFFLINE doesn't cover it. It downloads once per Python environment, so install it while online:

python -m spacy download en_core_web_sm

Repo-local cache (source checkouts only). If you run voxport from a clone, you can keep the cache inside it instead: create an hf_cache/ folder at the repo root (it's gitignored) and KokoroDirectTTS uses it as HF_HOME, unless you've set HF_HOME yourself. That makes the cache easy to copy along with the checkout.

Running a Wyoming Whisper server

WyomingWhisperSTT needs a server to talk to. For local testing, the easiest option is the rhasspy/wyoming-whisper Docker image:

docker run -d --name whisper --restart unless-stopped -p 10300:10300 -v wyoming-data:/data rhasspy/wyoming-whisper --model tiny-int8 --language en

The image is named rhasspy/wyoming-whisper, even though its GitHub repo is wyoming-faster-whisper. docker logs whisper shows Ready once the model has loaded. tiny-int8 is small and fast but not very accurate; use a larger model when transcription quality matters.

If you already run Home Assistant with its Whisper add-on, you can point WyomingWhisperSTT at that server's host and port instead.

Development

git clone https://github.com/brienalkire/voxport.git
cd voxport
pip install -e ".[all]" pytest
python -m pytest

The tests need no network, no Whisper server and no Kokoro model: WyomingWhisperSTT is tested against a fake in-process Wyoming server, and KokoroDirectTTS against stand-in torch and kokoro modules. Installing .[wyoming] instead of .[all] is enough to run them and skips the 2 GB torch download.

License

MIT

Metadata

Release files for voxport 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for voxport 0.5.0
File Size Uploaded Provenance Actions
voxport-0.5.0.tar.gz 16.7 kB With provenance Details for voxport-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for voxport 0.5.0
File Interpreter ABI Platform Actions
voxport-0.5.0-py3-none-any.whl Python 3 none any Details for voxport-0.5.0-py3-none-any.whl

Total release size: 28.6 kB

Release files / voxport-0.5.0.tar.gz

Download URL voxport-0.5.0.tar.gz
Size 16.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ecc71ed8d013d189f7704f630db88c225fe03446000ab18fd09a61b1ade6f86e
BLAKE2b-256 checksum
How to use checksums
1e2bbc73146180a3e01668cab8271841461e853480e03bacb10af05d4f23eab8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / voxport-0.5.0-py3-none-any.whl

Download URL voxport-0.5.0-py3-none-any.whl
Size 11.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9f3b9b3e7256a854b0b6c68e9c9cd1f717741f736afc06c05f451dac7157f91c
BLAKE2b-256 checksum
How to use checksums
f4061e6a81be4b9370eada426739cc0375ef5ebed75b7b85fc9de28a7edb97a4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Security for voxport 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for voxport-0.5.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page