--- language: - ne license: cc-by-4.0 pipeline_tag: text-to-speech library_name: matcha-tts tags: - matcha-tts - text-to-speech - tts - nepali - devanagari - single-speaker - flow-matching - hifi-gan - speech-synthesis --- # Matcha-TTS Nepali — v1, single-speaker (fresh) Self-contained release of a single-speaker Nepali Matcha-TTS model: acoustic checkpoint, vocoder, the exact training configs, the `matcha` package, a seeded synthesis script and reference audio. Everything needed to reproduce the shipped samples bit-for-bit is in this directory. > **Access:** this repo is gated — submit an access request from the file > listing and it will be reviewed. For questions or to be whitelisted, contact > **smartharry499@gmail.com**. | | | | --- | --- | | Run | `logs/train/nepali_real_fresh/runs/2026-08-11_15-33-57` | | Repo commit | `e154b4b7f23c25010f3951b594ae310d7c5d1b9b` (branch `feature/finetune-english-male-voice`) | | Trained | 2026-08-11, single NVIDIA GB10, 1000 epochs | | Sample rate | 22 050 Hz, 80-band mel, hop 256 | | Speakers | 1 (single voice) | | Vocabulary | `union` symbol set, `n_vocab = 264` | | Params | 20.9 M | | Training data | chatterbox-nepali corpus (~1441 utterances), Devanagari only | ## Which checkpoint to use Two checkpoints are shipped so they can be compared by ear. | file | epoch | step | note | | --- | --- | --- | --- | | **`matcha_nepali_fresh.ckpt`** (default) | 249 | 5750 | **best** `loss/val_epoch = 2.7284` | | `matcha_nepali_fresh_epoch999.ckpt` | 999 | 23000 | final / `last.ckpt` | `synthesize.py` loads the **epoch 249** checkpoint by default. The run trained the full 1000 epochs (its original config had `max_epochs: 1000`), but the best validation loss is epoch 249 and the experiment config now notes that longer runs overfit and degrade prosody. The shipped samples are all rendered from epoch 249. ## Contents ``` version1-nepali-fresh/ ├── README.md this file ├── synthesize.py seeded, standalone synthesis (no speaker id) ├── synth_samples.sh regenerates samples/{short,medium,long}.wav ├── requirements.txt exact pinned runtime ├── MANIFEST.sha256 checksums for every shipped file ├── checkpoints/ │ ├── matcha_nepali_fresh.ckpt epoch 249 (best) — default │ └── matcha_nepali_fresh_epoch999.ckpt epoch 999 (final) ├── vocoder/ │ └── g_02500000 HiFi-GAN universal v1 generator ├── configs/ │ ├── experiment_nepali_real_fresh.yaml hydra experiment config │ ├── data_nepali_real.yaml hydra data config │ ├── train_config_resolved.yaml fully-resolved config as trained │ ├── train_overrides.yaml CLI overrides for the run │ └── train.log training log for the run ├── matcha/ the model/text/vocoder package └── samples/ ├── texts.txt the 3 source sentences ├── phonemes.txt their G2P output + token counts ├── short.wav / medium.wav / long.wav epoch 249, seeded ``` ## Synthesis ```bash pip install -r requirements.txt # see the note about `real_nepali` # single sentence python synthesize.py --text "नमस्कार, तपाईंलाई नमस्ते।" --out out.wav # the two-length reference set bash synth_samples.sh # the final (epoch 999) checkpoint instead python synthesize.py --ckpt checkpoints/matcha_nepali_fresh_epoch999.ckpt \ --text "नमस्कार, तपाईंलाई नमस्ते।" --out out.wav ``` Defaults: `--steps 25 --temperature 0.667 --denoiser_strength 0.02 --symbols union`, HiFi-GAN universal v1. Useful extras: `--speaking_rate 1.1` (>1 is slower), `--lowpass_khz 9` (tames HF hiss), `--print-phonemes`. This is a **single-speaker** model — there is no `--spk` flag; speaker conditioning is not part of the encoder, so `spks` is always `None`. ### Text frontend Devanagari is phonemized by the hand-written `real_nepali` G2P (profile `real_nepali_v0.2`), **not** espeak-ng — it comes from the `nepali_frontend` repo, pinned at commit `b7395f28`, installed editable. `samples/phonemes.txt` records the exact token string and id count for each sample sentence — diff against it (or `--print-phonemes`) to confirm your frontend matches this release before blaming the acoustic model. ## Reproducibility `synthesize.py` seeds the RNG per utterance (`--seed`, default `1234`). This matters: the flow-matching prior is `torch.randn_like(mu) * temperature`, and unseeded runs give slightly different audio every time. Seeding is why the shipped wavs have stable checksums. ```bash PYTHON=python bash synth_samples.sh # re-render the three sample wavs sha256sum -c MANIFEST.sha256 # confirm byte-for-byte match ``` Verified bit-exact on the training machine (NVIDIA GB10, CUDA 13.0, torch 2.13.0+cu130). On different GPU/CUDA/library versions the audio is perceptually identical but checksums will differ. Pass `--seed -1` for varied output. ## Training recipe Warm-started from the English LJSpeech base checkpoint after its vocabulary was extended to the union set (`scripts/extend_vocab.py` → `checkpoints/matcha_tts_english_plus_nepali.ckpt`), then trained on the Nepali (chatterbox) phone stream. | | | | --- | --- | | Init | `checkpoints/matcha_tts_english_plus_nepali.ckpt` | | Optimizer | Adam, lr `1e-4`, no scheduler, weight decay 0 | | Epochs | 1000 (ran to completion at training time) | | Batch | 32, `accumulate_grad_batches: 2` (effective 64) | | Precision | `16-mixed`, `gradient_clip_val: 5.0` | | Encoder | RoPE, 6 layers, 192 ch, 2 heads (single-speaker: spk path not wired) | | Decoder | CFM/euler, `sigma_min 1e-4`, channels [256, 256], snakebeta | | Mel stats | `mel_mean -5.980818`, `mel_std 2.582703` | | Seed | 1234 | Full settings in `configs/train_config_resolved.yaml`. ## Known limitations - Trained on a **single** voice from the chatterbox-nepali corpus; there is no speaker conditioning, so you cannot pick between voices with this model. - Training data is **Devanagari-only**; code-switched Nepali+English is not covered by the training set. - The run was originally allowed to train 1000 epochs; validation loss bottoms out around epoch 249 and the config note warns later epochs overfit and add noise. Prefer the shipped **epoch 249** checkpoint.