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)
| File | Size | Uploaded | |
|---|---|---|---|
| pipersynth-0.1.3.tar.gz | 369.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|