Skip to main content

PiperSynth

PiperSynth is a standalone synthesis engine for Piper-compatible ONNX voices. Callers provide prepared, speakable text; PiperG2P owns phonemization and Piper ID generation, OnnxVoice handles model inference, and PiperSynth applies engine-local acoustic and audio policy. Document parsing, SSMD, written-to-spoken preparation, semantic pauses, markers, timeline composition, and final mastering belong to other layers.

Install

Install PiperSynth with the CPU runtime:

pip install "pipersynth[cpu]"

For GPU inference, install pipersynth[gpu]. OnnxVoice manages catalog lookup, model downloads, caching, provider selection, and ONNX Runtime sessions.

Synthesize prepared text

from pipersynth import PiperVoice

with PiperVoice.from_pretrained("en_US-lessac-medium") as voice:
    result = voice.synthesize_text(
        "Hello, this text is already prepared for speech.",
        language="en-us",
    )
    result.save_wav("hello.wav")

prepared_text is ordinary speakable text, not phoneme IDs. PiperSynth does not expand numbers, dates, abbreviations, or other written forms. Perform that semantic preparation before calling the engine.

Atomic prepared requests

PiperSynth never chooses a new text boundary. Readio or another caller prepares and splits text before sending each atomic request. PiperVoice.synthesize() and synthesize_text() pass the exact request text to PiperG2P and perform at most one acoustic inference. Frontend sentence groups are joined as phoneme IDs for that single inference; PiperSynth does not call Phrasplit or split on punctuation.

from pipersynth import PiperVoice, SynthesisRequest

prepared_text = (
    "The first already-prepared sentence. "
    "The next sentence remains part of this same atomic request."
)

request = SynthesisRequest(
    id="paragraph-001",
    text=prepared_text,
    language="en-us",
)

with PiperVoice.from_pretrained("en_US-lessac-medium") as voice:
    result = voice.synthesize(request)
    result.save_wav("paragraph.wav")

If the complete request exceeds an explicit hard phoneme maximum, PiperSynth raises SynthesisInputTooLongError. It does not retry with smaller pieces. Readio decides the next boundary.

Measure request capacity without inference

PiperVoice.measure(request) runs PiperG2P frontend lowering and phoneme-ID encoding, but does not run acoustic inference or audio postprocessing. It returns the exact phoneme_count plus capacity_kind, capacity_source, max_phonemes, and fits. bounded reports a declared hard maximum and whether the request is within it; variable means the graph declares a symbolic sequence axis and reports fits=True; fixed reports fits=True only for the exact graph length and otherwise fits=None; unknown reports fits=None. Measurement never splits the request.

max_phonemes=None alone does not distinguish variable, fixed, and unknown capacity. Consumers should use capacity_kind and fits; variable graph support is structural evidence, not infinite machine resources.

For repeated requests, reuse one voice:

from pipersynth import PiperVoice, SynthesisConfig

with PiperVoice.from_pretrained("en_US-lessac-medium", offline=True) as voice:
    result = voice.synthesize_text(
        "A second prepared request.",
        language="en-us",
        config=SynthesisConfig(length_scale=0.9, output_gain=0.8),
    )

Use PiperVoice.from_local("voice.onnx") to open a local model. By default, PiperSynth reads its config from voice.onnx.json.

Typed requests and linguistic context

Use SynthesisRequest for a request with an explicit identity, speaker, pronunciation override, or linguistic token context. Token offsets refer to the exact prepared string, and all supplied token fields, including morph, are forwarded to PiperG2P.

from pipersynth import (
    LinguisticToken,
    PiperVoice,
    PronunciationOverride,
    SynthesisRequest,
)

request = SynthesisRequest(
    id="line-001",
    text="I read the book yesterday.",
    language="en-us",
    pronunciation_overrides=(PronunciationOverride(2, 6, phonemes="ɹɛd"),),
    tokens=(
        LinguisticToken(
            start=2,
            end=6,
            text="read",
            pos="VERB",
            lemma="read",
            morph="Tense=Past",
        ),
    ),
)

with PiperVoice.from_pretrained("en_US-lessac-medium") as voice:
    result = voice.synthesize(request)

SynthesisSegment remains accepted as a compatibility request type. Its annotations become SynthesisRequest.tokens; it follows the same atomic behavior. synthesize_text() is also strict. None of these APIs accepts chunking.

Piper frontend and low-level IDs

PiperG2P may represent one atomic request as several frontend sentence groups. PiperSynth joins their phoneme IDs and performs one model inference for the complete request. It does not expose those groups as independently rendered chunks.

PiperVoice.synthesize_ids() remains available for callers that already have Piper phoneme IDs. ID validation, speaker selection, acoustic controls, voice calibration, and waveform postprocessing still apply.

Audio and calibration

Results contain mono finite float32 audio at the model's native sample rate. SynthesisResult.save_wav() writes mono 16-bit PCM. Conversion clips to the supported PCM range.

SynthesisConfig contains Piper controls (length_scale, noise_scale, and noise_w_scale), optional peak normalization, explicit engine-local output_gain, and static voice_level calibration. PiperSynth does not perform final LUFS or true-peak mastering. Use AudioCompose or another output layer when producing a document, chapter, or mixed timeline.

Voice discovery and providers

from pipersynth import VoiceAssetManager, list_voices

for item in list_voices(language="en", quality="medium"):
    print(item.id, item.name)

manager = VoiceAssetManager(offline=True)
print(manager.get_voice_metadata("en_US-lessac-medium"))

The default inference provider is CPUExecutionProvider. Pass providers and provider_options to PiperVoice.from_pretrained() or PiperVoice.from_local() to select runtime providers. See provider configuration.

Examples and development

Runnable examples are under examples/. They synthesize prepared text with PiperVoice; generated files are written below example-artefacts/ by default.

Run validation with:

python -m pytest
python -m ruff check pipersynth tests examples benchmarks
python -m mypy pipersynth tests/typecheck/engine_api.py

Metadata

Release files for pipersynth 0.2.5

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

Source distribution (sdist)

Source distribution for pipersynth 0.2.5
File Size Uploaded
pipersynth-0.2.5.tar.gz 183.1 kB Details

Built distribution (wheel)

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

Total release size: 323.8 kB

Release files / pipersynth-0.2.5.tar.gz

Download URL pipersynth-0.2.5.tar.gz
Size 183.1 kB
Tags Source
SHA-256 checksum
How to use checksums
cdb90a33cb9028e976419b08f5faabb3443f22fd5bc3231c7ce22844f7f39207
BLAKE2b-256 checksum
How to use checksums
6ea3e73d0aa5971be8b080da17ebaeedb470b576778569c6375eb03624cea384
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.14

Release files / pipersynth-0.2.5-py3-none-any.whl

Download URL pipersynth-0.2.5-py3-none-any.whl
Size 140.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6fd75b2315658620b1e07d66ffa08d8575c16bcdd3e6a0a42e88dd36dddaa33b
BLAKE2b-256 checksum
How to use checksums
6b403113d00eb1806c0660fcaf51896120ac4ebba02f081b847544cad0170730
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.2.5 This release

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

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