Skip to main content

PiperSynth

PiperSynth is an application-facing Python synthesis library for Piper-compatible ONNX voices. It uses piperg2p for voice configuration and phonemization, OnnxVoice for model assets and ONNX execution, and AudioCompose for generic audio composition and AudioJob persistence. It does not depend on the upstream Piper runtime or piper-tts.

Quick start

Install the CPU runtime and catalog support:

pip install "pipersynth[cpu]"

Generate a WAV from a catalog voice:

from pipersynth import synthesize_to_wav

synthesize_to_wav(
    "Hello, this sentence was generated with PiperSynth.",
    "hello.wav",
    voice="en_US-lessac-medium",
)

On first use OnnxVoice fetches the Piper catalog and installs the selected model, matching config, and any model card into its shared local store. Later calls reuse that installation. The convenience call creates a fresh pipeline and closes it before returning. For repeated synthesis, reuse one pipeline and one ONNX session:

from pipersynth import PiperPipeline

with PiperPipeline.from_pretrained("en_US-lessac-medium") as pipe:
    pipe("One.").save_wav("one.wav")
    pipe("Two.").save_wav("two.wav")

Use cached assets only with offline=True:

with PiperPipeline.from_pretrained("en_US-lessac-medium", offline=True) as pipe:
    pipe("This uses cached assets only.").save_wav("offline.wav")

Planning and rendering

PiperPipeline.plan() compiles text into an immutable UtterancePlan. The UtterPlan planner owns document parsing, Spokenform, SSMD, language runs, semantic units, markers, and resolved pauses. Rendering an existing plan never replans it, so the same plan can be rendered repeatedly with different acoustic overrides:

with PiperPipeline.from_pretrained("en_US-lessac-medium") as pipe:
    plan = pipe.plan("One. Two.", unit="sentence")
    plan.save("speech.utterplan.json")
    normal = pipe.render_plan(plan, length_scale=1.0)
    fast = pipe.render_plan(plan, length_scale=0.9)

AudioJob production and replay

An existing plan can be converted to a generic, persisted AudioJob without composing it in PiperSynth:

job = pipe.to_audio_job(plan)
manifest = job.save("speech.audiojob")

AudioClip IDs preserve UtterPlan segment IDs. Resolved semantic pauses are explicit Silence items, and the job includes an explicit compatibility output policy. Replay is producer-neutral:

from audiocompose import AudioJob, Composer

job = AudioJob.load("speech.audiojob/audiojob.json")
composition = Composer().compose(job)

The normal render_plan() API builds and composes this job exactly once, then adapts the composed waveform back to AudioResult. Streaming APIs remain a separate batch-independent path.

Runnable examples

The maintained examples use catalog voices and require no manual model download. They explicitly create and persist an UtterancePlan before rendering it. Generated plans and WAV files are written below example-artefacts/. See examples/README.md.

python examples/basic.py
python examples/run_all.py

Use is_phonemes=True only for direct Piper phoneme input. It bypasses UtterPlan and does not attach a semantic plan to the result.

Local models

Existing explicit local model usage remains network-free:

from pipersynth import PiperPipeline, PipelineConfig

with PiperPipeline(PipelineConfig(model_path="voice.onnx")) as pipe:
    pipe("No network is used here.").save_wav("local.wav")

PiperVoice.load() and PiperPipeline(PipelineConfig(...)) never resolve the catalog or download assets. Use PiperVoice.from_pretrained() or PiperPipeline.from_pretrained() when managed catalog resources are desired.

Calibrated voice leveling

PiperSynth can apply a fixed, offline-measured gain for an exact managed Piper catalog voice, quality, and numeric speaker identity:

from pipersynth import LoudnessConfig, PiperPipeline

with PiperPipeline.from_pretrained(
    "en_US-lessac-medium",
    loudness=LoudnessConfig(voice_leveling="calibrated"),
) as pipe:
    result = pipe.run("Hello from PiperSynth.")

Calibrated voice leveling is not dynamic normalization: synthesis never measures LUFS and the gain does not guarantee a final LUFS value for arbitrary text. It is applied after legacy peak normalization, before user or SSMD volume, and before the final clamp. voice_gain_db is an explicit gain override and works for managed and local voices.

Calibration keys are canonical piper:model-id:quality:speaker-N identities. Every speaker in a multi-speaker catalog model is measured independently; single-speaker models use speaker-0. Anonymous local models have no guessed catalog key, and missing records are safe no-ops with diagnostic metadata.

Complete-output normalization remains separate. Set target_lufs in LoudnessConfig only for batch composition; true streaming APIs reject it rather than normalizing each unit independently.

The packaged catalog is generated from corpus pipersynth-count-1-to-10-v1 at reference -24 LUFS with a -1 dBTP calibration ceiling. To regenerate it, run the full unfiltered benchmark, review summary.md, then promote its report with benchmarks/voice_loudness_calibration.py. Benchmark output is written below benchmarks/output/ and never overwrites production data automatically.

Voice discovery and cache

from pipersynth import VoiceAssetManager, list_voices

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

manager = VoiceAssetManager()
metadata = manager.get_voice_metadata("en_US-lessac-medium")
bundle = manager.resolve_voice("en_US-lessac-medium")
print(bundle.model_card_text)

Set ONNXVOICE_CACHE_DIR or pass cache_dir= explicitly to control the OnnxVoice store. PIPERSYNTH_CACHE_DIR remains accepted as a PiperSynth compatibility alias. Set PIPERSYNTH_OFFLINE=1 for process-wide offline operation. Explicit offline= arguments take precedence.

OnnxVoice owns installed artifacts, manifests, checksums, and locks. PiperSynth's VoiceAssetManager and VoiceBundle are compatibility views over that store. Voice licenses apply to the downloaded model and are not part of the PiperSynth Apache-2.0 license.

The Python API provides catalog and cache operations:

from pipersynth import VoiceAssetManager

manager = VoiceAssetManager()

# List voices
for voice in manager.list_voices(language="en", quality="medium"):
    print(voice.id, voice.name)

# Get voice metadata
metadata = manager.get_voice_metadata("en_US-lessac-medium")
print(metadata.id, metadata.name, metadata.language_code, metadata.quality)

# Download/resolve a voice
bundle = manager.resolve_voice("en_US-lessac-medium")
print(bundle.directory)
print(bundle.model_card_text)

# Cache operations
print(manager.cache_info())
for cached in manager.cached_voices():
    print(cached.directory)

# Destructive operations (use with caution)
# manager.remove_voice("en_US-lessac-medium")
# manager.prune()
# manager.clear(voices=True)

Optional features

The UtterPlan dependency provides Spokenform and SSMD planning. Install pipersynth[playback] for AudioResult.play() and streaming playback, or pipersynth[gpu] for the OnnxVoice GPU provider. Catalog support is provided by OnnxVoice and is also available as pipersynth[catalog].

The core API supports sentence and paragraph units through UtterPlan, resolved semantic pauses, plan save/load, and PCM iteration through iter_pcm(). It does not claim generic voice blending, approximate word timings, hidden language detection, model conversion, training, quantization, or HTTP serving.

See docs/architecture.md, docs/providers.md, docs/troubleshooting.md, and examples/download_and_synthesize.py.

Release files for pipersynth 0.1.3

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.1.3
File Size Uploaded
pipersynth-0.1.3.tar.gz 369.7 kB Details

Built distribution (wheel)

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

Total release size: 526.7 kB

Release files / pipersynth-0.1.3.tar.gz

Download URL pipersynth-0.1.3.tar.gz
Size 369.7 kB
Tags Source
SHA-256 checksum
How to use checksums
bb5f527c40005df10e6192fccf0eef31e14f524366afa7a3c4bcbb266f3571b0
BLAKE2b-256 checksum
How to use checksums
4fa3346abad7d5a01b92c495244a671f6786d8a103a6568ba23b701cfb6a976d
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.1.3-py3-none-any.whl

Download URL pipersynth-0.1.3-py3-none-any.whl
Size 157.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3943220307d1346d6d6e5217f93bd37a7106e345a02a8f63ed0d6130792f0cff
BLAKE2b-256 checksum
How to use checksums
886b3678cdcb52a460bbcf9b24cbd15cfe7e50bd24fd03f69b24c6e972f2a531
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.1.3 This release

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