File size: 9,429 Bytes
2ad314c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
---
license: other
license_name: mixed-mit-and-apache-2.0
license_link: LICENSE
language:
  - hi
  - en
  - bn
  - gu
  - kn
  - ml
  - mr
  - ta
  - te
library_name: onnx
pipeline_tag: text-to-speech
tags:
  - onnx
  - onnxruntime
  - text-to-speech
  - translation
  - on-device
  - android
  - indic
---

# EchoBharat models

Quantized ONNX models for [EchoBharat](https://github.com/raunaksahahere/EchoBharat), an
offline multilingual voice transceiver for Android. Phones turn speech into text locally,
send only the text across a Bluetooth LE mesh, and turn it back into speech on the other
side.

Everything here is a **derived redistribution** of work by other people. Nothing in this
repository was trained here. See [Licensing](#licensing) before you use any of it — the
files are not all under the same terms.

## What is in this repository

| Path | Contents | Derived from |
|---|---|---|
| `<lang>/fastpitch-<lang>.int8.onnx` | FastPitch acoustic model | AI4Bharat Indic-TTS |
| `<lang>/hifigan-<lang>.int8.onnx` | HiFi-GAN vocoder | AI4Bharat Indic-TTS |
| `<lang>/fastpitch-<lang>.tokens.json` | symbol table, indexed by token id | AI4Bharat Indic-TTS |
| `<lang>/sample-<lang>.wav` | a sample utterance, for listening | generated here |
| `mt/<lang>/mt-*-encoder.int8.onnx` | IndicTrans2 encoder | AI4Bharat IndicTrans2 |
| `mt/<lang>/mt-*-decoder.int8.onnx` | IndicTrans2 decoder | AI4Bharat IndicTrans2 |
| `mt/<lang>/mt-*-bpe-{src,tgt}.tsv` | flattened BPE vocabulary | AI4Bharat IndicTrans2 |
| `mt/<lang>/mt-*-meta.json` | language-tag ids and vocab sizes | AI4Bharat IndicTrans2 |

**Speech recognition is not hosted here.** EchoBharat uses the Apache-2.0 IndicConformer
conversions published at
[`parismitaglobalsolutions/indicconformer-sherpa-onnx`](https://huggingface.co/parismitaglobalsolutions/indicconformer-sherpa-onnx)
and links to them directly. They are documented below because anyone assembling a full
voice pack needs all three pieces.

## Graph contracts

Read off the exported graphs, not copied from upstream documentation.

### Speech-to-text — IndicConformer (hosted elsewhere, listed for completeness)

```
input   audio_signal  [B, 80, T]  float32     log-mel features
        length        [B]         int64       valid frames per item
output  logprobs      [B, T/4, V] float32     V = 5633 for the released vocabularies
```

Features are NeMo-compatible: 25 ms window, 10 ms hop, 512-point FFT, 80 Slaney mel bins,
0.97 pre-emphasis, log, then `per_feature` normalisation. Subsampling factor is 4.
Decoding is greedy CTC, and the blank token `<blk>` lives **inside** the vocabulary at id
5632 rather than being appended after it — assuming the usual "blank is index V" produces
plausible-looking but wrong transcripts.

### Text-to-speech — FastPitch + HiFi-GAN

```
fastpitch  input   text   [1, T]      int64     token ids from the .tokens.json table
           output  mel    [1, 80, F]  float32
hifigan    input   mel    [1, 80, F]  float32
           output  audio  [1, 1, S]   float32   22050 Hz, mono, roughly [-1, 1]
```

Both are int8 dynamically quantized, weights only. The token axis and frame axis are
dynamic. The two stages are exported separately rather than fused, so the vocoder — the
expensive half — can be swapped or requantized on its own.

Tokenisation is longest-match against the symbol table in `fastpitch-<lang>.tokens.json`,
where the first id wins on duplicates.

> **Exporter note.** FastPitch must be exported with PyTorch's **dynamo** exporter. Its
> `fftransformer` encoder is built on `torch.nn.MultiheadAttention`, which bakes the traced
> sequence length into a `Reshape` under the legacy TorchScript tracer. The result loads
> without complaint and then fails at runtime on any sentence that is not exactly the dummy
> length: `input_shape_size == requested_shape_size was false … requested shape:{24,1,512}`.

### Translation — IndicTrans2 (distilled 200M)

```
encoder  input   input_ids              [B, S]       int64
                 attention_mask         [B, S]       int64
         output  last_hidden_state      [B, S, 512]  float32

decoder  input   input_ids              [B, T]       int64
                 encoder_attention_mask [B, S]       int64
                 encoder_hidden_states  [B, S, 512]  float32
         output  logits                 [B, T, V]    float32
                 present.*              (72 KV-cache tensors)
```

`decoder_start_token_id` = 2, which is also `</s>`. `pad` = 1, `bos` = 0, `unk` = 3.
Maximum source length is 256 tokens. The decoder here is the **cacheless** variant, so a
greedy loop re-runs the whole prefix each step; the 72 `present.*` outputs are ignored.
Using `decoder_with_past_model.onnx` instead is the obvious speed-up.

The source sequence is `[<src_lang_tag>, <tgt_lang_tag>, …bpe pieces, </s>]`.

**Two traps worth stating plainly:**

1. The SentencePiece piece ids and the ONNX graph vocabulary ids are **different**.
   Upstream ships a `.model` file *and* a separate `dict.*.json`; conflating the two
   produces fluent nonsense rather than an error. The `bpe-*.tsv` files here are the two
   joined together — `piece <TAB> score <TAB> graph_id` — so this cannot be got wrong. A
   `graph_id` of `-1` means the piece exists in SentencePiece but not in the graph
   vocabulary and must resolve to `<unk>`.
2. The FLORES language-tag ids **differ per direction**: `hin_Deva` is `8` going
   Indic→English and `15` going English→Indic. Hardcoding either value silently corrupts
   the other direction. They ship in `mt-*-meta.json`.

## Which translation direction goes on which phone

EchoBharat translates **on receive, never on send**. A sender transmits in its own
language and tags the packet with that language; each receiving phone translates into
whatever language *it* is set to. That is what lets one broadcast reach a Hindi speaker
and an English speaker simultaneously, each hearing their own — a sender that translated
first would have to pick one target and the broadcast would stop being multilingual.

The consequence for packaging: **a phone needs only the direction *into* its own
language.**

| Phone's language | Needs | Files | Size |
|---|---|---|---|
| English | Hindi → English | `mt/en/mt-hi-en-*` | 226 MB |
| Hindi | English → Hindi | `mt/hi/mt-en-hi-*` | 270 MB |

So an English handset carries `mt/en/` and nothing else; it never needs `mt/hi/`.

Translation is available for **Hindi ↔ English only**. The other languages have
speech-to-text and text-to-speech but no translation pair, and the app reports that
honestly rather than passing text through as though it had been translated.

## Licensing

These files are **not all under one license.** Redistributing them means honouring each
upstream's terms separately.

| Component | Upstream | Upstream license | Notes |
|---|---|---|---|
| FastPitch / HiFi-GAN weights | [AI4Bharat/Indic-TTS](https://github.com/AI4Bharat/Indic-TTS) | **MIT** | checkpoints from the `v1-checkpoints-release` GitHub release |
| IndicTrans2 weights | [ai4bharat/indictrans2-*](https://huggingface.co/ai4bharat) | **MIT** | via the ONNX conversion below |
| IndicTrans2 ONNX conversion | [TigreGotico/indictrans2-*-dist-200M-onnx](https://huggingface.co/TigreGotico) | **MIT** | conversion this repo re-quantized/repacked |
| IndicConformer weights *(linked, not hosted)* | [ai4bharat/indicconformer_stt_*](https://huggingface.co/ai4bharat) | **MIT** | |
| IndicConformer ONNX conversion *(linked, not hosted)* | [parismitaglobalsolutions/indicconformer-sherpa-onnx](https://huggingface.co/parismitaglobalsolutions/indicconformer-sherpa-onnx) | **Apache-2.0** | the conversion declares Apache-2.0 even though the upstream weights are MIT; honour both |
| Silero VAD *(shipped in the app, not here)* | [snakers4/silero-vad](https://github.com/snakers4/silero-vad) | **MIT** | |
| Export and packaging scripts | this project | **MIT** | |

The repository is marked `license: other` because a single SPDX identifier would
misrepresent at least one of the components above.

**No new training data was used, and no new model was trained.** Every weight here is a
quantized re-export of a published checkpoint. Attribution belongs to AI4Bharat and to the
authors of the conversions named above.

## Known limitations

- **Quantization is lossy.** All models are int8. Quality is below the fp32 originals; how
  far below has not been measured against a reference.
- **Odia is absent.** No IndicConformer speech-to-text export exists for it, so a voice
  pack would be incomplete in the one direction that matters most.
- **Translation has no KV cache**, so decoding cost grows with the square of the output
  length.
- **No IndicNLP normalisation** in the translation path — NFKC only, unlike the reference
  IndicTrans2 pipeline. Unusual orthography is untested.
- **Voice quality has not been formally evaluated.** Each language ships a
  `sample-<lang>.wav` precisely so it can be listened to rather than taken on trust.

## Citation

Please cite the upstream work rather than this repository.

```bibtex
@article{ai4bharat-indictrans2,
  title   = {IndicTrans2: Towards High-Quality and Accessible Machine Translation
             Models for all 22 Scheduled Indian Languages},
  author  = {AI4Bharat},
  journal = {Transactions on Machine Learning Research},
  year    = {2023}
}
```