echogarden 2.0.14 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/data/lexicons/heteronyms.en.json +47 -5
- package/data/lexicons/words.en.json +184 -0
- package/data/schemas/options.json +64 -0
- package/dist/api/Synthesis.d.ts +10 -1
- package/dist/api/Synthesis.js +76 -9
- package/dist/api/Synthesis.js.map +1 -1
- package/dist/nlp/IPA.d.ts +3 -3
- package/dist/nlp/Lexicon.js +2 -0
- package/dist/nlp/Lexicon.js.map +1 -1
- package/dist/recognition/WhisperSTT.js +1 -1
- package/dist/recognition/WhisperSTT.js.map +1 -1
- package/dist/synthesis/GnuSpeechTTS.d.ts +12 -0
- package/dist/synthesis/GnuSpeechTTS.js +36 -0
- package/dist/synthesis/GnuSpeechTTS.js.map +1 -0
- package/dist/synthesis/KokoroTTS.d.ts +22 -0
- package/dist/synthesis/KokoroTTS.js +595 -0
- package/dist/synthesis/KokoroTTS.js.map +1 -0
- package/dist/synthesis/OpenAICloudTTS.js +15 -0
- package/dist/synthesis/OpenAICloudTTS.js.map +1 -1
- package/dist/synthesis/VitsTTS.js +6 -1
- package/dist/synthesis/VitsTTS.js.map +1 -1
- package/dist/utilities/FileReader.js +1 -1
- package/dist/utilities/PackageManager.js +4 -0
- package/dist/utilities/PackageManager.js.map +1 -1
- package/dist/utilities/Utilities.d.ts +1 -0
- package/dist/utilities/Utilities.js +8 -0
- package/dist/utilities/Utilities.js.map +1 -1
- package/dist/utilities/WasmMemoryManager.d.ts +1 -1
- package/docs/Development.md +1 -1
- package/docs/Engines.md +4 -1
- package/docs/Licenses.md +3 -1
- package/docs/Options.md +9 -5
- package/docs/Tasklist.md +1 -1
- package/package.json +13 -12
- package/src/api/Synthesis.ts +132 -10
- package/src/nlp/Lexicon.ts +3 -0
- package/src/recognition/WhisperSTT.ts +1 -1
- package/src/synthesis/GnuSpeechTTS.ts +40 -0
- package/src/synthesis/KokoroTTS.ts +693 -0
- package/src/synthesis/OpenAICloudTTS.ts +15 -0
- package/src/synthesis/VitsTTS.ts +6 -1
- package/src/utilities/FileReader.ts +1 -1
- package/src/utilities/PackageManager.ts +5 -0
- package/src/utilities/Utilities.ts +10 -0
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Echogarden is an easy-to-use speech toolset that includes a variety of speech pr
|
|
|
11
11
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
|
-
* **Text-to-speech** using
|
|
14
|
+
* **Text-to-speech** using high-quality [Kokoro](https://github.com/hexgrad/kokoro) and [VITS](https://github.com/jaywalnut310/vits) offline voices, for many languages and dialects, and [16 other offline and online engines](docs/Engines.md), including cloud services by [Google](https://cloud.google.com/text-to-speech), [Microsoft](https://azure.microsoft.com/en-us/products/ai-services/text-to-speech/), [Amazon](https://aws.amazon.com/polly/), [OpenAI](https://platform.openai.com/) and [Elevenlabs](https://elevenlabs.io/)
|
|
15
15
|
* **Speech-to-text** using a custom TypeScript/ONNX port of the [OpenAI Whisper](https://openai.com/research/whisper) speech recognition architecture, [whisper.cpp](https://github.com/ggerganov/whisper.cpp), and [several other engines](docs/Engines.md), including cloud services by [Google](https://cloud.google.com/speech-to-text), [Microsoft](https://azure.microsoft.com/en-us/products/ai-services/speech-to-text/), [Amazon](https://aws.amazon.com/transcribe/) and [OpenAI](https://platform.openai.com/)
|
|
16
16
|
* **Speech-to-transcript alignment** using several variants of [dynamic time warping](https://en.wikipedia.org/wiki/Dynamic_time_warping) (DTW, DTW-RA), including support for multi-pass (hierarchical) processing, or via guided decoding using Whisper recognition models. Supports 100+ languages
|
|
17
17
|
* **Speech-to-text translation**, translates speech in any of the [98 languages](https://platform.openai.com/docs/guides/speech-to-text/supported-languages) supported by Whisper, to English, with near word-level timing for the translated transcript
|
|
@@ -167,6 +167,48 @@
|
|
|
167
167
|
"example": "There's no use."
|
|
168
168
|
}
|
|
169
169
|
],
|
|
170
|
+
"close": [
|
|
171
|
+
{
|
|
172
|
+
"pronunciation": {
|
|
173
|
+
"espeak": {
|
|
174
|
+
"en-us": "k l ˈoʊ z",
|
|
175
|
+
"en-gb-x-rp": "k l ˈoʊ z"
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
"pos": [
|
|
180
|
+
"VB"
|
|
181
|
+
],
|
|
182
|
+
|
|
183
|
+
"precededBy": [
|
|
184
|
+
"to", "we", "you", "they", "who", "i", "me", "will", "also", "don't", "didn't", "not", "doesn't", "please", "we'll", "would", "wouldn't", "should", "shouldn't", "must", "mustn't", "shall", "can", "can't", "may", "might", "can", "could", "couldn't"
|
|
185
|
+
],
|
|
186
|
+
|
|
187
|
+
"notPrecededBy": [
|
|
188
|
+
"the", "a", "be", "for", "no", "in", "of", "make", "its", "single", "their", "good", "making", "her", "his", "its", "our", "your", "my", "any", "personal"
|
|
189
|
+
],
|
|
190
|
+
|
|
191
|
+
"succeededBy": [
|
|
192
|
+
"the", "a", "an", "their", "it", "this", "them", "his", "her", "our", "your", "its", "these", "all", "my", "any", "those", "some", "one", "more", "every", "up", "down", "other"
|
|
193
|
+
],
|
|
194
|
+
|
|
195
|
+
"notSucceededBy": [
|
|
196
|
+
"to", "with"
|
|
197
|
+
],
|
|
198
|
+
|
|
199
|
+
"example": "I will close the door."
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"pronunciation": {
|
|
203
|
+
"espeak": {
|
|
204
|
+
"en-us": "k l ˈoʊ s",
|
|
205
|
+
"en-gb-x-rp": "k l ˈoʊ s"
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
"example": "This seems very close."
|
|
210
|
+
}
|
|
211
|
+
],
|
|
170
212
|
"live": [
|
|
171
213
|
{
|
|
172
214
|
"pronunciation": {
|
|
@@ -226,7 +268,7 @@
|
|
|
226
268
|
],
|
|
227
269
|
|
|
228
270
|
"notPrecededBy": [
|
|
229
|
-
"the", "to", "their", "our", "these", "those", "some", "saved", "matter", "few", "some", "many", "innocent"
|
|
271
|
+
"the", "to", "their", "our", "these", "those", "some", "saved", "matter", "few", "some", "many", "innocent", "improve", "better"
|
|
230
272
|
],
|
|
231
273
|
|
|
232
274
|
"succeededBy": [
|
|
@@ -854,7 +896,7 @@
|
|
|
854
896
|
],
|
|
855
897
|
|
|
856
898
|
"succeededBy": [
|
|
857
|
-
"down", "up", "through", "the", "it", "each", "a", "an", "you", "me", "us", "them", "your", "their", "his", "her", "herself", "himself", "itself", "everybody", "our"
|
|
899
|
+
"down", "up", "out", "through", "the", "it", "each", "a", "an", "you", "me", "us", "them", "your", "their", "his", "her", "herself", "himself", "itself", "everybody", "our"
|
|
858
900
|
],
|
|
859
901
|
|
|
860
902
|
"notSucceededBy": [
|
|
@@ -1300,11 +1342,11 @@
|
|
|
1300
1342
|
],
|
|
1301
1343
|
|
|
1302
1344
|
"precededBy": [
|
|
1303
|
-
"to", "i", "me", "us", "they", "we", "you", "will", "would", "can", "can't", "may", "might", "would", "wouldn't", "won't", "don't", "doesn't", "should", "shouldn't", "could", "couldn't", "must", "mustn't", "shall", "did", "didn't", "then"
|
|
1345
|
+
"to", "i", "me", "us", "they", "we", "you", "will", "would", "can", "can't", "may", "might", "would", "wouldn't", "won't", "don't", "doesn't", "should", "shouldn't", "could", "couldn't", "must", "mustn't", "shall", "did", "didn't", "then", "people"
|
|
1304
1346
|
],
|
|
1305
1347
|
|
|
1306
1348
|
"notPrecededBy": [
|
|
1307
|
-
"of", "for", "this", "similar", "with", "criminal", "dangerous", "ethical", "unethical", "good", "future", "disorderly"
|
|
1349
|
+
"of", "for", "this", "similar", "with", "criminal", "dangerous", "ethical", "unethical", "good", "future", "disorderly", "his", "her", "our", "my"
|
|
1308
1350
|
],
|
|
1309
1351
|
|
|
1310
1352
|
"succeededBy": [
|
|
@@ -1629,7 +1671,7 @@
|
|
|
1629
1671
|
],
|
|
1630
1672
|
|
|
1631
1673
|
"precededBy": [
|
|
1632
|
-
"
|
|
1674
|
+
"very", "quite"
|
|
1633
1675
|
],
|
|
1634
1676
|
|
|
1635
1677
|
"notPrecededBy": [
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
{
|
|
2
|
+
"en": {
|
|
3
|
+
"vs.": [
|
|
4
|
+
{
|
|
5
|
+
"pronunciation": {
|
|
6
|
+
"espeak": {
|
|
7
|
+
"en-us": "v ˈɜː s ᵻ z",
|
|
8
|
+
"en-gb-x-rp": "v ˈɜː s ɪ z"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"inherently": [
|
|
14
|
+
{
|
|
15
|
+
"pronunciation": {
|
|
16
|
+
"espeak": {
|
|
17
|
+
"en-us": "ɪ n h ˈɛ ɹ ə n t l i",
|
|
18
|
+
"en-gb-x-rp": "ɪ n h ˈɛ ɹ ə n t l i"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"subsection": [
|
|
24
|
+
{
|
|
25
|
+
"pronunciation": {
|
|
26
|
+
"espeak": {
|
|
27
|
+
"en-us": "s ˈʌ b s ɛ k ʃ ə n",
|
|
28
|
+
"en-gb-x-rp": "s ˈʌ b s ɛ k ʃ ə n"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"subsections": [
|
|
34
|
+
{
|
|
35
|
+
"pronunciation": {
|
|
36
|
+
"espeak": {
|
|
37
|
+
"en-us": "s ˈʌ b s ɛ k ʃ ə n z",
|
|
38
|
+
"en-gb-x-rp": "s ˈʌ b s ɛ k ʃ ə n z"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"subvector": [
|
|
44
|
+
{
|
|
45
|
+
"pronunciation": {
|
|
46
|
+
"espeak": {
|
|
47
|
+
"en-us": "s ˈə b v ɛ k t ɚ",
|
|
48
|
+
"en-gb-x-rp": "s ˈə b v ɛ k t ɐ"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"subvectors": [
|
|
54
|
+
{
|
|
55
|
+
"pronunciation": {
|
|
56
|
+
"espeak": {
|
|
57
|
+
"en-us": "s ˈə b v ɛ k t ɚ z",
|
|
58
|
+
"en-gb-x-rp": "s ˈə b v ɛ k t ɐ z"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"recommender": [
|
|
64
|
+
{
|
|
65
|
+
"pronunciation": {
|
|
66
|
+
"espeak": {
|
|
67
|
+
"en-us": "ɹ ˌiː k ə m ˈɛ n d ɚ",
|
|
68
|
+
"en-gb-x-rp": "ɹ ˌiː k ə m ˈɛ n d ɐ"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"representation": [
|
|
74
|
+
{
|
|
75
|
+
"pronunciation": {
|
|
76
|
+
"espeak": {
|
|
77
|
+
"en-us": "ɹ ˌɛ p ɹ ə z ɛ n t ˈeɪ ʃ ə n",
|
|
78
|
+
"en-gb-x-rp": "ɹ ˌɛ p ɹ ᵻ z ɛ n t ˈeɪ ʃ ə n"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"representations": [
|
|
84
|
+
{
|
|
85
|
+
"pronunciation": {
|
|
86
|
+
"espeak": {
|
|
87
|
+
"en-us": "ɹ ˌɛ p ɹ ə z ɛ n t ˈeɪ ʃ ə n z",
|
|
88
|
+
"en-gb-x-rp": "ɹ ˌɛ p ɹ ᵻ z ɛ n t ˈeɪ ʃ ə n z"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"residual": [
|
|
94
|
+
{
|
|
95
|
+
"pronunciation": {
|
|
96
|
+
"espeak": {
|
|
97
|
+
"en-us": "ɹ ə z ˈɪ dʒ uː əl",
|
|
98
|
+
"en-gb-x-rp": "ɹ ᵻ z ˈɪ dʒ ʊ l"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
"residuals": [
|
|
104
|
+
{
|
|
105
|
+
"pronunciation": {
|
|
106
|
+
"espeak": {
|
|
107
|
+
"en-us": "ɹ ə z ˈɪ dʒ uː əl z",
|
|
108
|
+
"en-gb-x-rp": "ɹ ᵻ z ˈɪ dʒ ʊ l z"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
"kokoro": [
|
|
114
|
+
{
|
|
115
|
+
"pronunciation": {
|
|
116
|
+
"espeak": {
|
|
117
|
+
"en-us": "k ˈoʊ k ə ɹ oʊ",
|
|
118
|
+
"en-gb-x-rp": "k ˈəʊ k ə ɹ əʊ"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"query": [
|
|
124
|
+
{
|
|
125
|
+
"pronunciation": {
|
|
126
|
+
"espeak": {
|
|
127
|
+
"en-us": "k w ˈɛ ɹ i",
|
|
128
|
+
"en-gb-x-rp": "k w ˈiə ɹ i"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
"queries": [
|
|
134
|
+
{
|
|
135
|
+
"pronunciation": {
|
|
136
|
+
"espeak": {
|
|
137
|
+
"en-us": "k w ˈɛ ɹ i z",
|
|
138
|
+
"en-gb-x-rp": "k w ˈiə ɹ i z"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
],
|
|
143
|
+
"jupyter": [
|
|
144
|
+
{
|
|
145
|
+
"pronunciation": {
|
|
146
|
+
"espeak": {
|
|
147
|
+
"en-us": "dʒ ˈuː p ɪ ɾ ɚ",
|
|
148
|
+
"en-gb-x-rp": "dʒ ˈuː p ɪ t ɐ"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
"movies": [
|
|
154
|
+
{
|
|
155
|
+
"pronunciation": {
|
|
156
|
+
"espeak": {
|
|
157
|
+
"en-us": "m ˈuː v i z",
|
|
158
|
+
"en-gb-x-rp": "m ˈuː v i z"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
],
|
|
163
|
+
"preprocessing": [
|
|
164
|
+
{
|
|
165
|
+
"pronunciation": {
|
|
166
|
+
"espeak": {
|
|
167
|
+
"en-us": "p ɹ ˈi p ɹ ˌɑː s ɛ s ɪ ŋ",
|
|
168
|
+
"en-gb-x-rp": "p ɹ ˈi p ɹ ˌəʊ s ɛ s ɪ ŋ"
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
"annoy": [
|
|
174
|
+
{
|
|
175
|
+
"pronunciation": {
|
|
176
|
+
"espeak": {
|
|
177
|
+
"en-us": "ə n ˈɔ ɪ",
|
|
178
|
+
"en-gb-x-rp": "ə n ˈɔ ɪ"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -191,6 +191,22 @@
|
|
|
191
191
|
},
|
|
192
192
|
"additionalProperties": false
|
|
193
193
|
},
|
|
194
|
+
"kokoro": {
|
|
195
|
+
"type": "object",
|
|
196
|
+
"properties": {
|
|
197
|
+
"provider": {
|
|
198
|
+
"$ref": "#/definitions/OnnxExecutionProvider"
|
|
199
|
+
},
|
|
200
|
+
"model": {
|
|
201
|
+
"type": "string",
|
|
202
|
+
"enum": [
|
|
203
|
+
"82m-v1.0-fp32",
|
|
204
|
+
"82m-v1.0-quantized"
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"additionalProperties": false
|
|
209
|
+
},
|
|
194
210
|
"pico": {
|
|
195
211
|
"type": "object",
|
|
196
212
|
"additionalProperties": false
|
|
@@ -199,6 +215,21 @@
|
|
|
199
215
|
"type": "object",
|
|
200
216
|
"additionalProperties": false
|
|
201
217
|
},
|
|
218
|
+
"gnuspeech": {
|
|
219
|
+
"type": "object",
|
|
220
|
+
"properties": {
|
|
221
|
+
"tempo": {
|
|
222
|
+
"type": "number"
|
|
223
|
+
},
|
|
224
|
+
"controlRate": {
|
|
225
|
+
"type": "number"
|
|
226
|
+
},
|
|
227
|
+
"debug": {
|
|
228
|
+
"type": "boolean"
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
"additionalProperties": false
|
|
232
|
+
},
|
|
202
233
|
"espeak": {
|
|
203
234
|
"type": "object",
|
|
204
235
|
"properties": {
|
|
@@ -376,8 +407,10 @@
|
|
|
376
407
|
"type": "string",
|
|
377
408
|
"enum": [
|
|
378
409
|
"vits",
|
|
410
|
+
"kokoro",
|
|
379
411
|
"pico",
|
|
380
412
|
"flite",
|
|
413
|
+
"gnuspeech",
|
|
381
414
|
"espeak",
|
|
382
415
|
"sam",
|
|
383
416
|
"sapi",
|
|
@@ -1471,6 +1504,22 @@
|
|
|
1471
1504
|
},
|
|
1472
1505
|
"additionalProperties": false
|
|
1473
1506
|
},
|
|
1507
|
+
"kokoro": {
|
|
1508
|
+
"type": "object",
|
|
1509
|
+
"properties": {
|
|
1510
|
+
"provider": {
|
|
1511
|
+
"$ref": "#/definitions/OnnxExecutionProvider"
|
|
1512
|
+
},
|
|
1513
|
+
"model": {
|
|
1514
|
+
"type": "string",
|
|
1515
|
+
"enum": [
|
|
1516
|
+
"82m-v1.0-fp32",
|
|
1517
|
+
"82m-v1.0-quantized"
|
|
1518
|
+
]
|
|
1519
|
+
}
|
|
1520
|
+
},
|
|
1521
|
+
"additionalProperties": false
|
|
1522
|
+
},
|
|
1474
1523
|
"pico": {
|
|
1475
1524
|
"type": "object",
|
|
1476
1525
|
"additionalProperties": false
|
|
@@ -1479,6 +1528,21 @@
|
|
|
1479
1528
|
"type": "object",
|
|
1480
1529
|
"additionalProperties": false
|
|
1481
1530
|
},
|
|
1531
|
+
"gnuspeech": {
|
|
1532
|
+
"type": "object",
|
|
1533
|
+
"properties": {
|
|
1534
|
+
"tempo": {
|
|
1535
|
+
"type": "number"
|
|
1536
|
+
},
|
|
1537
|
+
"controlRate": {
|
|
1538
|
+
"type": "number"
|
|
1539
|
+
},
|
|
1540
|
+
"debug": {
|
|
1541
|
+
"type": "boolean"
|
|
1542
|
+
}
|
|
1543
|
+
},
|
|
1544
|
+
"additionalProperties": false
|
|
1545
|
+
},
|
|
1482
1546
|
"espeak": {
|
|
1483
1547
|
"type": "object",
|
|
1484
1548
|
"properties": {
|
package/dist/api/Synthesis.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface SynthesisResult {
|
|
|
14
14
|
language: string;
|
|
15
15
|
voice: string;
|
|
16
16
|
}
|
|
17
|
-
export type SynthesisEngine = 'vits' | 'pico' | 'flite' | 'espeak' | 'sam' | 'sapi' | 'msspeech' | 'coqui-server' | 'google-cloud' | 'microsoft-azure' | 'amazon-polly' | 'openai-cloud' | 'elevenlabs' | 'google-translate' | 'microsoft-edge' | 'streamlabs-polly';
|
|
17
|
+
export type SynthesisEngine = 'vits' | 'kokoro' | 'pico' | 'flite' | 'gnuspeech' | 'espeak' | 'sam' | 'sapi' | 'msspeech' | 'coqui-server' | 'google-cloud' | 'microsoft-azure' | 'amazon-polly' | 'openai-cloud' | 'elevenlabs' | 'google-translate' | 'microsoft-edge' | 'streamlabs-polly';
|
|
18
18
|
export type TimePitchShiftingMethod = 'sonic' | 'rubberband';
|
|
19
19
|
export interface SynthesisOptions {
|
|
20
20
|
engine?: SynthesisEngine;
|
|
@@ -50,8 +50,17 @@ export interface SynthesisOptions {
|
|
|
50
50
|
speakerId?: number;
|
|
51
51
|
provider?: OnnxExecutionProvider;
|
|
52
52
|
};
|
|
53
|
+
kokoro?: {
|
|
54
|
+
provider?: OnnxExecutionProvider;
|
|
55
|
+
model?: '82m-v1.0-fp32' | '82m-v1.0-quantized';
|
|
56
|
+
};
|
|
53
57
|
pico?: {};
|
|
54
58
|
flite?: {};
|
|
59
|
+
gnuspeech?: {
|
|
60
|
+
tempo?: number;
|
|
61
|
+
controlRate?: number;
|
|
62
|
+
debug?: boolean;
|
|
63
|
+
};
|
|
55
64
|
espeak?: {
|
|
56
65
|
rate?: number;
|
|
57
66
|
pitch?: number;
|
package/dist/api/Synthesis.js
CHANGED
|
@@ -110,9 +110,9 @@ async function synthesizeSegments(segments, options, onSegment, onSentence) {
|
|
|
110
110
|
const sentenceText = sentences[sentenceIndex].trim();
|
|
111
111
|
logger.log(`\n${chalk.magentaBright(`Synthesizing sentence ${sentenceIndex + 1}/${sentences.length}`)}: "${sentenceText}"`);
|
|
112
112
|
const sentenceStartTime = timeOffset;
|
|
113
|
-
let
|
|
114
|
-
|
|
115
|
-
const { synthesizedAudio: sentenceRawAudio, timeline: sentenceTimeline } = await synthesizeSegment(sentenceText,
|
|
113
|
+
let sentenceSynthesisOptions = { postProcessing: { normalizeAudio: false } };
|
|
114
|
+
sentenceSynthesisOptions = extendDeep(options, sentenceSynthesisOptions);
|
|
115
|
+
const { synthesizedAudio: sentenceRawAudio, timeline: sentenceTimeline } = await synthesizeSegment(sentenceText, sentenceSynthesisOptions);
|
|
116
116
|
const endPause = sentenceIndex == sentences.length - 1 ? options.segmentEndPause : options.sentenceEndPause;
|
|
117
117
|
sentenceRawAudio.audioChannels[0] = trimAudioEnd(sentenceRawAudio.audioChannels[0], endPause * sentenceRawAudio.sampleRate);
|
|
118
118
|
sentencesRawAudio.push(sentenceRawAudio);
|
|
@@ -284,6 +284,27 @@ async function synthesizeSegment(text, options) {
|
|
|
284
284
|
logger.end();
|
|
285
285
|
break;
|
|
286
286
|
}
|
|
287
|
+
case 'kokoro': {
|
|
288
|
+
if (inputIsSSML) {
|
|
289
|
+
throw new Error(`The Kokoro engine doesn't currently support SSML inputs`);
|
|
290
|
+
}
|
|
291
|
+
const kokoroOptions = options.kokoro;
|
|
292
|
+
const kokoroTTS = await import('../synthesis/KokoroTTS.js');
|
|
293
|
+
const lexicons = await loadLexiconsForLanguage(language, options.customLexiconPaths);
|
|
294
|
+
const onnxExecutionProviders = kokoroOptions.provider ? [kokoroOptions.provider] : [];
|
|
295
|
+
const modelName = kokoroOptions.model;
|
|
296
|
+
const modelPackageName = `kokoro-${modelName}`;
|
|
297
|
+
const modelPath = await loadPackage(modelPackageName);
|
|
298
|
+
const voicesPath = await loadPackage('kokoro-82m-v1.0-voices');
|
|
299
|
+
logger.end();
|
|
300
|
+
logger.logTitledMessage(`Using model`, modelPackageName);
|
|
301
|
+
const { rawAudio, timeline: outTimeline } = await kokoroTTS.synthesizeSentence(text, selectedVoice, speed, lexicons, modelPath, voicesPath, onnxExecutionProviders);
|
|
302
|
+
synthesizedAudio = rawAudio;
|
|
303
|
+
timeline = outTimeline;
|
|
304
|
+
shouldPostprocessPitch = true;
|
|
305
|
+
logger.end();
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
287
308
|
case 'pico': {
|
|
288
309
|
if (inputIsSSML) {
|
|
289
310
|
throw new Error(`The SVOX Pico engine doesn't currently support SSML inputs`);
|
|
@@ -312,6 +333,24 @@ async function synthesizeSegment(text, options) {
|
|
|
312
333
|
shouldPostprocessPitch = true;
|
|
313
334
|
break;
|
|
314
335
|
}
|
|
336
|
+
case 'gnuspeech': {
|
|
337
|
+
if (inputIsSSML) {
|
|
338
|
+
throw new Error(`The Gnuspeech engine doesn't currently support SSML inputs`);
|
|
339
|
+
}
|
|
340
|
+
const engineOptions = options.gnuspeech;
|
|
341
|
+
const GnuSpeech = await import('../synthesis/GnuSpeechTTS.js');
|
|
342
|
+
const { defaultGnuSpeechOptions } = await import('@echogarden/gnuspeech-wasm');
|
|
343
|
+
const gnuSpeechOptions = extendDeep(defaultGnuSpeechOptions, engineOptions);
|
|
344
|
+
if (!engineOptions.tempo) {
|
|
345
|
+
gnuSpeechOptions.tempo = speed;
|
|
346
|
+
}
|
|
347
|
+
await logger.startAsync(`Synthesize with Gnuspeech`);
|
|
348
|
+
const { rawAudio } = await GnuSpeech.synthesize(simplifiedText, gnuSpeechOptions);
|
|
349
|
+
synthesizedAudio = rawAudio;
|
|
350
|
+
shouldPostprocessPitch = true;
|
|
351
|
+
logger.end();
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
315
354
|
case 'espeak': {
|
|
316
355
|
const EspeakTTS = await import('../synthesis/EspeakTTS.js');
|
|
317
356
|
const engineOptions = options.espeak;
|
|
@@ -652,7 +691,7 @@ async function synthesizeSegment(text, options) {
|
|
|
652
691
|
timeline = timeline.filter(entry => isWordOrSymbolWord(entry.text));
|
|
653
692
|
}
|
|
654
693
|
logger.end();
|
|
655
|
-
logger.logDuration('
|
|
694
|
+
logger.logDuration('Part synthesis time', startTimestamp, chalk.magentaBright);
|
|
656
695
|
return { synthesizedAudio, timeline };
|
|
657
696
|
}
|
|
658
697
|
function convertSpeedScaleToSSMLValueString(rate) {
|
|
@@ -728,13 +767,19 @@ export const defaultSynthesisOptions = {
|
|
|
728
767
|
speakerId: undefined,
|
|
729
768
|
provider: undefined,
|
|
730
769
|
},
|
|
770
|
+
kokoro: {
|
|
771
|
+
model: '82m-v1.0-fp32'
|
|
772
|
+
},
|
|
731
773
|
pico: {},
|
|
732
774
|
flite: {},
|
|
775
|
+
gnuspeech: {
|
|
776
|
+
debug: false,
|
|
777
|
+
},
|
|
733
778
|
espeak: {
|
|
734
779
|
rate: undefined,
|
|
735
780
|
pitch: undefined,
|
|
736
781
|
pitchRange: undefined,
|
|
737
|
-
useKlatt: false
|
|
782
|
+
useKlatt: false,
|
|
738
783
|
},
|
|
739
784
|
sam: {
|
|
740
785
|
speed: undefined,
|
|
@@ -826,6 +871,11 @@ export async function requestVoiceList(options) {
|
|
|
826
871
|
voiceList = SvoxPicoTTS.voiceList;
|
|
827
872
|
break;
|
|
828
873
|
}
|
|
874
|
+
case 'gnuspeech': {
|
|
875
|
+
const GnuSpeech = await import('../synthesis/GnuSpeechTTS.js');
|
|
876
|
+
voiceList = GnuSpeech.voiceList;
|
|
877
|
+
break;
|
|
878
|
+
}
|
|
829
879
|
case 'sam': {
|
|
830
880
|
voiceList.push({
|
|
831
881
|
name: 'sam',
|
|
@@ -841,6 +891,11 @@ export async function requestVoiceList(options) {
|
|
|
841
891
|
});
|
|
842
892
|
break;
|
|
843
893
|
}
|
|
894
|
+
case 'kokoro': {
|
|
895
|
+
const KokoroTTS = await import('../synthesis/KokoroTTS.js');
|
|
896
|
+
voiceList = KokoroTTS.voiceList;
|
|
897
|
+
break;
|
|
898
|
+
}
|
|
844
899
|
case 'sapi': {
|
|
845
900
|
const SapiTTS = await import('../synthesis/SapiTTS.js');
|
|
846
901
|
await SapiTTS.AssertSAPIAvailable(false);
|
|
@@ -1066,28 +1121,40 @@ export const synthesisEngines = [
|
|
|
1066
1121
|
description: 'A high-quality end-to-end neural speech synthesis architecture.',
|
|
1067
1122
|
type: 'local'
|
|
1068
1123
|
},
|
|
1124
|
+
{
|
|
1125
|
+
id: 'kokoro',
|
|
1126
|
+
name: 'Kokoro',
|
|
1127
|
+
description: 'A high-quality neural speech synthesis model based on the StyleTTS 2 architecture.',
|
|
1128
|
+
type: 'local'
|
|
1129
|
+
},
|
|
1069
1130
|
{
|
|
1070
1131
|
id: 'pico',
|
|
1071
1132
|
name: 'SVOX Pico',
|
|
1072
|
-
description: 'A legacy diphone-based
|
|
1133
|
+
description: 'A legacy diphone-based speech synthesizer.',
|
|
1073
1134
|
type: 'local'
|
|
1074
1135
|
},
|
|
1075
1136
|
{
|
|
1076
1137
|
id: 'flite',
|
|
1077
1138
|
name: 'Flite',
|
|
1078
|
-
description: 'A legacy diphone-based
|
|
1139
|
+
description: 'A legacy diphone-based speech synthesizer.',
|
|
1140
|
+
type: 'local'
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
id: 'gnuspeech',
|
|
1144
|
+
name: 'Gnuspeech',
|
|
1145
|
+
description: 'A legacy articulatory speech synthesizer.',
|
|
1079
1146
|
type: 'local'
|
|
1080
1147
|
},
|
|
1081
1148
|
{
|
|
1082
1149
|
id: 'espeak',
|
|
1083
1150
|
name: 'eSpeak NG',
|
|
1084
|
-
description: `A lightweight 'robot'
|
|
1151
|
+
description: `A lightweight, highly multilingual, 'robot'-like formant-based speech synthesizer.`,
|
|
1085
1152
|
type: 'local'
|
|
1086
1153
|
},
|
|
1087
1154
|
{
|
|
1088
1155
|
id: 'sam',
|
|
1089
1156
|
name: 'SAM (Software Automatic Mouth)',
|
|
1090
|
-
description: `A classic 'robot' speech synthesizer from 1982.`,
|
|
1157
|
+
description: `A classic 'robot'-like speech synthesizer from 1982.`,
|
|
1091
1158
|
type: 'local'
|
|
1092
1159
|
},
|
|
1093
1160
|
{
|