Downloads · 30 days
65
21% of all-time downloads
naklitechie/indic-parler-tts-ONNX
indic-parler-tts-ONNX is a text-to-audio model from naklitechie. Use it for the text-to-audio task on the model card, and read the license before you ship it in a product. It is set up for transformers.js. The card lists the license as apache-2.0.
This is a verbatim ONNX export of ai4bharat/indic-parler-tts for in-browser inference via onnxruntime-web or transformers.js.
Downloads · 30 days
65
21% of all-time downloads
All-time downloads
315
Public
Repo size
8 GB
Likes
1
Public
Click a slice to open those files.
.data8 GB · 100%
From the Hugging Face model README
This is a verbatim ONNX export of ai4bharat/indic-parler-tts for in-browser inference via onnxruntime-web or transformers.js.
The upstream model is the multilingual Indic-language fine-tune of Parler-TTS (huggingface/parler-tts) by AI4Bharat. This repo re-exports the same weights as ONNX graphs so they can be loaded into a browser without a Python runtime.
Both precisions ship in this repo following the
onnx-community/dac_44khz-ONNX
convention. fp16 graphs use keep_io_types=True so they are drop-in
replacements for fp32 — consumer code doesn't change tensor dtypes
between sessions when switching variants.
| File | Size | Purpose |
|---|---|---|
text_encoder.onnx + .data | 1.30 GB | fp32 — T5 (flan-t5-large) description encoder |
text_encoder_fp16.onnx + .data | 651 MB | fp16 — same, fp32 I/O |
decoder_model.onnx + .data | 1.98 GB | fp32 — first AR step (codec embed + prompt prefix + cross-attn + 24-layer decoder + fused 9-codebook lm-head) |
decoder_model_fp16.onnx + .data | 992 MB | fp16 |
decoder_with_past_model.onnx + .data | 1.25 GB | fp32 — subsequent AR steps with past KV cache |
decoder_with_past_model_fp16.onnx + .data | 622 MB | fp16 |
tokenizer.json, tokenizer.model, tokenizer_config.json | 12 MB | LlamaTokenizerFast, vocab 90,714 — used for both description AND prompt |
config.json, generation_config.json, special_tokens_map.json | small | Model + generation config |
Bundle totals:
The DAC 44.1 kHz vocoder (onnx-community/dac_44khz-ONNX, referenced separately — pick its decoder_model_fp16.onnx at 104 MB) is needed to turn the decoder's codec tokens into audio waveform.
Conversion via onnxruntime.transformers.float16.convert_float_to_float16(..., keep_io_types=True) with the default ORT op-block list. Verified on CPU EP:
| Graph | Max abs diff |
|---|---|
text_encoder_fp16.onnx | 8.6×10⁻³ |
decoder_model_fp16.onnx | 1.8×10⁻² |
decoder_with_past_model_fp16.onnx | (sanity only — finite outputs across full step) |
All within typical fp16 transformer tolerances (≤5×10⁻² is the gate). Audio quality is indistinguishable in practice for VITS-derived TTS.
// Browser, prefer fp16 unless you need bit-exact PyTorch reproduction
const url = (file) =>
`https://huggingface.co/naklitechie/indic-parler-tts-ONNX/resolve/main/${file}`;
const dtype = 'fp16'; // or 'fp32'
const suffix = dtype === 'fp16' ? '_fp16' : '';
const sess = await ort.InferenceSession.create(
await fetch(url(`text_encoder${suffix}.onnx`)).then(r => r.arrayBuffer()),
{
externalData: [{
data: await fetch(url(`text_encoder${suffix}.onnx.data`)).then(r => r.arrayBuffer()),
path: `text_encoder${suffix}.onnx.data`,
}],
executionProviders: ['webgpu', 'wasm'],
}
);
prompt_tokenizer/ subfolder is a documentation artifact — both inputs use the same LlamaTokenizerFast, vocab 90,714).prompt_cross_attention=False — prompt embeddings are prefixed to the decoder's input embeddings, not cross-attended. The decoder's self-attention KV cache region therefore covers (prompt_len + codec_len) positions after step 1.Linear: 1024 → 9 × 1088 projection (not 9 separate heads), reshape + transpose inside the graph.text_encoder.onnx| Input | Shape | Type |
|---|---|---|
input_ids | [B, S] | int64 |
attention_mask | [B, S] | int64 |
| Output | Shape | Type |
|---|---|---|
last_hidden_state | [B, S, 1024] | float32 |
decoder_model.onnx (first AR step)| Input | Shape | Type |
|---|---|---|
codec_input_ids | [B, 9, T] | int64 |
prompt_input_ids | [B, P] | int64 |
prompt_attention_mask | [B, P] | int64 |
encoder_hidden_states | [B, S, 1024] | float32 |
encoder_attention_mask | [B, S] | int64 |
| Output | Shape | Type |
|---|---|---|
logits | [9*B, P+T, 1088] | float32 |
present.{i}.{decoder.key,decoder.value,encoder.key,encoder.value} × 24 layers | [B, 16, P+T or S, 64] | float32 |
decoder_with_past_model.onnx (subsequent AR steps)| Input | Shape | Type |
|---|---|---|
codec_input_ids | [B, 9, 1] | int64 |
attention_mask | [B, full_t] | int64 — covers prompt + prior codec + new |
encoder_attention_mask | [B, S] | int64 |
cache_position | [1] | int64 — past_kv_length scalar |
past_key_values.{i}.{decoder.key,decoder.value,encoder.key,encoder.value} × 24 layers | as in present above | float32 |
| Output | Shape | Type |
|---|---|---|
logits | [9*B, 1, 1088] | float32 |
present.{i}.{...} × 24 layers | shifted by 1 in self-attn time dim | float32 |
KV layout per layer: (decoder_self.key, decoder_self.value, encoder_cross.key, encoder_cross.value) — IT2-compatible.
// 1. Encode description
const encOut = await sessText.run({ input_ids, attention_mask });
const enc_h = encOut.last_hidden_state;
// 2. Build initial codec — [B, 9, 1] all START_ID=1025
const codec0 = new BigInt64Array(B * 9 * 1).fill(1025n);
// 3. Build delay-pattern mask (port of parler_tts.build_delay_pattern_mask)
const { initialIds, patternMask } = buildDelayPatternMask({
bos: 1025, pad: 1024, maxLen: 256, numCodebooks: 9,
});
// 4. First step
let { logits, ...present } = await sessDecNoPast.run({
codec_input_ids: initialIds, // [B, 9, T_init]
prompt_input_ids,
prompt_attention_mask,
encoder_hidden_states: enc_h,
encoder_attention_mask: attention_mask,
});
// 5. Greedy AR loop — apply delay pattern between steps
for (let step = 1; step < maxSteps; step++) {
const next = applyDelayPatternMask(argmaxLogits(logits), patternMask, step);
({ logits, ...present } = await sessDecWithPast.run({
codec_input_ids: next,
attention_mask: buildFullAttnMask(promptLen + step),
encoder_attention_mask,
cache_position: BigInt(promptLen + step),
...present, // re-feed all 96 KV tensors
}));
}
// 6. Decode codec tokens → audio via DAC
// use onnx-community/dac_44khz-ONNX decoder
The apply_delay_pattern_mask and build_delay_pattern_mask functions need porting to JS — reference the Python source in parler_tts/modeling_parler_tts.py.
4.72e-61.91e-51.68e-4All well below the typical fp32-sufficient 1e-3 tolerance.
If you use this in research or production, please cite the original AI4Bharat work:
@misc{indic-parler-tts,
title = {Indic Parler-TTS},
author = {AI4Bharat},
year = {2024},
url = {https://huggingface.co/ai4bharat/indic-parler-tts}
}
And the upstream Parler-TTS:
@misc{lacombe-etal-2024-parler-tts,
author = {Yoach Lacombe and Vaibhav Srivastav and Sanchit Gandhi},
title = {Parler-TTS},
year = {2024},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {\url{https://github.com/huggingface/parler-tts}}
}
Apache 2.0 — same as the upstream ai4bharat/indic-parler-tts. See NOTICE.md for attribution.