@mastra/voice-speechify 0.14.0 → 0.14.1-alpha.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/dist/index.js CHANGED
@@ -1,1071 +1,1172 @@
1
- import { Readable } from 'stream';
2
- import { Speechify } from '@speechify/api-sdk';
3
-
4
- // src/index.ts
5
-
6
- // ../../packages/_internal-core/dist/chunk-3M4SEWMI.js
7
- var RegisteredLogger = {
8
- LLM: "LLM"};
9
- var LogLevel = {
10
- DEBUG: "debug",
11
- INFO: "info",
12
- WARN: "warn",
13
- ERROR: "error"};
1
+ import { Readable } from "stream";
2
+ import { Speechify } from "@speechify/api-sdk";
3
+ //#region ../../packages/_internal-core/dist/logger/index.js
4
+ /**
5
+ * Export a tracked exception through the adapter sink, mirroring the
6
+ * DualLogger dual-write shape (`errorId`/`domain`/`category`/`details`/`cause`
7
+ * when present on a MastraError-like value). Never throws into the caller.
8
+ */
9
+ function exportTrackedException(ctx, error, metadata) {
10
+ if (!ctx?.options.export) return;
11
+ try {
12
+ const mastraError = error;
13
+ ctx.getLogSink()?.error(error.message, {
14
+ ...mastraError.id !== void 0 ? { errorId: mastraError.id } : {},
15
+ ...mastraError.domain !== void 0 ? { domain: mastraError.domain } : {},
16
+ ...mastraError.category !== void 0 ? { category: mastraError.category } : {},
17
+ ...mastraError.details !== void 0 ? { details: mastraError.details } : {},
18
+ ...error.cause instanceof Error ? { cause: error.cause.message } : {},
19
+ ...metadata
20
+ });
21
+ } catch {}
22
+ }
23
+ /**
24
+ * Adapt IMastraLogger's variadic args into the structured `data` payload of
25
+ * an exported log record. Extracts the first plain object as data,
26
+ * serializes an Error arg, and collects remaining primitives under `args`
27
+ * so the derived record preserves all context from the native call.
28
+ */
29
+ function buildLogRecordData(args) {
30
+ const objectData = args.find((arg) => arg !== null && typeof arg === "object" && !Array.isArray(arg) && !(arg instanceof Error));
31
+ const errorArg = args.find((arg) => arg instanceof Error);
32
+ const extraArgs = args.filter((arg) => arg !== objectData && arg !== errorArg);
33
+ if (!objectData && !errorArg && extraArgs.length === 0) return void 0;
34
+ return {
35
+ ...objectData ?? {},
36
+ ...errorArg ? { error: {
37
+ name: errorArg.name,
38
+ message: errorArg.message,
39
+ stack: errorArg.stack
40
+ } } : {},
41
+ ...extraArgs.length > 0 ? { args: extraArgs } : {}
42
+ };
43
+ }
44
+ const RegisteredLogger = {
45
+ AGENT: "AGENT",
46
+ OBSERVABILITY: "OBSERVABILITY",
47
+ AUTH: "AUTH",
48
+ BROWSER: "BROWSER",
49
+ NETWORK: "NETWORK",
50
+ WORKFLOW: "WORKFLOW",
51
+ LLM: "LLM",
52
+ TTS: "TTS",
53
+ VOICE: "VOICE",
54
+ VECTOR: "VECTOR",
55
+ BUNDLER: "BUNDLER",
56
+ DEPLOYER: "DEPLOYER",
57
+ MEMORY: "MEMORY",
58
+ STORAGE: "STORAGE",
59
+ EMBEDDINGS: "EMBEDDINGS",
60
+ MCP_SERVER: "MCP_SERVER",
61
+ SERVER_CACHE: "SERVER_CACHE",
62
+ SERVER: "SERVER",
63
+ WORKSPACE: "WORKSPACE",
64
+ CHANNEL: "CHANNEL"
65
+ };
66
+ const LogLevel = {
67
+ DEBUG: "debug",
68
+ INFO: "info",
69
+ WARN: "warn",
70
+ ERROR: "error",
71
+ NONE: "silent"
72
+ };
14
73
  var MastraLogger = class {
15
- name;
16
- level;
17
- transports;
18
- constructor(options = {}) {
19
- this.name = options.name || "Mastra";
20
- this.level = options.level || LogLevel.ERROR;
21
- this.transports = new Map(Object.entries(options.transports || {}));
22
- }
23
- getTransports() {
24
- return this.transports;
25
- }
26
- trackException(_error, _metadata) {
27
- }
28
- async listLogs(transportId, params) {
29
- if (!transportId || !this.transports.has(transportId)) {
30
- return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false };
31
- }
32
- return this.transports.get(transportId).listLogs?.(params) ?? {
33
- logs: [],
34
- total: 0,
35
- page: params?.page ?? 1,
36
- perPage: params?.perPage ?? 100,
37
- hasMore: false
38
- };
39
- }
40
- async listLogsByRunId({
41
- transportId,
42
- runId,
43
- fromDate,
44
- toDate,
45
- logLevel,
46
- filters,
47
- page,
48
- perPage
49
- }) {
50
- if (!transportId || !this.transports.has(transportId) || !runId) {
51
- return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false };
52
- }
53
- return this.transports.get(transportId).listLogsByRunId?.({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
54
- logs: [],
55
- total: 0,
56
- page: page ?? 1,
57
- perPage: perPage ?? 100,
58
- hasMore: false
59
- };
60
- }
74
+ name;
75
+ level;
76
+ transports;
77
+ constructor(options = {}) {
78
+ this.name = options.name || "Mastra";
79
+ this.level = options.level || LogLevel.ERROR;
80
+ this.transports = new Map(Object.entries(options.transports || {}));
81
+ }
82
+ getTransports() {
83
+ return this.transports;
84
+ }
85
+ trackException(_error, _metadata) {}
86
+ async listLogs(transportId, params) {
87
+ if (!transportId || !this.transports.has(transportId)) return {
88
+ logs: [],
89
+ total: 0,
90
+ page: params?.page ?? 1,
91
+ perPage: params?.perPage ?? 100,
92
+ hasMore: false
93
+ };
94
+ return this.transports.get(transportId).listLogs?.(params) ?? {
95
+ logs: [],
96
+ total: 0,
97
+ page: params?.page ?? 1,
98
+ perPage: params?.perPage ?? 100,
99
+ hasMore: false
100
+ };
101
+ }
102
+ async listLogsByRunId({ transportId, runId, fromDate, toDate, logLevel, filters, page, perPage }) {
103
+ if (!transportId || !this.transports.has(transportId) || !runId) return {
104
+ logs: [],
105
+ total: 0,
106
+ page: page ?? 1,
107
+ perPage: perPage ?? 100,
108
+ hasMore: false
109
+ };
110
+ return this.transports.get(transportId).listLogsByRunId?.({
111
+ runId,
112
+ fromDate,
113
+ toDate,
114
+ logLevel,
115
+ filters,
116
+ page,
117
+ perPage
118
+ }) ?? {
119
+ logs: [],
120
+ total: 0,
121
+ page: page ?? 1,
122
+ perPage: perPage ?? 100,
123
+ hasMore: false
124
+ };
125
+ }
61
126
  };
62
- var ConsoleLogger = class _ConsoleLogger extends MastraLogger {
63
- component;
64
- filter;
65
- constructor(options = {}) {
66
- super(options);
67
- this.component = options.component;
68
- this.filter = options.filter;
69
- }
70
- child(componentOrBindings) {
71
- const component = typeof componentOrBindings === "string" ? componentOrBindings : componentOrBindings?.component ?? this.component;
72
- return new _ConsoleLogger({
73
- name: this.name,
74
- level: this.level,
75
- component,
76
- filter: this.filter
77
- });
78
- }
79
- shouldLog(level, message, args) {
80
- if (!this.filter) return true;
81
- try {
82
- return this.filter({ component: this.component, level, message, args });
83
- } catch (e) {
84
- console.error(`[Logger] Filter error for component=${this.component} level=${level}:`, e);
85
- return true;
86
- }
87
- }
88
- prefix() {
89
- return this.component ? `[${this.component}] ` : "";
90
- }
91
- debug(message, ...args) {
92
- if (this.level === LogLevel.DEBUG && this.shouldLog(LogLevel.DEBUG, message, args)) {
93
- console.info(`${this.prefix()}${message}`, ...args);
94
- }
95
- }
96
- info(message, ...args) {
97
- if ((this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.INFO, message, args)) {
98
- console.info(`${this.prefix()}${message}`, ...args);
99
- }
100
- }
101
- warn(message, ...args) {
102
- if ((this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.WARN, message, args)) {
103
- console.warn(`${this.prefix()}${message}`, ...args);
104
- }
105
- }
106
- error(message, ...args) {
107
- if ((this.level === LogLevel.ERROR || this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.ERROR, message, args)) {
108
- console.error(`${this.prefix()}${message}`, ...args);
109
- }
110
- }
111
- async listLogs(_transportId, _params) {
112
- return { logs: [], total: 0, page: _params?.page ?? 1, perPage: _params?.perPage ?? 100, hasMore: false };
113
- }
114
- async listLogsByRunId(_args) {
115
- return { logs: [], total: 0, page: _args.page ?? 1, perPage: _args.perPage ?? 100, hasMore: false };
116
- }
127
+ var ConsoleLogger = class ConsoleLogger extends MastraLogger {
128
+ component;
129
+ filter;
130
+ #adapterContext;
131
+ constructor(options = {}) {
132
+ super(options);
133
+ this.component = options.component;
134
+ this.filter = options.filter;
135
+ }
136
+ /**
137
+ * Adapter hook (see `AdaptableLogger`): enables native trace correlation
138
+ * (trace_id/span_id appended to console output) and observability export
139
+ * derived from the same record. Called by Mastra during setup.
140
+ */
141
+ __attachObservability(ctx) {
142
+ this.#adapterContext = ctx;
143
+ }
144
+ child(componentOrBindings) {
145
+ const component = typeof componentOrBindings === "string" ? componentOrBindings : componentOrBindings?.component ?? this.component;
146
+ const child = new ConsoleLogger({
147
+ name: this.name,
148
+ level: this.level,
149
+ component,
150
+ filter: this.filter
151
+ });
152
+ if (this.#adapterContext) child.__attachObservability(this.#adapterContext);
153
+ return child;
154
+ }
155
+ /**
156
+ * Native-record correlation: when a span is active, append the trace
157
+ * fields object to the console args so every destination sees them.
158
+ */
159
+ #correlate(args) {
160
+ const ctx = this.#adapterContext;
161
+ if (!ctx?.options.correlation) return args;
162
+ try {
163
+ const fields = ctx.resolveTraceFields();
164
+ return fields ? [...args, fields] : args;
165
+ } catch {
166
+ return args;
167
+ }
168
+ }
169
+ /**
170
+ * Export the record derived from the same native call to observability.
171
+ * Mirrors DualLogger semantics: export is independent of the console
172
+ * level filter, and never throws into the caller.
173
+ */
174
+ #export(level, message, args) {
175
+ const ctx = this.#adapterContext;
176
+ if (!ctx?.options.export) return;
177
+ try {
178
+ ctx.getLogSink()?.[level](message, buildLogRecordData(args));
179
+ } catch {}
180
+ }
181
+ shouldLog(level, message, args) {
182
+ if (!this.filter) return true;
183
+ try {
184
+ return this.filter({
185
+ component: this.component,
186
+ level,
187
+ message,
188
+ args
189
+ });
190
+ } catch (e) {
191
+ console.error(`[Logger] Filter error for component=${this.component} level=${level}:`, e);
192
+ return true;
193
+ }
194
+ }
195
+ prefix() {
196
+ return this.component ? `[${this.component}] ` : "";
197
+ }
198
+ debug(message, ...args) {
199
+ if (this.level === LogLevel.DEBUG && this.shouldLog(LogLevel.DEBUG, message, args)) console.info(`${this.prefix()}${message}`, ...this.#correlate(args));
200
+ this.#export("debug", message, args);
201
+ }
202
+ info(message, ...args) {
203
+ if ((this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.INFO, message, args)) console.info(`${this.prefix()}${message}`, ...this.#correlate(args));
204
+ this.#export("info", message, args);
205
+ }
206
+ warn(message, ...args) {
207
+ if ((this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.WARN, message, args)) console.warn(`${this.prefix()}${message}`, ...this.#correlate(args));
208
+ this.#export("warn", message, args);
209
+ }
210
+ error(message, ...args) {
211
+ if ((this.level === LogLevel.ERROR || this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) && this.shouldLog(LogLevel.ERROR, message, args)) console.error(`${this.prefix()}${message}`, ...this.#correlate(args));
212
+ this.#export("error", message, args);
213
+ }
214
+ trackException(error, metadata) {
215
+ exportTrackedException(this.#adapterContext, error, metadata);
216
+ }
217
+ async listLogs(_transportId, _params) {
218
+ return {
219
+ logs: [],
220
+ total: 0,
221
+ page: _params?.page ?? 1,
222
+ perPage: _params?.perPage ?? 100,
223
+ hasMore: false
224
+ };
225
+ }
226
+ async listLogsByRunId(_args) {
227
+ return {
228
+ logs: [],
229
+ total: 0,
230
+ page: _args.page ?? 1,
231
+ perPage: _args.perPage ?? 100,
232
+ hasMore: false
233
+ };
234
+ }
117
235
  };
118
-
119
- // ../../packages/_internal-core/dist/base/index.js
236
+ //#endregion
237
+ //#region ../../packages/_internal-core/dist/base/index.js
120
238
  var MastraBase = class {
121
- component = RegisteredLogger.LLM;
122
- logger;
123
- name;
124
- #rawConfig;
125
- constructor({
126
- component,
127
- name,
128
- rawConfig
129
- }) {
130
- this.component = component || RegisteredLogger.LLM;
131
- this.name = name;
132
- this.#rawConfig = rawConfig;
133
- this.logger = new ConsoleLogger({ name: `${this.component} - ${this.name}` });
134
- }
135
- /**
136
- * Returns the raw storage configuration this primitive was created from,
137
- * or undefined if it was created from code.
138
- */
139
- toRawConfig() {
140
- return this.#rawConfig;
141
- }
142
- /**
143
- * Sets the raw storage configuration for this primitive.
144
- * @internal
145
- */
146
- __setRawConfig(rawConfig) {
147
- this.#rawConfig = rawConfig;
148
- }
149
- /**
150
- * Set the logger for the agent
151
- * @param logger
152
- */
153
- __setLogger(logger) {
154
- this.logger = "child" in logger && typeof logger.child === "function" ? logger.child({ component: this.component }) : logger;
155
- }
239
+ component = RegisteredLogger.LLM;
240
+ logger;
241
+ name;
242
+ #rawConfig;
243
+ constructor({ component, name, rawConfig }) {
244
+ this.component = component || RegisteredLogger.LLM;
245
+ this.name = name;
246
+ this.#rawConfig = rawConfig;
247
+ this.logger = new ConsoleLogger({ name: `${this.component} - ${this.name}` });
248
+ }
249
+ /**
250
+ * Returns the raw storage configuration this primitive was created from,
251
+ * or undefined if it was created from code.
252
+ */
253
+ toRawConfig() {
254
+ return this.#rawConfig;
255
+ }
256
+ /**
257
+ * Sets the raw storage configuration for this primitive.
258
+ * @internal
259
+ */
260
+ __setRawConfig(rawConfig) {
261
+ this.#rawConfig = rawConfig;
262
+ }
263
+ /**
264
+ * Set the logger for the agent
265
+ * @param logger
266
+ */
267
+ __setLogger(logger) {
268
+ this.logger = "child" in logger && typeof logger.child === "function" ? logger.child({ component: this.component }) : logger;
269
+ }
156
270
  };
157
-
158
- // ../../packages/_internals/voice/dist/chunk-NWNKSBZV.js
271
+ //#endregion
272
+ //#region ../../packages/_internals/voice/dist/aisdk-C_K-VCwq.js
159
273
  var MastraVoice = class extends MastraBase {
160
- listeningModel;
161
- speechModel;
162
- speaker;
163
- realtimeConfig;
164
- constructor({ listeningModel, speechModel, speaker, realtimeConfig, name } = {}) {
165
- super({
166
- component: "VOICE",
167
- name
168
- });
169
- this.listeningModel = listeningModel;
170
- this.speechModel = speechModel;
171
- this.speaker = speaker;
172
- this.realtimeConfig = realtimeConfig;
173
- }
174
- /**
175
- * Custom serialization for tracing/observability spans.
176
- * Excludes `apiKey` from listeningModel / speechModel / realtimeConfig
177
- * and any provider-specific state held by subclasses. Subclasses that
178
- * need to expose additional non-sensitive fields can override.
179
- */
180
- serializeForSpan() {
181
- return {
182
- component: "VOICE",
183
- name: this.name,
184
- speaker: this.speaker,
185
- listeningModel: this.listeningModel ? { name: this.listeningModel.name } : void 0,
186
- speechModel: this.speechModel ? { name: this.speechModel.name } : void 0,
187
- realtimeModel: this.realtimeConfig?.model
188
- };
189
- }
190
- updateConfig(_options) {
191
- this.logger.debug("updateConfig not implemented by this voice provider");
192
- }
193
- /**
194
- * Initializes a WebSocket or WebRTC connection for real-time communication
195
- * @returns Promise that resolves when the connection is established
196
- */
197
- async connect(_options) {
198
- this.logger.debug("connect not implemented by this voice provider");
199
- }
200
- /**
201
- * Relay audio data to the voice provider for real-time processing
202
- * @param audioData Audio data to relay
203
- */
204
- async send(_audioData) {
205
- this.logger.debug("relay not implemented by this voice provider");
206
- }
207
- /**
208
- * Trigger voice providers to respond
209
- */
210
- async answer(_options) {
211
- this.logger.debug("answer not implemented by this voice provider");
212
- }
213
- /**
214
- * Equip the voice provider with instructions
215
- * @param instructions Instructions to add
216
- */
217
- addInstructions(_instructions) {
218
- }
219
- /**
220
- * Equip the voice provider with tools
221
- * @param tools Array of tools to add
222
- */
223
- addTools(_tools) {
224
- }
225
- /**
226
- * Disconnect from the WebSocket or WebRTC connection
227
- */
228
- close() {
229
- this.logger.debug("close not implemented by this voice provider");
230
- }
231
- /**
232
- * Register an event listener
233
- * @param event Event name (e.g., 'speaking', 'writing', 'error')
234
- * @param callback Callback function that receives event data
235
- */
236
- on(_event, _callback) {
237
- this.logger.debug("on not implemented by this voice provider");
238
- }
239
- /**
240
- * Remove an event listener
241
- * @param event Event name (e.g., 'speaking', 'writing', 'error')
242
- * @param callback Callback function to remove
243
- */
244
- off(_event, _callback) {
245
- this.logger.debug("off not implemented by this voice provider");
246
- }
247
- /**
248
- * Get available speakers/voices
249
- * @returns Array of available voice IDs and their metadata
250
- */
251
- getSpeakers() {
252
- this.logger.debug("getSpeakers not implemented by this voice provider");
253
- return Promise.resolve([]);
254
- }
255
- /**
256
- * Get available speakers/voices
257
- * @returns Array of available voice IDs and their metadata
258
- */
259
- getListener() {
260
- this.logger.debug("getListener not implemented by this voice provider");
261
- return Promise.resolve({ enabled: false });
262
- }
274
+ listeningModel;
275
+ speechModel;
276
+ speaker;
277
+ realtimeConfig;
278
+ constructor({ listeningModel, speechModel, speaker, realtimeConfig, name } = {}) {
279
+ super({
280
+ component: "VOICE",
281
+ name
282
+ });
283
+ this.listeningModel = listeningModel;
284
+ this.speechModel = speechModel;
285
+ this.speaker = speaker;
286
+ this.realtimeConfig = realtimeConfig;
287
+ }
288
+ /**
289
+ * Custom serialization for tracing/observability spans.
290
+ * Excludes `apiKey` from listeningModel / speechModel / realtimeConfig
291
+ * and any provider-specific state held by subclasses. Subclasses that
292
+ * need to expose additional non-sensitive fields can override.
293
+ */
294
+ serializeForSpan() {
295
+ return {
296
+ component: "VOICE",
297
+ name: this.name,
298
+ speaker: this.speaker,
299
+ listeningModel: this.listeningModel ? { name: this.listeningModel.name } : void 0,
300
+ speechModel: this.speechModel ? { name: this.speechModel.name } : void 0,
301
+ realtimeModel: this.realtimeConfig?.model
302
+ };
303
+ }
304
+ updateConfig(_options) {
305
+ this.logger.debug("updateConfig not implemented by this voice provider");
306
+ }
307
+ /**
308
+ * Initializes a WebSocket or WebRTC connection for real-time communication
309
+ * @returns Promise that resolves when the connection is established
310
+ */
311
+ async connect(_options) {
312
+ this.logger.debug("connect not implemented by this voice provider");
313
+ }
314
+ /**
315
+ * Relay audio data to the voice provider for real-time processing
316
+ * @param audioData Audio data to relay
317
+ */
318
+ async send(_audioData) {
319
+ this.logger.debug("relay not implemented by this voice provider");
320
+ }
321
+ /**
322
+ * Trigger voice providers to respond
323
+ */
324
+ async answer(_options) {
325
+ this.logger.debug("answer not implemented by this voice provider");
326
+ }
327
+ /**
328
+ * Equip the voice provider with instructions
329
+ * @param instructions Instructions to add
330
+ */
331
+ addInstructions(_instructions) {}
332
+ /**
333
+ * Equip the voice provider with tools
334
+ * @param tools Array of tools to add
335
+ */
336
+ addTools(_tools) {}
337
+ /**
338
+ * Disconnect from the WebSocket or WebRTC connection
339
+ */
340
+ close() {
341
+ this.logger.debug("close not implemented by this voice provider");
342
+ }
343
+ /**
344
+ * Register an event listener
345
+ * @param event Event name (e.g., 'speaking', 'writing', 'error')
346
+ * @param callback Callback function that receives event data
347
+ */
348
+ on(_event, _callback) {
349
+ this.logger.debug("on not implemented by this voice provider");
350
+ }
351
+ /**
352
+ * Remove an event listener
353
+ * @param event Event name (e.g., 'speaking', 'writing', 'error')
354
+ * @param callback Callback function to remove
355
+ */
356
+ off(_event, _callback) {
357
+ this.logger.debug("off not implemented by this voice provider");
358
+ }
359
+ /**
360
+ * Get available speakers/voices
361
+ * @returns Array of available voice IDs and their metadata
362
+ */
363
+ getSpeakers() {
364
+ this.logger.debug("getSpeakers not implemented by this voice provider");
365
+ return Promise.resolve([]);
366
+ }
367
+ /**
368
+ * Get available speakers/voices
369
+ * @returns Array of available voice IDs and their metadata
370
+ */
371
+ getListener() {
372
+ this.logger.debug("getListener not implemented by this voice provider");
373
+ return Promise.resolve({ enabled: false });
374
+ }
263
375
  };
264
-
265
- // src/voices.ts
266
- var SIMBA_3_VOICES = [
267
- "beatrice_32",
268
- "dominic_32",
269
- "edmund_32",
270
- "geffen_32",
271
- "harper_32",
272
- "hugh_32",
273
- "imogen_32",
274
- "wyatt_32"
376
+ //#endregion
377
+ //#region src/voices.ts
378
+ /**
379
+ * Curated voices served by the Simba 3 generation models (`simba-3.0` and
380
+ * `simba-3.2`). The classic catalog voices in `SPEECHIFY_VOICES` are not
381
+ * served by those models and return an error. `simba-3.2` additionally
382
+ * accepts cloned voices manually approved by Speechify.
383
+ */
384
+ const SIMBA_3_VOICES = [
385
+ "beatrice_32",
386
+ "dominic_32",
387
+ "edmund_32",
388
+ "geffen_32",
389
+ "harper_32",
390
+ "hugh_32",
391
+ "imogen_32",
392
+ "wyatt_32"
275
393
  ];
276
- var SPEECHIFY_VOICES = [
277
- "henry",
278
- "bwyneth",
279
- "carly",
280
- "kristy",
281
- "oliver",
282
- "tasha",
283
- "joe",
284
- "lisa",
285
- "george",
286
- "emily",
287
- "rob",
288
- "russell",
289
- "benjamin",
290
- "michael",
291
- "kim",
292
- "ankit",
293
- "arun",
294
- "carol",
295
- "helen",
296
- "julie",
297
- "linda",
298
- "mark",
299
- "nick",
300
- "elijah",
301
- "beverly",
302
- "collin",
303
- "erin",
304
- "jack",
305
- "jesse",
306
- "ken",
307
- "lindsey",
308
- "monica",
309
- "phil",
310
- "ron",
311
- "stacy",
312
- "archie",
313
- "evelyn",
314
- "freddie",
315
- "harper",
316
- "jacob",
317
- "james",
318
- "mason",
319
- "victoria",
320
- "christina",
321
- "douglas",
322
- "lauren",
323
- "patricia",
324
- "jennifer",
325
- "robert",
326
- "peter",
327
- "jeremy",
328
- "barbara",
329
- "susan",
330
- "charles",
331
- "harold",
332
- "sarah",
333
- "karen",
334
- "anthony",
335
- "donald",
336
- "paul",
337
- "steven",
338
- "andrew",
339
- "kenneth",
340
- "joshua",
341
- "betty",
342
- "margaret",
343
- "kyle",
344
- "edward",
345
- "ronald",
346
- "timothy",
347
- "sandra",
348
- "dorothy",
349
- "jeffrey",
350
- "kimberly",
351
- "donna",
352
- "walter",
353
- "megan",
354
- "richard",
355
- "amanda",
356
- "melissa",
357
- "deborah",
358
- "gary",
359
- "rebecca",
360
- "sharon",
361
- "cynthia",
362
- "kathleen",
363
- "joan",
364
- "shirley",
365
- "angela",
366
- "anna",
367
- "brenda",
368
- "larry",
369
- "keith",
370
- "scott",
371
- "pamela",
372
- "samuel",
373
- "gregory",
374
- "samantha",
375
- "katherine",
376
- "christine",
377
- "frank",
378
- "alexander",
379
- "raymond",
380
- "debra",
381
- "patrick",
382
- "catherine",
383
- "carolyn",
384
- "janet",
385
- "ruth",
386
- "zachary",
387
- "heather",
388
- "diane",
389
- "dennis",
390
- "jerry",
391
- "tyler",
392
- "aaron",
393
- "virginia",
394
- "joyce",
395
- "judith",
396
- "kelly",
397
- "nathan",
398
- "terry",
399
- "carl",
400
- "gerald",
401
- "jaqueline",
402
- "cheryl",
403
- "christian",
404
- "rohit",
405
- "gloria",
406
- "arthur",
407
- "austin",
408
- "sean",
409
- "martha",
410
- "randy",
411
- "ralph",
412
- "roy",
413
- "alan",
414
- "logan",
415
- "willie",
416
- "kathryn",
417
- "frances",
418
- "madison",
419
- "bruce",
420
- "billy",
421
- "jordan",
422
- "bryan",
423
- "dylan",
424
- "vincent",
425
- "eugene",
426
- "janice",
427
- "jean",
428
- "abigail",
429
- "alice",
430
- "bobby",
431
- "julia",
432
- "johnny",
433
- "judy",
434
- "bradley",
435
- "hunter",
436
- "dale",
437
- "howard",
438
- "fred",
439
- "danielle",
440
- "marilyn",
441
- "blake",
442
- "doris",
443
- "denise",
444
- "issac",
445
- "theresa",
446
- "natalie",
447
- "aiden",
448
- "brittany",
449
- "charlotte",
450
- "marie",
451
- "kayla",
452
- "alexis",
453
- "lori",
454
- "landon",
455
- "tiffany",
456
- "marcus",
457
- "martin",
458
- "curtis",
459
- "kathy",
460
- "todd",
461
- "leonard",
462
- "calvin",
463
- "rose",
464
- "ava",
465
- "bonnie",
466
- "peggy",
467
- "edwin",
468
- "don",
469
- "ruby",
470
- "crystal",
471
- "craig",
472
- "norma",
473
- "paula",
474
- "annie",
475
- "shawn",
476
- "lillian",
477
- "robin",
478
- "evan",
479
- "garrette",
480
- "francis",
481
- "danny",
482
- "stanley",
483
- "lucy",
484
- "jeffery",
485
- "herbert",
486
- "lee",
487
- "april",
488
- "anne",
489
- "tammy",
490
- "trevor",
491
- "eleanor",
492
- "regina",
493
- "carrie",
494
- "leah",
495
- "beth",
496
- "cody",
497
- "shane",
498
- "dana",
499
- "allison",
500
- "dawn",
501
- "julian",
502
- "wendy",
503
- "travis",
504
- "florence",
505
- "tracy",
506
- "adrian",
507
- "phillis",
508
- "carole",
509
- "mildred",
510
- "cameron",
511
- "chad",
512
- "connie",
513
- "gladys",
514
- "arlene",
515
- "jana",
516
- "leona",
517
- "miriam",
518
- "lorrie",
519
- "velma",
520
- "eduardo",
521
- "bennie",
522
- "rene",
523
- "ed",
524
- "stuart",
525
- "terrence",
526
- "delbert",
527
- "colin",
528
- "susanne",
529
- "hugo",
530
- "ignacio",
531
- "sheldon",
532
- "josefina",
533
- "corinne",
534
- "lana",
535
- "cherry",
536
- "erick",
537
- "frankie",
538
- "stewart",
539
- "claudette",
540
- "doyle",
541
- "darrel",
542
- "janine",
543
- "simone",
544
- "casey",
545
- "leta",
546
- "rogelio",
547
- "lorraine",
548
- "terence",
549
- "santiago",
550
- "alonzo",
551
- "benny",
552
- "elisa",
553
- "dee",
554
- "bert",
555
- "elbert",
556
- "charmaine",
557
- "roslyn",
558
- "shelley",
559
- "ramiro",
560
- "noel",
561
- "mercedes",
562
- "christie",
563
- "laurel",
564
- "spencer",
565
- "pat",
566
- "dorthy",
567
- "jeanie",
568
- "clare",
569
- "aileen",
570
- "grady",
571
- "deana",
572
- "cornelius",
573
- "cecelia",
574
- "maryann",
575
- "rolando",
576
- "lamar",
577
- "susana",
578
- "katharine",
579
- "clay",
580
- "liza",
581
- "jerri",
582
- "rochelle",
583
- "cathy",
584
- "percy",
585
- "dexter",
586
- "maribel",
587
- "rosemarie",
588
- "bradford",
589
- "kari",
590
- "nikki",
591
- "bernadette",
592
- "eugenia",
593
- "merie",
594
- "darie",
595
- "amon",
596
- "moses",
597
- "concetta",
598
- "irvin",
599
- "rodolfo",
600
- "christi",
601
- "roman",
602
- "janie",
603
- "marcy",
604
- "lindy",
605
- "tommie",
606
- "darnell",
607
- "randal",
608
- "selena",
609
- "shari",
610
- "antoinette",
611
- "timmy",
612
- "darrin",
613
- "margo",
614
- "sherri",
615
- "erika",
616
- "robbie",
617
- "marcella",
618
- "lela",
619
- "winston",
620
- "jeannine",
621
- "brendan",
622
- "christa",
623
- "deloris",
624
- "toby",
625
- "elva",
626
- "van",
627
- "abel",
628
- "myron",
629
- "gracie",
630
- "gwen",
631
- "melba",
632
- "boyd",
633
- "shawna",
634
- "courtney",
635
- "marlena",
636
- "cathie",
637
- "ramesh",
638
- "rita",
639
- "joel",
640
- "derek",
641
- "earl",
642
- "brett",
643
- "ellis",
644
- "ian",
645
- "oscar",
646
- "edna",
647
- "ethel",
648
- "gene",
649
- "shannon",
650
- "sheila",
651
- "dustin",
652
- "ellen",
653
- "hilda",
654
- "ray",
655
- "marjorie",
656
- "sylvia",
657
- "barry",
658
- "melvin",
659
- "thelma",
660
- "cindy",
661
- "miranda",
662
- "bernard",
663
- "carlton",
664
- "juanita",
665
- "darrell",
666
- "erik",
667
- "jeremiah",
668
- "nicolas",
669
- "gordon",
670
- "violet",
671
- "mona",
672
- "glen",
673
- "willis",
674
- "harvey",
675
- "rudolph",
676
- "preston",
677
- "cole",
678
- "june",
679
- "pauline",
680
- "leo",
681
- "earnest",
682
- "devin",
683
- "audrey",
684
- "claire",
685
- "vivian",
686
- "goldie",
687
- "tommy",
688
- "allen",
689
- "glenn",
690
- "wilson",
691
- "jill",
692
- "loretta",
693
- "mabel",
694
- "marsha",
695
- "lillie",
696
- "minnie",
697
- "essie",
698
- "madge",
699
- "viola",
700
- "nellie",
701
- "pearl",
702
- "marvin",
703
- "mae",
704
- "levi",
705
- "lucille",
706
- "hazel",
707
- "nathaniel",
708
- "lydia",
709
- "bertha",
710
- "ursula",
711
- "kay",
712
- "sue",
713
- "dean",
714
- "verna",
715
- "teri",
716
- "edith",
717
- "dan",
718
- "lewis",
719
- "harriett",
720
- "clifford",
721
- "genevieve",
722
- "colleen",
723
- "gilbert",
724
- "patrice",
725
- "jared",
726
- "elaine",
727
- "maureen",
728
- "edmund",
729
- "nina",
730
- "georgia",
731
- "garrett",
732
- "renee",
733
- "bessie",
734
- "leslie",
735
- "max",
736
- "leon",
737
- "fannie",
738
- "lowell",
739
- "veronica",
740
- "vanessa",
741
- "joy",
742
- "jim",
743
- "faith",
744
- "valerie",
745
- "wanda",
746
- "steve",
747
- "naomi",
748
- "miles",
749
- "marcia",
750
- "brent",
751
- "clinton",
752
- "jon",
753
- "marshall",
754
- "roberta",
755
- "alexandra",
756
- "doreen",
757
- "daisy",
758
- "della",
759
- "minerva",
760
- "cedric",
761
- "patsy",
762
- "kerry",
763
- "lena",
764
- "gregg",
765
- "lois",
766
- "kurt",
767
- "lorene",
768
- "susie",
769
- "nora",
770
- "lucinda",
771
- "mathew",
772
- "flora",
773
- "rosie",
774
- "sherman",
775
- "lance",
776
- "darcy",
777
- "mattie",
778
- "madeline",
779
- "sylvester",
780
- "cory",
781
- "anita",
782
- "allan",
783
- "lula",
784
- "nell",
785
- "priscilla",
786
- "kristin",
787
- "rosemary",
788
- "roosevelt",
789
- "geneva",
790
- "jeannette",
791
- "bob",
792
- "esther",
793
- "michele",
794
- "forrest",
795
- "wilbert",
796
- "cathleen",
797
- "jaime",
798
- "dwayne",
799
- "inez",
800
- "alberto",
801
- "lynne",
802
- "maxine",
803
- "wilma",
804
- "taylor",
805
- "angelina",
806
- "hope",
807
- "margie",
808
- "myrtle",
809
- "misty",
810
- "jimmie",
811
- "eunice",
812
- "everett",
813
- "miracle",
814
- "billie",
815
- "leland",
816
- "jackie",
817
- "kristina",
818
- "johnnie",
819
- "isaac",
820
- "bobbie",
821
- "tonya",
822
- "reba",
823
- "kristine",
824
- "amelia",
825
- "cassandra",
826
- "angie",
827
- "maude",
828
- "nichole",
829
- "marguerite",
830
- "justine",
831
- "kelli",
832
- "mandy",
833
- "jeri",
834
- "darla",
835
- "shelia",
836
- "jacquelin",
837
- "cara",
838
- "kellie",
839
- "jolene",
840
- "chelsea",
841
- "autumn",
842
- "glenda",
843
- "lolita",
844
- "jeanne",
845
- "sherrie",
846
- "toni",
847
- "becky",
848
- "jennie",
849
- "jenna",
850
- "leigh",
851
- "cristina",
852
- "blanche",
853
- "clarissa",
854
- "betsy",
855
- "bridget",
856
- "ginger",
857
- "faye",
858
- "candice",
859
- "jaclyn",
860
- "krista",
861
- "marisa",
862
- "gayle",
863
- "meredith",
864
- "angelica",
865
- "rachael",
866
- "candy",
867
- "trisha",
868
- "sandy",
869
- "holly",
870
- "alicia",
871
- "melinda",
872
- "geraldine",
873
- "tara",
874
- "isabel",
875
- "adrienne",
876
- "terra",
877
- "rubye",
878
- "antonia",
879
- "guadalupe",
880
- "cheri",
881
- "janelle",
882
- "constance",
883
- "robyn",
884
- "jodi",
885
- "krystal",
886
- "rosalie",
887
- "deanna",
888
- "debbie",
889
- "josie",
890
- "ronda",
891
- "paulette",
892
- "belinda",
893
- "alton",
894
- "rudy",
895
- "kelvin",
896
- "damon",
897
- "johnathan",
898
- "cesar",
899
- "ira",
900
- "horace",
901
- "grant",
902
- "lionel",
903
- "wilbur",
904
- "jake",
905
- "jody",
906
- "rickey",
907
- "lester",
908
- "pablo",
909
- "neal",
910
- "mack",
911
- "orlando",
912
- "alfonso",
913
- "ernesto",
914
- "rex",
915
- "lynn",
916
- "matt",
917
- "lyle",
918
- "kristopher",
919
- "hubert",
920
- "kenny",
921
- "doug",
922
- "sammy",
923
- "homer",
924
- "wendell",
925
- "woodrow",
926
- "felipe",
927
- "garry",
928
- "pete",
929
- "marco",
930
- "rufus",
931
- "owen",
932
- "bryant",
933
- "abraham",
934
- "irving",
935
- "jermaine",
936
- "julius",
937
- "marty",
938
- "alejandro",
939
- "carmen",
940
- "carlos",
941
- "celia",
942
- "lucas",
943
- "luiza",
944
- "diogo",
945
- "agueda",
946
- "raphael",
947
- "elise",
948
- "frederick",
949
- "andra",
950
- "frederik",
951
- "freja",
952
- "daan",
953
- "lotte",
954
- "eino",
955
- "helmi",
956
- "jakob",
957
- "frida",
958
- "kostas",
959
- "eleni",
960
- "lazzaro",
961
- "alessia",
962
- "mart",
963
- "liis",
964
- "trinh",
965
- "thoa",
966
- "lesya",
967
- "taras",
968
- "mikhail",
969
- "olga",
970
- "axel",
971
- "ebba",
972
- "hemant",
973
- "priya",
974
- "aicha",
975
- "ismail",
976
- "moshe",
977
- "inbar",
978
- "gil",
979
- "lital",
980
- "yusuf",
981
- "elif",
982
- "dominika",
983
- "michal"
394
+ const SPEECHIFY_VOICES = [
395
+ "henry",
396
+ "bwyneth",
397
+ "carly",
398
+ "kristy",
399
+ "oliver",
400
+ "tasha",
401
+ "joe",
402
+ "lisa",
403
+ "george",
404
+ "emily",
405
+ "rob",
406
+ "russell",
407
+ "benjamin",
408
+ "michael",
409
+ "kim",
410
+ "ankit",
411
+ "arun",
412
+ "carol",
413
+ "helen",
414
+ "julie",
415
+ "linda",
416
+ "mark",
417
+ "nick",
418
+ "elijah",
419
+ "beverly",
420
+ "collin",
421
+ "erin",
422
+ "jack",
423
+ "jesse",
424
+ "ken",
425
+ "lindsey",
426
+ "monica",
427
+ "phil",
428
+ "ron",
429
+ "stacy",
430
+ "archie",
431
+ "evelyn",
432
+ "freddie",
433
+ "harper",
434
+ "jacob",
435
+ "james",
436
+ "mason",
437
+ "victoria",
438
+ "christina",
439
+ "douglas",
440
+ "lauren",
441
+ "patricia",
442
+ "jennifer",
443
+ "robert",
444
+ "peter",
445
+ "jeremy",
446
+ "barbara",
447
+ "susan",
448
+ "charles",
449
+ "harold",
450
+ "sarah",
451
+ "karen",
452
+ "anthony",
453
+ "donald",
454
+ "paul",
455
+ "steven",
456
+ "andrew",
457
+ "kenneth",
458
+ "joshua",
459
+ "betty",
460
+ "margaret",
461
+ "kyle",
462
+ "edward",
463
+ "ronald",
464
+ "timothy",
465
+ "sandra",
466
+ "dorothy",
467
+ "jeffrey",
468
+ "kimberly",
469
+ "donna",
470
+ "walter",
471
+ "megan",
472
+ "richard",
473
+ "amanda",
474
+ "melissa",
475
+ "deborah",
476
+ "gary",
477
+ "rebecca",
478
+ "sharon",
479
+ "cynthia",
480
+ "kathleen",
481
+ "joan",
482
+ "shirley",
483
+ "angela",
484
+ "anna",
485
+ "brenda",
486
+ "larry",
487
+ "keith",
488
+ "scott",
489
+ "pamela",
490
+ "samuel",
491
+ "gregory",
492
+ "samantha",
493
+ "katherine",
494
+ "christine",
495
+ "frank",
496
+ "alexander",
497
+ "raymond",
498
+ "debra",
499
+ "patrick",
500
+ "catherine",
501
+ "carolyn",
502
+ "janet",
503
+ "ruth",
504
+ "zachary",
505
+ "heather",
506
+ "diane",
507
+ "dennis",
508
+ "jerry",
509
+ "tyler",
510
+ "aaron",
511
+ "virginia",
512
+ "joyce",
513
+ "judith",
514
+ "kelly",
515
+ "nathan",
516
+ "terry",
517
+ "carl",
518
+ "gerald",
519
+ "jaqueline",
520
+ "cheryl",
521
+ "christian",
522
+ "rohit",
523
+ "gloria",
524
+ "arthur",
525
+ "austin",
526
+ "sean",
527
+ "martha",
528
+ "randy",
529
+ "ralph",
530
+ "roy",
531
+ "alan",
532
+ "logan",
533
+ "willie",
534
+ "kathryn",
535
+ "frances",
536
+ "madison",
537
+ "bruce",
538
+ "billy",
539
+ "jordan",
540
+ "bryan",
541
+ "dylan",
542
+ "vincent",
543
+ "eugene",
544
+ "janice",
545
+ "jean",
546
+ "abigail",
547
+ "alice",
548
+ "bobby",
549
+ "julia",
550
+ "johnny",
551
+ "judy",
552
+ "bradley",
553
+ "hunter",
554
+ "dale",
555
+ "howard",
556
+ "fred",
557
+ "danielle",
558
+ "marilyn",
559
+ "blake",
560
+ "doris",
561
+ "denise",
562
+ "issac",
563
+ "theresa",
564
+ "natalie",
565
+ "aiden",
566
+ "brittany",
567
+ "charlotte",
568
+ "marie",
569
+ "kayla",
570
+ "alexis",
571
+ "lori",
572
+ "landon",
573
+ "tiffany",
574
+ "marcus",
575
+ "martin",
576
+ "curtis",
577
+ "kathy",
578
+ "todd",
579
+ "leonard",
580
+ "calvin",
581
+ "rose",
582
+ "ava",
583
+ "bonnie",
584
+ "peggy",
585
+ "edwin",
586
+ "don",
587
+ "ruby",
588
+ "crystal",
589
+ "craig",
590
+ "norma",
591
+ "paula",
592
+ "annie",
593
+ "shawn",
594
+ "lillian",
595
+ "robin",
596
+ "evan",
597
+ "garrette",
598
+ "francis",
599
+ "danny",
600
+ "stanley",
601
+ "lucy",
602
+ "jeffery",
603
+ "herbert",
604
+ "lee",
605
+ "april",
606
+ "anne",
607
+ "tammy",
608
+ "trevor",
609
+ "eleanor",
610
+ "regina",
611
+ "carrie",
612
+ "leah",
613
+ "beth",
614
+ "cody",
615
+ "shane",
616
+ "dana",
617
+ "allison",
618
+ "dawn",
619
+ "julian",
620
+ "wendy",
621
+ "travis",
622
+ "florence",
623
+ "tracy",
624
+ "adrian",
625
+ "phillis",
626
+ "carole",
627
+ "mildred",
628
+ "cameron",
629
+ "chad",
630
+ "connie",
631
+ "gladys",
632
+ "arlene",
633
+ "jana",
634
+ "leona",
635
+ "miriam",
636
+ "lorrie",
637
+ "velma",
638
+ "eduardo",
639
+ "bennie",
640
+ "rene",
641
+ "ed",
642
+ "stuart",
643
+ "terrence",
644
+ "delbert",
645
+ "colin",
646
+ "susanne",
647
+ "hugo",
648
+ "ignacio",
649
+ "sheldon",
650
+ "josefina",
651
+ "corinne",
652
+ "lana",
653
+ "cherry",
654
+ "erick",
655
+ "frankie",
656
+ "stewart",
657
+ "claudette",
658
+ "doyle",
659
+ "darrel",
660
+ "janine",
661
+ "simone",
662
+ "casey",
663
+ "leta",
664
+ "rogelio",
665
+ "lorraine",
666
+ "terence",
667
+ "santiago",
668
+ "alonzo",
669
+ "benny",
670
+ "elisa",
671
+ "dee",
672
+ "bert",
673
+ "elbert",
674
+ "charmaine",
675
+ "roslyn",
676
+ "shelley",
677
+ "ramiro",
678
+ "noel",
679
+ "mercedes",
680
+ "christie",
681
+ "laurel",
682
+ "spencer",
683
+ "pat",
684
+ "dorthy",
685
+ "jeanie",
686
+ "clare",
687
+ "aileen",
688
+ "grady",
689
+ "deana",
690
+ "cornelius",
691
+ "cecelia",
692
+ "maryann",
693
+ "rolando",
694
+ "lamar",
695
+ "susana",
696
+ "katharine",
697
+ "clay",
698
+ "liza",
699
+ "jerri",
700
+ "rochelle",
701
+ "cathy",
702
+ "percy",
703
+ "dexter",
704
+ "maribel",
705
+ "rosemarie",
706
+ "bradford",
707
+ "kari",
708
+ "nikki",
709
+ "bernadette",
710
+ "eugenia",
711
+ "merie",
712
+ "darie",
713
+ "amon",
714
+ "moses",
715
+ "concetta",
716
+ "irvin",
717
+ "rodolfo",
718
+ "christi",
719
+ "roman",
720
+ "janie",
721
+ "marcy",
722
+ "lindy",
723
+ "tommie",
724
+ "darnell",
725
+ "randal",
726
+ "selena",
727
+ "shari",
728
+ "antoinette",
729
+ "timmy",
730
+ "darrin",
731
+ "margo",
732
+ "sherri",
733
+ "erika",
734
+ "robbie",
735
+ "marcella",
736
+ "lela",
737
+ "winston",
738
+ "jeannine",
739
+ "brendan",
740
+ "christa",
741
+ "deloris",
742
+ "toby",
743
+ "elva",
744
+ "van",
745
+ "abel",
746
+ "myron",
747
+ "gracie",
748
+ "gwen",
749
+ "melba",
750
+ "boyd",
751
+ "shawna",
752
+ "courtney",
753
+ "marlena",
754
+ "cathie",
755
+ "ramesh",
756
+ "rita",
757
+ "joel",
758
+ "derek",
759
+ "earl",
760
+ "brett",
761
+ "ellis",
762
+ "ian",
763
+ "oscar",
764
+ "edna",
765
+ "ethel",
766
+ "gene",
767
+ "shannon",
768
+ "sheila",
769
+ "dustin",
770
+ "ellen",
771
+ "hilda",
772
+ "ray",
773
+ "marjorie",
774
+ "sylvia",
775
+ "barry",
776
+ "melvin",
777
+ "thelma",
778
+ "cindy",
779
+ "miranda",
780
+ "bernard",
781
+ "carlton",
782
+ "juanita",
783
+ "darrell",
784
+ "erik",
785
+ "jeremiah",
786
+ "nicolas",
787
+ "gordon",
788
+ "violet",
789
+ "mona",
790
+ "glen",
791
+ "willis",
792
+ "harvey",
793
+ "rudolph",
794
+ "preston",
795
+ "cole",
796
+ "june",
797
+ "pauline",
798
+ "leo",
799
+ "earnest",
800
+ "devin",
801
+ "audrey",
802
+ "claire",
803
+ "vivian",
804
+ "goldie",
805
+ "tommy",
806
+ "allen",
807
+ "glenn",
808
+ "wilson",
809
+ "jill",
810
+ "loretta",
811
+ "mabel",
812
+ "marsha",
813
+ "lillie",
814
+ "minnie",
815
+ "essie",
816
+ "madge",
817
+ "viola",
818
+ "nellie",
819
+ "pearl",
820
+ "marvin",
821
+ "mae",
822
+ "levi",
823
+ "lucille",
824
+ "hazel",
825
+ "nathaniel",
826
+ "lydia",
827
+ "bertha",
828
+ "ursula",
829
+ "kay",
830
+ "sue",
831
+ "dean",
832
+ "verna",
833
+ "teri",
834
+ "edith",
835
+ "dan",
836
+ "lewis",
837
+ "harriett",
838
+ "clifford",
839
+ "genevieve",
840
+ "colleen",
841
+ "gilbert",
842
+ "patrice",
843
+ "jared",
844
+ "elaine",
845
+ "maureen",
846
+ "edmund",
847
+ "nina",
848
+ "georgia",
849
+ "garrett",
850
+ "renee",
851
+ "bessie",
852
+ "leslie",
853
+ "max",
854
+ "leon",
855
+ "fannie",
856
+ "lowell",
857
+ "veronica",
858
+ "vanessa",
859
+ "joy",
860
+ "jim",
861
+ "faith",
862
+ "valerie",
863
+ "wanda",
864
+ "steve",
865
+ "naomi",
866
+ "miles",
867
+ "marcia",
868
+ "brent",
869
+ "clinton",
870
+ "jon",
871
+ "marshall",
872
+ "roberta",
873
+ "alexandra",
874
+ "doreen",
875
+ "daisy",
876
+ "della",
877
+ "minerva",
878
+ "cedric",
879
+ "patsy",
880
+ "kerry",
881
+ "lena",
882
+ "gregg",
883
+ "lois",
884
+ "kurt",
885
+ "lorene",
886
+ "susie",
887
+ "nora",
888
+ "lucinda",
889
+ "mathew",
890
+ "flora",
891
+ "rosie",
892
+ "sherman",
893
+ "lance",
894
+ "darcy",
895
+ "mattie",
896
+ "madeline",
897
+ "sylvester",
898
+ "cory",
899
+ "anita",
900
+ "allan",
901
+ "lula",
902
+ "nell",
903
+ "priscilla",
904
+ "kristin",
905
+ "rosemary",
906
+ "roosevelt",
907
+ "geneva",
908
+ "jeannette",
909
+ "bob",
910
+ "esther",
911
+ "michele",
912
+ "forrest",
913
+ "wilbert",
914
+ "cathleen",
915
+ "jaime",
916
+ "dwayne",
917
+ "inez",
918
+ "alberto",
919
+ "lynne",
920
+ "maxine",
921
+ "wilma",
922
+ "taylor",
923
+ "angelina",
924
+ "hope",
925
+ "margie",
926
+ "myrtle",
927
+ "misty",
928
+ "jimmie",
929
+ "eunice",
930
+ "everett",
931
+ "miracle",
932
+ "billie",
933
+ "leland",
934
+ "jackie",
935
+ "kristina",
936
+ "johnnie",
937
+ "isaac",
938
+ "bobbie",
939
+ "tonya",
940
+ "reba",
941
+ "kristine",
942
+ "amelia",
943
+ "cassandra",
944
+ "angie",
945
+ "maude",
946
+ "nichole",
947
+ "marguerite",
948
+ "justine",
949
+ "kelli",
950
+ "mandy",
951
+ "jeri",
952
+ "darla",
953
+ "shelia",
954
+ "jacquelin",
955
+ "cara",
956
+ "kellie",
957
+ "jolene",
958
+ "chelsea",
959
+ "autumn",
960
+ "glenda",
961
+ "lolita",
962
+ "jeanne",
963
+ "sherrie",
964
+ "toni",
965
+ "becky",
966
+ "jennie",
967
+ "jenna",
968
+ "leigh",
969
+ "cristina",
970
+ "blanche",
971
+ "clarissa",
972
+ "betsy",
973
+ "bridget",
974
+ "ginger",
975
+ "faye",
976
+ "candice",
977
+ "jaclyn",
978
+ "krista",
979
+ "marisa",
980
+ "gayle",
981
+ "meredith",
982
+ "angelica",
983
+ "rachael",
984
+ "candy",
985
+ "trisha",
986
+ "sandy",
987
+ "holly",
988
+ "alicia",
989
+ "melinda",
990
+ "geraldine",
991
+ "tara",
992
+ "isabel",
993
+ "adrienne",
994
+ "terra",
995
+ "rubye",
996
+ "antonia",
997
+ "guadalupe",
998
+ "cheri",
999
+ "janelle",
1000
+ "constance",
1001
+ "robyn",
1002
+ "jodi",
1003
+ "krystal",
1004
+ "rosalie",
1005
+ "deanna",
1006
+ "debbie",
1007
+ "josie",
1008
+ "ronda",
1009
+ "paulette",
1010
+ "belinda",
1011
+ "alton",
1012
+ "rudy",
1013
+ "kelvin",
1014
+ "damon",
1015
+ "johnathan",
1016
+ "cesar",
1017
+ "ira",
1018
+ "horace",
1019
+ "grant",
1020
+ "lionel",
1021
+ "wilbur",
1022
+ "jake",
1023
+ "jody",
1024
+ "rickey",
1025
+ "lester",
1026
+ "pablo",
1027
+ "neal",
1028
+ "mack",
1029
+ "orlando",
1030
+ "alfonso",
1031
+ "ernesto",
1032
+ "rex",
1033
+ "lynn",
1034
+ "matt",
1035
+ "lyle",
1036
+ "kristopher",
1037
+ "hubert",
1038
+ "kenny",
1039
+ "doug",
1040
+ "sammy",
1041
+ "homer",
1042
+ "wendell",
1043
+ "woodrow",
1044
+ "felipe",
1045
+ "garry",
1046
+ "pete",
1047
+ "marco",
1048
+ "rufus",
1049
+ "owen",
1050
+ "bryant",
1051
+ "abraham",
1052
+ "irving",
1053
+ "jermaine",
1054
+ "julius",
1055
+ "marty",
1056
+ "alejandro",
1057
+ "carmen",
1058
+ "carlos",
1059
+ "celia",
1060
+ "lucas",
1061
+ "luiza",
1062
+ "diogo",
1063
+ "agueda",
1064
+ "raphael",
1065
+ "elise",
1066
+ "frederick",
1067
+ "andra",
1068
+ "frederik",
1069
+ "freja",
1070
+ "daan",
1071
+ "lotte",
1072
+ "eino",
1073
+ "helmi",
1074
+ "jakob",
1075
+ "frida",
1076
+ "kostas",
1077
+ "eleni",
1078
+ "lazzaro",
1079
+ "alessia",
1080
+ "mart",
1081
+ "liis",
1082
+ "trinh",
1083
+ "thoa",
1084
+ "lesya",
1085
+ "taras",
1086
+ "mikhail",
1087
+ "olga",
1088
+ "axel",
1089
+ "ebba",
1090
+ "hemant",
1091
+ "priya",
1092
+ "aicha",
1093
+ "ismail",
1094
+ "moshe",
1095
+ "inbar",
1096
+ "gil",
1097
+ "lital",
1098
+ "yusuf",
1099
+ "elif",
1100
+ "dominika",
1101
+ "michal"
984
1102
  ];
985
-
986
- // src/index.ts
987
- var isSimba3Model = (model) => model === "simba-3.0" || model === "simba-3.2";
1103
+ //#endregion
1104
+ //#region src/index.ts
1105
+ const isSimba3Model = (model) => model === "simba-3.0" || model === "simba-3.2";
988
1106
  var SpeechifyVoice = class extends MastraVoice {
989
- client;
990
- constructor({ speechModel, speaker } = {}) {
991
- const modelName = speechModel?.name ?? "simba-english";
992
- super({
993
- speechModel: {
994
- name: modelName,
995
- apiKey: speechModel?.apiKey ?? process.env.SPEECHIFY_API_KEY
996
- },
997
- // The Simba 3 models serve only the curated SIMBA_3_VOICES, so the
998
- // default speaker has to follow the configured model.
999
- speaker: speaker ?? (isSimba3Model(modelName) ? "harper_32" : "george")
1000
- });
1001
- const apiKey = speechModel?.apiKey ?? process.env.SPEECHIFY_API_KEY;
1002
- if (!apiKey) {
1003
- throw new Error("SPEECHIFY_API_KEY is not set");
1004
- }
1005
- this.client = new Speechify({ apiKey });
1006
- }
1007
- async getSpeakers() {
1008
- return [...SIMBA_3_VOICES, ...SPEECHIFY_VOICES].map((voice) => ({
1009
- voiceId: voice,
1010
- name: voice
1011
- }));
1012
- }
1013
- async streamToString(stream) {
1014
- const chunks = [];
1015
- for await (const chunk of stream) {
1016
- if (typeof chunk === "string") {
1017
- chunks.push(Buffer.from(chunk));
1018
- } else {
1019
- chunks.push(chunk);
1020
- }
1021
- }
1022
- return Buffer.concat(chunks).toString("utf-8");
1023
- }
1024
- async speak(input, options) {
1025
- const text = typeof input === "string" ? input : await this.streamToString(input);
1026
- const { speaker, model, ...streamOptions } = options ?? {};
1027
- const request = {
1028
- ...streamOptions,
1029
- input: text,
1030
- // The SDK sends `model` to the API verbatim, so casting the wider
1031
- // SpeechifyModel union into its narrower VoiceModelName is safe.
1032
- model: model || this.speechModel?.name,
1033
- voiceId: speaker || this.speaker
1034
- };
1035
- const webStream = await this.client.audioStream(request);
1036
- const reader = webStream.getReader();
1037
- const nodeStream = new Readable({
1038
- read: async function() {
1039
- try {
1040
- const { done, value } = await reader.read();
1041
- if (done) {
1042
- this.push(null);
1043
- } else {
1044
- this.push(value);
1045
- }
1046
- } catch (error) {
1047
- this.destroy(error);
1048
- }
1049
- }
1050
- });
1051
- nodeStream.on("end", () => {
1052
- reader.releaseLock();
1053
- });
1054
- return nodeStream;
1055
- }
1056
- /**
1057
- * Checks if listening capabilities are enabled.
1058
- *
1059
- * @returns {Promise<{ enabled: boolean }>}
1060
- */
1061
- async getListener() {
1062
- return { enabled: false };
1063
- }
1064
- async listen(_input, _options) {
1065
- throw new Error("Speechify does not support speech recognition");
1066
- }
1107
+ client;
1108
+ constructor({ speechModel, speaker } = {}) {
1109
+ const modelName = speechModel?.name ?? "simba-english";
1110
+ super({
1111
+ speechModel: {
1112
+ name: modelName,
1113
+ apiKey: speechModel?.apiKey ?? process.env.SPEECHIFY_API_KEY
1114
+ },
1115
+ speaker: speaker ?? (isSimba3Model(modelName) ? "harper_32" : "george")
1116
+ });
1117
+ const apiKey = speechModel?.apiKey ?? process.env.SPEECHIFY_API_KEY;
1118
+ if (!apiKey) throw new Error("SPEECHIFY_API_KEY is not set");
1119
+ this.client = new Speechify({ apiKey });
1120
+ }
1121
+ async getSpeakers() {
1122
+ return [...SIMBA_3_VOICES, ...SPEECHIFY_VOICES].map((voice) => ({
1123
+ voiceId: voice,
1124
+ name: voice
1125
+ }));
1126
+ }
1127
+ async streamToString(stream) {
1128
+ const chunks = [];
1129
+ for await (const chunk of stream) if (typeof chunk === "string") chunks.push(Buffer.from(chunk));
1130
+ else chunks.push(chunk);
1131
+ return Buffer.concat(chunks).toString("utf-8");
1132
+ }
1133
+ async speak(input, options) {
1134
+ const text = typeof input === "string" ? input : await this.streamToString(input);
1135
+ const { speaker, model, ...streamOptions } = options ?? {};
1136
+ const request = {
1137
+ ...streamOptions,
1138
+ input: text,
1139
+ model: model || this.speechModel?.name,
1140
+ voiceId: speaker || this.speaker
1141
+ };
1142
+ const reader = (await this.client.audioStream(request)).getReader();
1143
+ const nodeStream = new Readable({ read: async function() {
1144
+ try {
1145
+ const { done, value } = await reader.read();
1146
+ if (done) this.push(null);
1147
+ else this.push(value);
1148
+ } catch (error) {
1149
+ this.destroy(error);
1150
+ }
1151
+ } });
1152
+ nodeStream.on("end", () => {
1153
+ reader.releaseLock();
1154
+ });
1155
+ return nodeStream;
1156
+ }
1157
+ /**
1158
+ * Checks if listening capabilities are enabled.
1159
+ *
1160
+ * @returns {Promise<{ enabled: boolean }>}
1161
+ */
1162
+ async getListener() {
1163
+ return { enabled: false };
1164
+ }
1165
+ async listen(_input, _options) {
1166
+ throw new Error("Speechify does not support speech recognition");
1167
+ }
1067
1168
  };
1068
-
1169
+ //#endregion
1069
1170
  export { SpeechifyVoice };
1070
- //# sourceMappingURL=index.js.map
1171
+
1071
1172
  //# sourceMappingURL=index.js.map