Santali Piper VITS
A single-speaker Santali (sat) text-to-speech model for the Ol Chiki script, trained with the Piper VITS pipeline on the Santali female corpus of AI4Bharat Rasa.
It is exported to ONNX for offline, on-device inference, including Android. A deterministic Santali phonemizer (Python and Kotlin) converts Ol Chiki text into IPA phoneme tokens before they reach the model.
Model Summary
| Property | Value |
|---|---|
| Language / script | Santali (sat), Ol Chiki |
| Architecture | Piper VITS |
| Speaker | Single speaker (Rasa Santali Female), sid = 0 |
| Sample rate | 22050 Hz |
| Phoneme vocabulary | 238 symbols (custom Santali inventory) |
| Training data | 11,767 utterances, about 20.16 hours |
| Training | 175 epochs, batch size 16 per GPU, 2 × NVIDIA Tesla T4, FP16 mixed precision |
| Release checkpoint | training/best_mos.ckpt (epoch 171) |
| Deployment format | ONNX |
The default model, model/santali_piper_vits.onnx, is the ONNX export of the best MOS checkpoint at epoch 171.
Quick Start
Android
Download the all in one package, extract it, and add the files to your app:
santali_piper_vits_onnx_android.tar.gz
It contains santali_piper_vits.onnx, santali_piper_vits.onnx.json, SantaliPhonemizer.kt, phoneme_id_map.json, and config.json. Phonemize the text with SantaliPhonemizer.kt, map tokens to IDs with phoneme_id_map.json, and run the model with ONNX Runtime.
Python
pip install onnxruntime numpy soundfile huggingface_hub
import json
import numpy as np
import onnxruntime as ort
import soundfile as sf
from huggingface_hub import snapshot_download
root = snapshot_download("kaushalkrishnax/santali-piper-vits")
with open(f"{root}/model/santali_piper_vits.onnx.json", encoding="utf-8") as f:
cfg = json.load(f)
id_map = cfg["phoneme_id_map"]
inf = cfg["inference"]
# Tokenize with santali_phonemizer.py from this repo (see the file for its API)
tokens = ... # list of atomic IPA tokens
ids = list(id_map["^"])
for t in tokens:
ids += id_map[t] + id_map["_"]
ids += id_map["$"]
session = ort.InferenceSession(
f"{root}/model/santali_piper_vits.onnx",
providers=["CPUExecutionProvider"],
)
ids = np.array([ids], dtype=np.int64)
audio = session.run(None, {
"input": ids,
"input_lengths": np.array([ids.shape[1]], dtype=np.int64),
"scales": np.array(
[inf["noise_scale"], inf["length_scale"], inf["noise_w"]],
dtype=np.float32,
),
"sid": np.array([0], dtype=np.int64),
})[0].squeeze()
sf.write("output.wav", audio, cfg["audio"]["sample_rate"])
How It Works
Ol Chiki text → Santali phonemizer → IPA tokens → phoneme_id_map.json → ONNX model → audio
The model does not contain any text to phoneme logic, so the phonemizer is a required part of inference. Phonemization, tokenization, and the phoneme ID map must match what was used in training. Changing any of them independently produces inputs the network was not trained on.
SantaliPhonemizer.kt mirrors the reference santali_phonemizer.py, including Ol Chiki normalization, IPA conversion, coda handling, and Phaarkaa behavior, so Android apps do not depend on Python.
Inference Parameters
The ONNX model takes input, input_lengths, scales, and sid. scales is [noise_scale, length_scale, noise_w].
| Parameter | Default | Effect |
|---|---|---|
noise_scale | 0.0 | Voice variability |
length_scale | 1.0 | Speaking rate (higher is slower) |
noise_w | 0.0 | Duration variability |
These defaults are stored in model/santali_piper_vits.onnx.json, so applications can read them from the config directly.
Repository Layout
.
├── model/
│ ├── santali_piper_vits.onnx
│ └── santali_piper_vits.onnx.json
├── training/
│ ├── best_mos.ckpt # Release checkpoint (epoch 171)
│ ├── best.ckpt # Best validation mel loss
│ ├── last.ckpt # Latest state, for resuming training
│ ├── checkpoint_index.json
│ └── config.json
├── dataset/
│ ├── rasa_female_metadata.csv
│ └── rasa_female_metadata.parquet
├── santali_piper_vits_onnx_android.tar.gz
├── SantaliPhonemizer.kt
├── santali_phonemizer.py
├── phoneme_id_map.json
├── phoneme_training.csv
├── phoneme_training_metadata.parquet
├── config.json
├── runtime_config.json
└── model_manifest.json
Raw WAV files, training caches, the Piper source tree, and intermediate exports are not included.
Training Details
Data. The Santali female portion of AI4Bharat Rasa, filtered and preprocessed into 11,767 utterances (about 20.16 hours). Only processed metadata is published here. The source audio is not redistributed.
Setup. Piper VITS with a phoneme ID input type and a custom Santali phoneme vocabulary instead of the default English inventory. The run targeted 175 epochs, and training/config.json holds the full training configuration.
Checkpoints. The training/ folder keeps the main checkpoints so alternative selections and resumed training remain possible.
Limitations
- Mispronunciation of rare, borrowed, or unseen words
- Differences between written forms and expected spoken forms
- Occasional prosody inconsistencies and synthesis artifacts
- Reduced quality on text far from the training distribution
- One female voice, so dialects and speaking styles are not covered
License
The model and code in this repository are released under Apache-2.0. The Rasa dataset has its own license and attribution terms, so review them before redistributing source data or derived materials. Piper and its components keep their own licenses.
Citation
@misc{kaushal2026santalipipervits,
author = {Kaushal, Krishna},
title = {Santali Piper VITS},
year = {2026},
publisher = {Hugging Face},
url = {https://huggingface.co/kaushalkrishnax/santali-piper-vits}
}