File size: 7,512 Bytes
80be62c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72ba36a
80be62c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1d61dcb
d296d19
80be62c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
---
license: cc-by-nc-4.0
language:
  - ne
  - en
pipeline_tag: text-to-speech
library_name: pytorch
tags:
  - text-to-speech
  - tts
  - nepali
  - styletts2
  - kokoro
  - customer-service
---

# Swar

**Swar** (स्वर, "voice") is a small, experimental text-to-speech model for **Nepali and
English**, including sentences that mix the two, tuned toward a calm customer-service manner
of speaking.

- **38.5 M parameters**, 16 kHz output. The architecture is derived from
  [Kokoro-82M](https://huggingface.co/hexgrad/Kokoro-82M) (StyleTTS2 family), built from its layer
  classes: non-autoregressive, so a sentence is generated in one pass.
- Reads **Devanagari and Latin letters directly**: no phonemiser, no language switch.
  Numbers, currency ("Rs. 250", "रु ५००"), times and phone numbers are written out in words in
  the language of their sentence.
- **Default voice: `bijaya`** (`voices/bijaya.pt`). Any 3-10 s clip of one speaker gives
  another voice.
- Fast: about **15x real time on a desktop CPU** with all cores, about 6x on a single thread,
  and about 30x on a consumer GPU (measured on a Ryzen 9 5900X and an RTX 3090).

Try it in the Space: [Nepali Call Center Experimental - Powered by Swar](https://huggingface.co/spaces/elitexp/Nepali-Swar-Call-Center-Experimental).

## Quick start

```bash
pip install torch torchaudio transformers safetensors huggingface_hub soundfile
```

```python
import sys, soundfile as sf
from huggingface_hub import snapshot_download

folder = snapshot_download("elitexp/Swar")
sys.path.insert(0, folder)
from swar import Swar

tts = Swar.from_pretrained(folder)                       # GPU if available, else CPU
wav, sr = tts.synthesize("नमस्ते, ग्राहक सेवा केन्द्रमा यहाँलाई स्वागत छ।")   # voice "bijaya"
sf.write("hello.wav", wav, sr)

# another voice from a reference clip, a little slower, with clear pauses at punctuation
wav, sr = tts.synthesize("Your balance is Rs. 250. धन्यवाद।",
                         voice="my_reference.wav", speed=0.95, pause_floor_ms=300)
```

From the command line, inside the downloaded folder:

```bash
python -m swar.inference "नमस्ते, यहाँलाई स्वागत छ।" -o hello.wav
```

### Options

| argument | meaning |
|---|---|
| `voice` | a name from `voices/` (default `bijaya`), a `.pt` of style vectors, or an audio clip (wav / flac / mp3 / ogg) |
| `speed` | 0.5-2.0, scales the predicted durations (1.0 = as predicted) |
| `pause_floor_ms` | every comma / full stop / question mark *inside* a sentence lasts at least this long (0 = as predicted) |
| `loanwords` | in a mostly-Nepali sentence, common English words are said the Nepali way ("recharge" -> रिचार्ज, "balance" -> ब्यालेन्स; list in `swar/loanwords.py`). Default on |
| `sentence_pause_ms` | silence between two sentences (default 350); the start and end of each sentence are trimmed, so the first sound comes within about 0.1 s |
| `return_info` | also return timing and the exact letters the model read |

## What is inside

| part | params | role |
|---|---|---|
| PL-BERT (ALBERT, letters) + projection | 3.5 M | contextual letter features |
| prosody predictor | 9.7 M | duration per letter, pitch and energy at 80 Hz |
| prosodic style encoder | 3.5 M | manner of speaking from a reference clip |
| text encoder | 3.2 M | letter features for the decoder |
| decoder (iSTFTNet with harmonic source) | 15.1 M | waveform at 16 kHz |
| acoustic style encoder | 3.5 M | timbre from a reference clip |

A voice is two 128-d vectors: acoustic (timbre, read by the decoder) and prosodic (manner,
read by the predictor). `voices/bijaya.pt` stores them as `{"s_ac", "s_pr"}`.

Files: `swar.safetensors` (inference weights only), `config.json`, `swar/` (model,
text front-end, mel, inference; Kokoro's layer code is vendored under `swar/kokoro/` with its
Apache-2.0 licence), `voices/`.

## Training

Trained from scratch in five stages, after the StyleTTS2 / Kokoro recipe adapted to letters at
16 kHz:

1. **PL-BERT** on Nepali and English text (masked letters).
2. **Letter aligner** (CTC) on both languages, for durations.
3. **Acoustic model**: text encoder, decoder and both style encoders, adversarial training with
   multi-period and multi-resolution discriminators (300 k steps).
4. **Prosody**: duration, pitch and energy predictors and the prosodic style encoder (100 k steps).
5. **Register**: a short fine-tune (6 k steps) of the prosody half on about 8 hours of
   customer-service style Nepali recordings, with general data replayed so the rest of the model
   does not drift.

Data (acoustic and prosody stages): about 800 hours of Nepali speech from public corpora
(including OpenSLR 43 and OpenSLR 143) and other licensed and in-house recordings, part of it
synthetic, and about 570 hours of English speech synthesised with Kokoro-82M (`af_heart`).

## Evaluation

- **Copy-synthesis intelligibility** (stage 3, durations and pitch taken from the real clip,
  recognised by the same ASR as the real recordings): Nepali character error rate through a
  G.711 telephone channel 0.199 against 0.220 for the real recordings (285 clips); English word
  error rate 0.097 against 0.098 (200 clips).
- **Customer-service register** (stage 5): median pitch stays within 15 Hz of the reference
  voice. The pause rate (about 0.13 pauses per second, about 0.20 with `pause_floor_ms=300`)
  is still below the 0.30-0.45 target band: pauses are only lengthened where the text has
  punctuation.
- Full text-to-speech intelligibility has not yet been measured with the same protocol.

## Limitations

- Experimental. Rare words, names and some English spellings can be mispronounced; Nepali
  rhythm is less polished than English.
- 16 kHz, telephone-oriented; not a studio-quality voice.
- Voices from a reference clip copy that clip's recording conditions too; use clean audio.

## Responsible use

Swar can speak in a voice taken from a short recording. Only use voices you have permission to
use, label synthetic speech as synthetic where people could mistake it for a person, and do not
use the model to impersonate anyone or to deceive.

## Acknowledgements

Swar would not exist without **[Kokoro-82M](https://huggingface.co/hexgrad/Kokoro-82M)** by
hexgrad. Its architecture is Swar's blueprint: the text encoder, the prosody predictor (duration,
pitch and energy), the iSTFTNet decoder with its harmonic source and the split acoustic / prosodic
style design all come from Kokoro, and Kokoro's own layer code is vendored in `swar/kokoro/`. Swar
re-sizes that design for 16 kHz, reads letters instead of phonemes, adds trainable style encoders
and is trained from scratch; Kokoro (voice `af_heart`) also generated Swar's English training
speech. Kokoro in turn builds on [StyleTTS2](https://github.com/yl4579/StyleTTS2) (Li et al.), whose
style encoder and PL-BERT recipe Swar also uses.

## License

The Swar weights (`swar.safetensors`, `voices/`) and Swar's own code are released under
**[CC BY-NC 4.0](https://creativecommons.org/licenses/by-nc/4.0/)**: free for research and other
non-commercial use, with attribution. The vendored Kokoro code in `swar/kokoro/` stays under its
original Apache-2.0 licence (`swar/kokoro/LICENSE`); the StyleTTS2 style encoder code is MIT.
Training data includes [OpenSLR](https://www.openslr.org/) corpora under their own licences.