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 a capacity reported by the model or frontend, 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 the acoustic ONNX model or audio postprocessing. It returns the exact encoded phoneme_ids count and a hard maximum only when the active runtime, config, or model metadata declares one. A known overflow is returned as fits=False; measurement never splits the request.

max_phonemes=None means PiperSynth has no declared hard maximum for that voice. It does not mean the model has infinite capacity.

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.4

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.4
File Size Uploaded
pipersynth-0.2.4.tar.gz 180.8 kB Details

Built distribution (wheel)

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

Total release size: 320.2 kB

Release files / pipersynth-0.2.4.tar.gz

Download URL pipersynth-0.2.4.tar.gz
Size 180.8 kB
Tags Source
SHA-256 checksum
How to use checksums
910fff5540741f1cf6036059bbe6c832a0f934f2d8af77fa3b0821cd9052f2c7
BLAKE2b-256 checksum
How to use checksums
0f795db8253d390ef136150e865736a868e48f26ee3d4e7d49bfde0e30e0af4e
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.4-py3-none-any.whl

Download URL pipersynth-0.2.4-py3-none-any.whl
Size 139.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c999b677b4ec379fc2acb4a0913699d9f4ba054153de1264e6487c71bd1a4cbd
BLAKE2b-256 checksum
How to use checksums
a9adf8db072b00b9455536ca3a7b0171629fce62272b256a300a3c75c96e8804
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

0.2.5

2 release files

This release

0.2.4 This release

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