christopherthompson81 commited on
Commit
5daca9d
Β·
verified Β·
1 Parent(s): 7cf98be

Add kokoro_batched.onnx: variable-length batched graph (masked AdaIN + packed LSTMs), supersedes kokoro.onnx

Browse files
Files changed (1) hide show
  1. README.md +31 -2
README.md CHANGED
@@ -42,12 +42,20 @@ layout, for use as the Kokoro text-to-speech engine in
42
  rendered into Kokoro's vocabulary, so the same frontend serves every engine.
43
  - **Voice packs as flat float32**, indexed by phoneme-string length, readable without a
44
  tensor library.
 
 
 
 
 
 
 
45
 
46
  ## Contents
47
 
48
  | File | Purpose |
49
  |---|---|
50
- | `kokoro.onnx` | The whole model: token ids + style vector + speed β†’ 24 kHz waveform (fp32, ~310 MB, weights inlined) |
 
51
  | `voices/<name>.bin` | One voice pack per voice: `510 Γ— 256` float32, little-endian β€” row *n* is the style vector for a phoneme string of length *n + 1* |
52
  | `manifest.json` | Per-file MD5 hashes for integrity checks |
53
 
@@ -63,6 +71,27 @@ layout, for use as the Kokoro text-to-speech engine in
63
  `tokens` and `samples` are dynamic. The context window is 510 tokens; split longer text
64
  on sentence boundaries first.
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  ### Voices
67
 
68
  The 28 English voices of Kokoro v1.0 β€” American (`af_*` / `am_*`) and British
@@ -100,7 +129,7 @@ from huggingface_hub import snapshot_download
100
  import numpy as np, onnxruntime as ort
101
 
102
  path = snapshot_download(repo_id="christopherthompson81/kokoro-82m-onnx")
103
- sess = ort.InferenceSession(f"{path}/kokoro.onnx")
104
 
105
  # ids: Kokoro vocabulary ids for the phoneme string (see upstream / misaki)
106
  ids = np.array([[0, *phoneme_ids, 0]], dtype=np.int64)
 
42
  rendered into Kokoro's vocabulary, so the same frontend serves every engine.
43
  - **Voice packs as flat float32**, indexed by phoneme-string length, readable without a
44
  tensor library.
45
+ - **A variable-length batched graph** (`kokoro_batched.onnx`) that renders several texts of
46
+ *different* lengths in one call, at the model's own fidelity. Kokoro is batch=1 upstream, and
47
+ naive padding corrupts the shorter items β€” AdaIN normalises over time, so padding frames
48
+ pollute the per-item statistics, and the bidirectional LSTMs read padding backwards into real
49
+ tokens and shift the predicted durations. Masking the statistics, packing the LSTMs and
50
+ re-zeroing the padding after each `AdaIN1d` closes all three. It supersedes `kokoro.onnx`,
51
+ being faster even at batch 1.
52
 
53
  ## Contents
54
 
55
  | File | Purpose |
56
  |---|---|
57
+ | `kokoro_batched.onnx` | **Preferred.** The whole model with a dynamic batch axis: renders a padded batch of different-length texts in one call (fp32, ~311 MB, weights inlined) |
58
+ | `kokoro.onnx` | The original batch=1 graph, kept for older clients: token ids + style vector + speed β†’ 24 kHz waveform (fp32, ~310 MB, weights inlined) |
59
  | `voices/<name>.bin` | One voice pack per voice: `510 Γ— 256` float32, little-endian β€” row *n* is the style vector for a phoneme string of length *n + 1* |
60
  | `manifest.json` | Per-file MD5 hashes for integrity checks |
61
 
 
71
  `tokens` and `samples` are dynamic. The context window is 510 tokens; split longer text
72
  on sentence boundaries first.
73
 
74
+ ### ONNX contract β€” `kokoro_batched.onnx`
75
+
76
+ | Name | Shape | dtype | Description |
77
+ |---|---|---|---|
78
+ | `input_ids` (in) | `[batch, tokens]` | int64 | Right-padded token ids, one row per text |
79
+ | `ref_s` (in) | `[batch, 256]` | float32 | Style vector per item (each indexed by *its own* phoneme-string length) |
80
+ | `speed` (in) | `[1]` | float32 | Speech-rate multiplier, shared by the batch |
81
+ | `input_lengths` (in) | `[batch]` | int64 | Real token count per item β€” **required**; padding is masked from it |
82
+ | `audio` (out) | `[batch, samples]` | float32 | 24 kHz waveform, padded to the batch's longest item |
83
+ | `pred_dur` (out) | `[batch, tokens]` | int64 | Per-token frames, 0 on padded tokens |
84
+
85
+ Each item is valid for its **own** `pred_dur.sum() * 600` samples; the rest of its row is batch
86
+ padding, so trim before use. `pred_dur` is identical to what the item gets rendered alone, at any
87
+ batch size β€” so word alignment never depends on which texts share a batch.
88
+
89
+ A batch is padded to its longest item, so grouping texts of **similar length** matters for
90
+ throughput: an unsorted mix of one-line headings and long paragraphs fills only ~37% of the batch
91
+ and is no faster than rendering one at a time. Sorting by phoneme length first roughly doubles it.
92
+ Fidelity does not depend on the grouping β€” the padding error is a step function (two frames of
93
+ padding cost as much as two hundred) and is masked out either way.
94
+
95
  ### Voices
96
 
97
  The 28 English voices of Kokoro v1.0 β€” American (`af_*` / `am_*`) and British
 
129
  import numpy as np, onnxruntime as ort
130
 
131
  path = snapshot_download(repo_id="christopherthompson81/kokoro-82m-onnx")
132
+ sess = ort.InferenceSession(f"{path}/kokoro.onnx") # or kokoro_batched.onnx, see above
133
 
134
  # ids: Kokoro vocabulary ids for the phoneme string (see upstream / misaki)
135
  ids = np.array([[0, *phoneme_ids, 0]], dtype=np.int64)