Instructions to use sujitvasanth/piper-mnn-cpugpu-inputoutput-streaming with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Piper
How to use sujitvasanth/piper-mnn-cpugpu-inputoutput-streaming with Piper:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Piper MNN β CPU/GPU, streaming input and output
A Piper voice (en_US-data_7024-medium, 22050 Hz) split into two fixed-shape MNN models so it can run
entirely on CPU or GPU (MNN OpenCL) with no graph rebuilding, and accept text word by word (for example
straight from an LLM) while audio streams out.
Files
| File | What it is | SHA-256 |
|---|---|---|
data.encoder.fixed64x160.static.mnn |
Encoder: 64 phoneme IDs β 160 latent frames + per-ID durations | 31a85913846c7c4cefee0db9bf46c917be9558c34aff99edcb72da032ab75584 |
data.decoder.fixed64.mnn |
Decoder: 64 latent frames β 16384 samples (256 per frame) | 390d1c8037a82dfa48e34c2b0dd9e128627cfe10c4823e9e4778a9056de7d0af |
data.onnx.json |
Piper voice config (phoneme ID map, sample rate, default scales) | |
onnx/ |
The same two models in ONNX | |
scripts/ |
Export scripts, Python reference implementation, C++ streaming engine |
Encoder β data.encoder.fixed64x160.static.mnn
Inputs:
inputint32[1, 64]β phoneme IDs, zero-paddedinput_lengthsint32[1]β number of real IDsscalesfloat[3]βnoise_scale, length_scale, noise_w(voice default0.667, 1.0, 0.8)noise_dpfloat[1, 2, 64]β standard normal noise for the duration predictornoise_zfloat[1, 192, 160]β standard normal noise for the latent prior
Outputs:
zfloat[1, 192, 160]β latent frames (frames pastframesare masked to zero)durationsfloat[1, 1, 64]β frames per input IDframesfloat[1]β real frame count (speech longer than 160 frames is cut off)
Changes from the stock Piper export:
- fixed input/output sizes (total frame count is a constant, so no data-dependent shapes)
- the two random-noise nodes are inputs, so overlapping windows can reuse the same noise
- the duration predictor's spline flows no longer use
NonZero/GatherND/ScatterNDwith data-dependent sizes; they run densely with masks. Output is bit-identical to the original.
Decoder β data.decoder.fixed64.mnn
Inputs: z float [1, 192, 64] and masks valid_mask_1/8/64/256 float [1, 1, 64Γscale]
(1 where the frame is real, 0 for padding). Output: output float [1, 1, 1, 16384].
Use 12 frames of context on each side and keep the middle 40 frames (40 Γ 256 samples). Assembled chunks match whole-utterance decoding to about 7Γ10β»β· relative error.
Streaming text in
- Phonemize the text so far (eSpeak NG, as Piper does) and turn each new word into IDs: a leading space ID
(or
^for the first word), then each phoneme followed by_. End of text adds$. - Window = 2 words of left context + new words, padded to 64 IDs.
- Run the encoder; use
durationsto find frame offsets. - Commit audio up to the last word boundary that has 1 whole word of look-ahead after it (and keeps 12 frames of right context for the decoder).
- Decode the committed frames in 64-frame chunks; play them.
- Next window starts 2 words before the commit point.
Tested settings (Android, GPU): commit 2β3 words per window (3 sounds more coherent), no pre-buffer, 2-frame (β23 ms) crossfade between windows. On a desktop CPU each window is about 17 ms encoder + 17 ms decoder.
See scripts/word_stream_piper.cpp for the C++ engine and scripts/stream_text_windows.py for the
Python reference.
Source
Derived from the Piper voice en_US-data_7024-medium (see data.onnx.json). Check that voice's
original licence before redistributing.
- Downloads last month
- 39