@cartesia/cartesia-js 1.0.0 → 1.0.2

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.
Files changed (62) hide show
  1. package/.turbo/turbo-build.log +50 -50
  2. package/CHANGELOG.md +12 -0
  3. package/LICENSE.md +21 -0
  4. package/README.md +92 -19
  5. package/dist/{chunk-PQ6CIPFW.js → chunk-6YQ6KDIQ.js} +44 -5
  6. package/dist/{chunk-RO7TY474.js → chunk-BHY7MNGT.js} +11 -6
  7. package/dist/{chunk-F4QWVJY3.js → chunk-EDAAHENY.js} +2 -2
  8. package/dist/{chunk-WIFMLPT5.js → chunk-GHY2WEOK.js} +13 -0
  9. package/dist/{chunk-FN7BK4PS.js → chunk-IZBPLCGW.js} +97 -75
  10. package/dist/{chunk-JYLAM6VU.js → chunk-LZO6K34D.js} +2 -2
  11. package/dist/{chunk-3FL2SNIR.js → chunk-NQVZNVOU.js} +1 -1
  12. package/dist/{chunk-IEN4NCER.js → chunk-NVOCUUOF.js} +3 -3
  13. package/dist/chunk-PISCPZK4.js +40 -0
  14. package/dist/{chunk-SGXUEFII.js → chunk-UCYL2SOX.js} +18 -15
  15. package/dist/index.cjs +186 -103
  16. package/dist/index.d.cts +4 -4
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.js +15 -9
  19. package/dist/lib/client.cjs +35 -10
  20. package/dist/lib/client.d.cts +2 -2
  21. package/dist/lib/client.d.ts +2 -2
  22. package/dist/lib/client.js +2 -2
  23. package/dist/lib/constants.js +1 -1
  24. package/dist/lib/index.cjs +181 -102
  25. package/dist/lib/index.js +8 -8
  26. package/dist/react/index.cjs +286 -158
  27. package/dist/react/index.d.cts +5 -4
  28. package/dist/react/index.d.ts +5 -4
  29. package/dist/react/index.js +115 -66
  30. package/dist/react/utils.js +2 -2
  31. package/dist/tts/index.cjs +165 -89
  32. package/dist/tts/index.js +6 -6
  33. package/dist/tts/player.cjs +5 -0
  34. package/dist/tts/player.js +4 -3
  35. package/dist/tts/source.cjs +50 -4
  36. package/dist/tts/source.d.cts +16 -6
  37. package/dist/tts/source.d.ts +16 -6
  38. package/dist/tts/source.js +4 -2
  39. package/dist/tts/utils.cjs +18 -6
  40. package/dist/tts/utils.d.cts +7 -5
  41. package/dist/tts/utils.d.ts +7 -5
  42. package/dist/tts/utils.js +3 -2
  43. package/dist/tts/websocket.cjs +165 -89
  44. package/dist/tts/websocket.d.cts +12 -8
  45. package/dist/tts/websocket.d.ts +12 -8
  46. package/dist/tts/websocket.js +5 -5
  47. package/dist/types/index.d.cts +65 -5
  48. package/dist/types/index.d.ts +65 -5
  49. package/dist/voices/index.cjs +31 -23
  50. package/dist/voices/index.d.cts +2 -1
  51. package/dist/voices/index.d.ts +2 -1
  52. package/dist/voices/index.js +3 -3
  53. package/package.json +1 -1
  54. package/src/index.ts +2 -0
  55. package/src/lib/client.ts +10 -10
  56. package/src/react/index.ts +115 -64
  57. package/src/tts/source.ts +53 -7
  58. package/src/tts/utils.ts +26 -12
  59. package/src/tts/websocket.ts +42 -23
  60. package/src/types/index.ts +89 -4
  61. package/src/voices/index.ts +22 -15
  62. package/dist/chunk-PQ5EVEEH.js +0 -34
@@ -22,6 +22,18 @@ var __spreadValues = (a, b) => {
22
22
  return a;
23
23
  };
24
24
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __objRest = (source, exclude) => {
26
+ var target = {};
27
+ for (var prop in source)
28
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
29
+ target[prop] = source[prop];
30
+ if (source != null && __getOwnPropSymbols)
31
+ for (var prop of __getOwnPropSymbols(source)) {
32
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
33
+ target[prop] = source[prop];
34
+ }
35
+ return target;
36
+ };
25
37
  var __export = (target, all) => {
26
38
  for (var name in all)
27
39
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -111,20 +123,25 @@ var constructApiUrl = (baseUrl, path, { websocket = false } = {}) => {
111
123
  // src/lib/client.ts
112
124
  var Client = class {
113
125
  constructor(options = {}) {
114
- if (!(options.apiKey || process.env.CARTESIA_API_KEY)) {
126
+ const apiKey = options.apiKey || process.env.CARTESIA_API_KEY;
127
+ if (!apiKey) {
115
128
  throw new Error("Missing Cartesia API key.");
116
129
  }
117
- this.apiKey = options.apiKey || process.env.CARTESIA_API_KEY;
130
+ this.apiKey = typeof apiKey === "function" ? apiKey : () => __async(this, null, function* () {
131
+ return apiKey;
132
+ });
118
133
  this.baseUrl = options.baseUrl || BASE_URL;
119
134
  }
120
- fetch(path, options = {}) {
121
- const url = constructApiUrl(this.baseUrl, path);
122
- return (0, import_cross_fetch.default)(url.toString(), __spreadProps(__spreadValues({}, options), {
123
- headers: __spreadValues({
124
- "X-API-Key": this.apiKey,
125
- "Cartesia-Version": CARTESIA_VERSION
126
- }, options.headers)
127
- }));
135
+ _fetch(_0) {
136
+ return __async(this, arguments, function* (path, options = {}) {
137
+ const url = constructApiUrl(this.baseUrl, path);
138
+ const headers = new Headers(options.headers);
139
+ headers.set("X-API-Key", yield this.apiKey());
140
+ headers.set("Cartesia-Version", CARTESIA_VERSION);
141
+ return (0, import_cross_fetch.default)(url.toString(), __spreadProps(__spreadValues({}, options), {
142
+ headers
143
+ }));
144
+ });
128
145
  }
129
146
  };
130
147
 
@@ -135,7 +152,13 @@ var import_partysocket = require("partysocket");
135
152
 
136
153
  // src/tts/source.ts
137
154
  var import_emittery = __toESM(require("emittery"), 1);
138
- var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate;
155
+ var ENCODING_MAP = {
156
+ pcm_f32le: { arrayType: Float32Array, bytesPerElement: 4 },
157
+ pcm_s16le: { arrayType: Int16Array, bytesPerElement: 2 },
158
+ pcm_alaw: { arrayType: Uint8Array, bytesPerElement: 1 },
159
+ pcm_mulaw: { arrayType: Uint8Array, bytesPerElement: 1 }
160
+ };
161
+ var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate, _encoding, _container, _createBuffer, createBuffer_fn;
139
162
  var Source = class {
140
163
  /**
141
164
  * Create a new Source.
@@ -143,23 +166,44 @@ var Source = class {
143
166
  * @param options - Options for the Source.
144
167
  * @param options.sampleRate - The sample rate of the audio.
145
168
  */
146
- constructor({ sampleRate }) {
169
+ constructor({
170
+ sampleRate,
171
+ encoding,
172
+ container
173
+ }) {
174
+ /**
175
+ * Create a new buffer for the source.
176
+ *
177
+ * @param size - The size of the buffer to create.
178
+ * @returns The new buffer as a TypedArray based on the encoding.
179
+ */
180
+ __privateAdd(this, _createBuffer);
147
181
  __privateAdd(this, _emitter, new import_emittery.default());
148
182
  __privateAdd(this, _buffer, void 0);
149
183
  __privateAdd(this, _readIndex, 0);
150
184
  __privateAdd(this, _writeIndex, 0);
151
185
  __privateAdd(this, _closed, false);
152
186
  __privateAdd(this, _sampleRate, void 0);
187
+ __privateAdd(this, _encoding, void 0);
188
+ __privateAdd(this, _container, void 0);
153
189
  this.on = __privateGet(this, _emitter).on.bind(__privateGet(this, _emitter));
154
190
  this.once = __privateGet(this, _emitter).once.bind(__privateGet(this, _emitter));
155
191
  this.events = __privateGet(this, _emitter).events.bind(__privateGet(this, _emitter));
156
192
  this.off = __privateGet(this, _emitter).off.bind(__privateGet(this, _emitter));
157
193
  __privateSet(this, _sampleRate, sampleRate);
158
- __privateSet(this, _buffer, new Float32Array(1024));
194
+ __privateSet(this, _encoding, encoding);
195
+ __privateSet(this, _container, container);
196
+ __privateSet(this, _buffer, __privateMethod(this, _createBuffer, createBuffer_fn).call(this, 1024));
159
197
  }
160
198
  get sampleRate() {
161
199
  return __privateGet(this, _sampleRate);
162
200
  }
201
+ get encoding() {
202
+ return __privateGet(this, _encoding);
203
+ }
204
+ get container() {
205
+ return __privateGet(this, _container);
206
+ }
163
207
  /**
164
208
  * Append audio to the buffer.
165
209
  *
@@ -173,7 +217,7 @@ var Source = class {
173
217
  while (newCapacity < requiredCapacity) {
174
218
  newCapacity *= 2;
175
219
  }
176
- const newBuffer = new Float32Array(newCapacity);
220
+ const newBuffer = __privateMethod(this, _createBuffer, createBuffer_fn).call(this, newCapacity);
177
221
  newBuffer.set(__privateGet(this, _buffer));
178
222
  __privateSet(this, _buffer, newBuffer);
179
223
  }
@@ -221,6 +265,9 @@ var Source = class {
221
265
  get readIndex() {
222
266
  return __privateGet(this, _readIndex);
223
267
  }
268
+ get writeIndex() {
269
+ return __privateGet(this, _writeIndex);
270
+ }
224
271
  /**
225
272
  * Close the source. This signals that no more audio will be enqueued.
226
273
  *
@@ -242,19 +289,27 @@ _readIndex = new WeakMap();
242
289
  _writeIndex = new WeakMap();
243
290
  _closed = new WeakMap();
244
291
  _sampleRate = new WeakMap();
292
+ _encoding = new WeakMap();
293
+ _container = new WeakMap();
294
+ _createBuffer = new WeakSet();
295
+ createBuffer_fn = function(size) {
296
+ const { arrayType: ArrayType } = ENCODING_MAP[__privateGet(this, _encoding)];
297
+ return new ArrayType(size);
298
+ };
245
299
 
246
300
  // src/tts/utils.ts
247
301
  var import_base64_js = __toESM(require("base64-js"), 1);
248
- function base64ToArray(b64) {
302
+ function base64ToArray(b64, encoding) {
249
303
  const byteArrays = filterSentinel(b64).map((b) => import_base64_js.default.toByteArray(b));
304
+ const { arrayType: ArrayType, bytesPerElement } = ENCODING_MAP[encoding];
250
305
  const totalLength = byteArrays.reduce(
251
- (acc, arr) => acc + arr.length / Float32Array.BYTES_PER_ELEMENT,
306
+ (acc, arr) => acc + arr.length / bytesPerElement,
252
307
  0
253
308
  );
254
- const result = new Float32Array(totalLength);
309
+ const result = new ArrayType(totalLength);
255
310
  let offset = 0;
256
311
  for (const arr of byteArrays) {
257
- const floats = new Float32Array(arr.buffer);
312
+ const floats = new ArrayType(arr.buffer);
258
313
  result.set(floats, offset);
259
314
  offset += floats.length;
260
315
  }
@@ -285,10 +340,10 @@ function createMessageHandlerForContextId(contextId, handler) {
285
340
  let chunk;
286
341
  if (message.done) {
287
342
  chunk = getSentinel();
288
- } else {
343
+ } else if (message.type === "chunk") {
289
344
  chunk = message.data;
290
345
  }
291
- handler({ chunk, message: event.data });
346
+ handler({ chunk, message: event.data, data: message });
292
347
  };
293
348
  }
294
349
  function getSentinel() {
@@ -312,14 +367,14 @@ function getEmitteryCallbacks(emitter) {
312
367
  }
313
368
 
314
369
  // src/tts/websocket.ts
315
- var _isConnected, _sampleRate2, _generateId, generateId_fn;
370
+ var _isConnected, _sampleRate2, _container2, _encoding2, _generateId, generateId_fn;
316
371
  var WebSocket = class extends Client {
317
372
  /**
318
373
  * Create a new WebSocket client.
319
374
  *
320
375
  * @param args - Arguments to pass to the Client constructor.
321
376
  */
322
- constructor({ sampleRate }, ...args) {
377
+ constructor({ sampleRate, container, encoding }, ...args) {
323
378
  super(...args);
324
379
  /**
325
380
  * Generate a unique ID suitable for a streaming context.
@@ -332,12 +387,16 @@ var WebSocket = class extends Client {
332
387
  __privateAdd(this, _generateId);
333
388
  __privateAdd(this, _isConnected, false);
334
389
  __privateAdd(this, _sampleRate2, void 0);
390
+ __privateAdd(this, _container2, void 0);
391
+ __privateAdd(this, _encoding2, void 0);
335
392
  __privateSet(this, _sampleRate2, sampleRate);
393
+ __privateSet(this, _container2, container != null ? container : "raw");
394
+ __privateSet(this, _encoding2, encoding != null ? encoding : "pcm_f32le");
336
395
  }
337
396
  /**
338
397
  * Send a message over the WebSocket to start a stream.
339
398
  *
340
- * @param inputs - Stream options.
399
+ * @param inputs - Stream options. Defined in the StreamRequest type.
341
400
  * @param options - Options for the stream.
342
401
  * @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
343
402
  * If set to `0`, the stream will not time out.
@@ -345,26 +404,30 @@ var WebSocket = class extends Client {
345
404
  * @returns An Emittery instance that emits messages from the WebSocket.
346
405
  * @returns An abort function that can be called to cancel the stream.
347
406
  */
348
- send(inputs, { timeout = 0 } = {}) {
349
- var _a, _b, _c, _d;
407
+ send(_a, { timeout = 0 } = {}) {
408
+ var inputs = __objRest(_a, []);
409
+ var _a2, _b, _c, _d;
350
410
  if (!__privateGet(this, _isConnected)) {
351
411
  throw new Error("Not connected to WebSocket. Call .connect() first.");
352
412
  }
353
- const contextId = __privateMethod(this, _generateId, generateId_fn).call(this);
354
- (_a = this.socket) == null ? void 0 : _a.send(
355
- JSON.stringify(__spreadProps(__spreadValues({
356
- context_id: contextId
357
- }, inputs), {
358
- output_format: {
359
- container: "raw",
360
- encoding: "pcm_f32le",
361
- sample_rate: __privateGet(this, _sampleRate2)
362
- }
363
- }))
413
+ if (!inputs.context_id) {
414
+ inputs.context_id = __privateMethod(this, _generateId, generateId_fn).call(this);
415
+ }
416
+ if (!inputs.output_format) {
417
+ inputs.output_format = {
418
+ container: __privateGet(this, _container2),
419
+ encoding: __privateGet(this, _encoding2),
420
+ sample_rate: __privateGet(this, _sampleRate2)
421
+ };
422
+ }
423
+ (_a2 = this.socket) == null ? void 0 : _a2.send(
424
+ JSON.stringify(__spreadValues({}, inputs))
364
425
  );
365
426
  const emitter = new import_emittery2.default();
366
427
  const source = new Source({
367
- sampleRate: __privateGet(this, _sampleRate2)
428
+ sampleRate: __privateGet(this, _sampleRate2),
429
+ encoding: __privateGet(this, _encoding2),
430
+ container: __privateGet(this, _container2)
368
431
  });
369
432
  const streamCompleteController = new AbortController();
370
433
  let timeoutId = null;
@@ -372,19 +435,26 @@ var WebSocket = class extends Client {
372
435
  timeoutId = setTimeout(streamCompleteController.abort, timeout);
373
436
  }
374
437
  const handleMessage = createMessageHandlerForContextId(
375
- contextId,
376
- (_0) => __async(this, [_0], function* ({ chunk, message }) {
438
+ inputs.context_id,
439
+ (_0) => __async(this, [_0], function* ({ chunk, message, data }) {
377
440
  emitter.emit("message", message);
441
+ if (data.type === "timestamps") {
442
+ emitter.emit("timestamps", data.word_timestamps);
443
+ return;
444
+ }
378
445
  if (isSentinel(chunk)) {
379
446
  yield source.close();
380
447
  streamCompleteController.abort();
381
448
  return;
382
449
  }
383
- yield source.enqueue(base64ToArray([chunk]));
384
450
  if (timeoutId) {
385
451
  clearTimeout(timeoutId);
386
452
  timeoutId = setTimeout(streamCompleteController.abort, timeout);
387
453
  }
454
+ if (!chunk) {
455
+ return;
456
+ }
457
+ yield source.enqueue(base64ToArray([chunk], __privateGet(this, _encoding2)));
388
458
  })
389
459
  );
390
460
  (_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
@@ -427,56 +497,60 @@ var WebSocket = class extends Client {
427
497
  * @throws {Error} If the WebSocket fails to connect.
428
498
  */
429
499
  connect() {
430
- const url = constructApiUrl(this.baseUrl, "/tts/websocket", {
431
- websocket: true
500
+ return __async(this, null, function* () {
501
+ const emitter = new import_emittery2.default();
502
+ this.socket = new import_partysocket.WebSocket(() => __async(this, null, function* () {
503
+ const url = constructApiUrl(this.baseUrl, "/tts/websocket", {
504
+ websocket: true
505
+ });
506
+ url.searchParams.set("api_key", yield this.apiKey());
507
+ url.searchParams.set("cartesia_version", CARTESIA_VERSION);
508
+ return url.toString();
509
+ }));
510
+ this.socket.onopen = () => {
511
+ __privateSet(this, _isConnected, true);
512
+ emitter.emit("open");
513
+ };
514
+ this.socket.onclose = () => {
515
+ __privateSet(this, _isConnected, false);
516
+ emitter.emit("close");
517
+ };
518
+ return new Promise(
519
+ (resolve, reject) => {
520
+ var _a, _b, _c;
521
+ (_a = this.socket) == null ? void 0 : _a.addEventListener(
522
+ "open",
523
+ () => {
524
+ resolve(getEmitteryCallbacks(emitter));
525
+ },
526
+ {
527
+ once: true
528
+ }
529
+ );
530
+ const aborter = new AbortController();
531
+ (_b = this.socket) == null ? void 0 : _b.addEventListener(
532
+ "error",
533
+ () => {
534
+ aborter.abort();
535
+ reject(new Error("WebSocket failed to connect."));
536
+ },
537
+ {
538
+ signal: aborter.signal
539
+ }
540
+ );
541
+ (_c = this.socket) == null ? void 0 : _c.addEventListener(
542
+ "close",
543
+ () => {
544
+ aborter.abort();
545
+ reject(new Error("WebSocket closed before it could connect."));
546
+ },
547
+ {
548
+ signal: aborter.signal
549
+ }
550
+ );
551
+ }
552
+ );
432
553
  });
433
- url.searchParams.set("api_key", this.apiKey);
434
- url.searchParams.set("cartesia_version", CARTESIA_VERSION);
435
- const emitter = new import_emittery2.default();
436
- this.socket = new import_partysocket.WebSocket(url.toString());
437
- this.socket.onopen = () => {
438
- __privateSet(this, _isConnected, true);
439
- emitter.emit("open");
440
- };
441
- this.socket.onclose = () => {
442
- __privateSet(this, _isConnected, false);
443
- emitter.emit("close");
444
- };
445
- return new Promise(
446
- (resolve, reject) => {
447
- var _a, _b, _c;
448
- (_a = this.socket) == null ? void 0 : _a.addEventListener(
449
- "open",
450
- () => {
451
- resolve(getEmitteryCallbacks(emitter));
452
- },
453
- {
454
- once: true
455
- }
456
- );
457
- const aborter = new AbortController();
458
- (_b = this.socket) == null ? void 0 : _b.addEventListener(
459
- "error",
460
- () => {
461
- aborter.abort();
462
- reject(new Error("WebSocket failed to connect."));
463
- },
464
- {
465
- signal: aborter.signal
466
- }
467
- );
468
- (_c = this.socket) == null ? void 0 : _c.addEventListener(
469
- "close",
470
- () => {
471
- aborter.abort();
472
- reject(new Error("WebSocket closed before it could connect."));
473
- },
474
- {
475
- signal: aborter.signal
476
- }
477
- );
478
- }
479
- );
480
554
  }
481
555
  /**
482
556
  * Disconnect from the Cartesia streaming WebSocket.
@@ -488,6 +562,8 @@ var WebSocket = class extends Client {
488
562
  };
489
563
  _isConnected = new WeakMap();
490
564
  _sampleRate2 = new WeakMap();
565
+ _container2 = new WeakMap();
566
+ _encoding2 = new WeakMap();
491
567
  _generateId = new WeakSet();
492
568
  generateId_fn = function() {
493
569
  return (0, import_human_id.humanId)({
@@ -515,40 +591,43 @@ var TTS = class extends Client {
515
591
  var Voices = class extends Client {
516
592
  list() {
517
593
  return __async(this, null, function* () {
518
- const response = yield this.fetch("/voices");
594
+ const response = yield this._fetch("/voices");
519
595
  return response.json();
520
596
  });
521
597
  }
522
598
  get(voiceId) {
523
599
  return __async(this, null, function* () {
524
- const response = yield this.fetch(`/voices/${voiceId}`);
600
+ const response = yield this._fetch(`/voices/${voiceId}`);
525
601
  return response.json();
526
602
  });
527
603
  }
528
604
  create(voice) {
529
605
  return __async(this, null, function* () {
530
- const response = yield this.fetch("/voices", {
606
+ const response = yield this._fetch("/voices", {
531
607
  method: "POST",
532
608
  body: JSON.stringify(voice)
533
609
  });
534
610
  return response.json();
535
611
  });
536
612
  }
613
+ update(id, voice) {
614
+ return __async(this, null, function* () {
615
+ const response = yield this._fetch(`/voices/${id}`, {
616
+ method: "PATCH",
617
+ body: JSON.stringify(voice)
618
+ });
619
+ return response.json();
620
+ });
621
+ }
537
622
  clone(options) {
538
623
  return __async(this, null, function* () {
539
- if (options.mode === "url") {
540
- const response = yield this.fetch(
541
- `/voices/clone/url?link=${options.link}`,
542
- {
543
- method: "POST"
544
- }
545
- );
546
- return response.json();
547
- }
548
624
  if (options.mode === "clip") {
549
625
  const formData = new FormData();
550
626
  formData.append("clip", options.clip);
551
- const response = yield this.fetch("/voices/clone/clip", {
627
+ if (options.enhance !== void 0) {
628
+ formData.append("enhance", options.enhance.toString());
629
+ }
630
+ const response = yield this._fetch("/voices/clone/clip", {
552
631
  method: "POST",
553
632
  body: formData
554
633
  });
@@ -702,7 +781,8 @@ var DEFAULT_BUFFER_DURATION = 0.01;
702
781
  function useTTS({
703
782
  apiKey,
704
783
  baseUrl,
705
- sampleRate
784
+ sampleRate,
785
+ onError
706
786
  }) {
707
787
  var _a, _b;
708
788
  if (typeof window === "undefined") {
@@ -733,7 +813,11 @@ function useTTS({
733
813
  }
734
814
  const cartesia = new Cartesia({ apiKey, baseUrl });
735
815
  baseUrl = baseUrl != null ? baseUrl : cartesia.baseUrl;
736
- return cartesia.tts.websocket({ sampleRate });
816
+ return cartesia.tts.websocket({
817
+ container: "raw",
818
+ encoding: "pcm_f32le",
819
+ sampleRate
820
+ });
737
821
  }, [apiKey, baseUrl, sampleRate]);
738
822
  const websocketReturn = (0, import_react.useRef)(null);
739
823
  const player = (0, import_react.useRef)(null);
@@ -747,20 +831,32 @@ function useTTS({
747
831
  (options) => __async(this, null, function* () {
748
832
  var _a2, _b2;
749
833
  (_a2 = websocketReturn.current) == null ? void 0 : _a2.stop();
750
- setMessages([]);
751
- setBufferStatus("buffering");
752
- websocketReturn.current = (_b2 = websocket == null ? void 0 : websocket.send(options)) != null ? _b2 : null;
753
- if (!websocketReturn.current) {
754
- return;
834
+ try {
835
+ setMessages([]);
836
+ setBufferStatus("buffering");
837
+ websocketReturn.current = (_b2 = websocket == null ? void 0 : websocket.send(options)) != null ? _b2 : null;
838
+ if (!websocketReturn.current) {
839
+ return;
840
+ }
841
+ const unsubscribe = websocketReturn.current.on("message", (message) => {
842
+ const parsedMessage = JSON.parse(message);
843
+ setMessages((messages2) => [...messages2, parsedMessage]);
844
+ if (parsedMessage.error) {
845
+ onError == null ? void 0 : onError(new Error(parsedMessage.error));
846
+ }
847
+ });
848
+ yield websocketReturn.current.source.once("close");
849
+ setBufferStatus("buffered");
850
+ unsubscribe();
851
+ } catch (error) {
852
+ if (error instanceof Error) {
853
+ onError == null ? void 0 : onError(error);
854
+ } else {
855
+ console.error(error);
856
+ }
755
857
  }
756
- const unsubscribe = websocketReturn.current.on("message", (message) => {
757
- setMessages((messages2) => [...messages2, JSON.parse(message)]);
758
- });
759
- yield websocketReturn.current.source.once("close");
760
- setBufferStatus("buffered");
761
- unsubscribe();
762
858
  }),
763
- [websocket]
859
+ [websocket, onError]
764
860
  );
765
861
  const metrics = (0, import_react.useMemo)(() => {
766
862
  var _a2;
@@ -829,56 +925,88 @@ function useTTS({
829
925
  return () => cleanup == null ? void 0 : cleanup();
830
926
  }, [websocket, baseUrl]);
831
927
  const play = (0, import_react.useCallback)(() => __async(this, null, function* () {
832
- if (playbackStatus === "playing" || !websocketReturn.current) {
833
- return;
834
- }
835
- if (player.current) {
836
- yield player.current.stop();
837
- }
838
- setPlaybackStatus("playing");
839
- const unsubscribes = [];
840
- unsubscribes.push(
841
- websocketReturn.current.source.on("wait", () => {
842
- setIsWaiting(true);
843
- })
844
- );
845
- unsubscribes.push(
846
- websocketReturn.current.source.on("read", () => {
847
- setIsWaiting(false);
848
- })
849
- );
850
- player.current = new Player({
851
- bufferDuration: bufferDuration != null ? bufferDuration : DEFAULT_BUFFER_DURATION
852
- });
853
- yield player.current.play(websocketReturn.current.source);
854
- for (const unsubscribe of unsubscribes) {
855
- unsubscribe();
928
+ try {
929
+ if (playbackStatus === "playing" || !websocketReturn.current) {
930
+ return;
931
+ }
932
+ if (player.current) {
933
+ yield player.current.stop();
934
+ }
935
+ setPlaybackStatus("playing");
936
+ const unsubscribes = [];
937
+ unsubscribes.push(
938
+ websocketReturn.current.source.on("wait", () => {
939
+ setIsWaiting(true);
940
+ })
941
+ );
942
+ unsubscribes.push(
943
+ websocketReturn.current.source.on("read", () => {
944
+ setIsWaiting(false);
945
+ })
946
+ );
947
+ player.current = new Player({
948
+ bufferDuration: bufferDuration != null ? bufferDuration : DEFAULT_BUFFER_DURATION
949
+ });
950
+ yield player.current.play(websocketReturn.current.source);
951
+ for (const unsubscribe of unsubscribes) {
952
+ unsubscribe();
953
+ }
954
+ setPlaybackStatus("finished");
955
+ } catch (error) {
956
+ if (error instanceof Error) {
957
+ onError == null ? void 0 : onError(error);
958
+ } else {
959
+ console.error(error);
960
+ }
856
961
  }
857
- setPlaybackStatus("finished");
858
- }), [playbackStatus, bufferDuration]);
962
+ }), [playbackStatus, bufferDuration, onError]);
859
963
  const pause = (0, import_react.useCallback)(() => __async(this, null, function* () {
860
964
  var _a2;
861
- yield (_a2 = player.current) == null ? void 0 : _a2.pause();
862
- setPlaybackStatus("paused");
863
- }), []);
965
+ try {
966
+ yield (_a2 = player.current) == null ? void 0 : _a2.pause();
967
+ setPlaybackStatus("paused");
968
+ } catch (error) {
969
+ if (error instanceof Error) {
970
+ onError == null ? void 0 : onError(error);
971
+ } else {
972
+ console.error(error);
973
+ }
974
+ }
975
+ }), [onError]);
864
976
  const resume = (0, import_react.useCallback)(() => __async(this, null, function* () {
865
977
  var _a2;
866
- yield (_a2 = player.current) == null ? void 0 : _a2.resume();
867
- setPlaybackStatus("playing");
868
- }), []);
978
+ try {
979
+ yield (_a2 = player.current) == null ? void 0 : _a2.resume();
980
+ setPlaybackStatus("playing");
981
+ } catch (error) {
982
+ if (error instanceof Error) {
983
+ onError == null ? void 0 : onError(error);
984
+ } else {
985
+ console.error(error);
986
+ }
987
+ }
988
+ }), [onError]);
869
989
  const toggle = (0, import_react.useCallback)(() => __async(this, null, function* () {
870
990
  var _a2;
871
- yield (_a2 = player.current) == null ? void 0 : _a2.toggle();
872
- setPlaybackStatus((status) => {
873
- if (status === "playing") {
874
- return "paused";
875
- }
876
- if (status === "paused") {
877
- return "playing";
991
+ try {
992
+ yield (_a2 = player.current) == null ? void 0 : _a2.toggle();
993
+ setPlaybackStatus((status) => {
994
+ if (status === "playing") {
995
+ return "paused";
996
+ }
997
+ if (status === "paused") {
998
+ return "playing";
999
+ }
1000
+ return status;
1001
+ });
1002
+ } catch (error) {
1003
+ if (error instanceof Error) {
1004
+ onError == null ? void 0 : onError(error);
1005
+ } else {
1006
+ console.error(error);
878
1007
  }
879
- return status;
880
- });
881
- }), []);
1008
+ }
1009
+ }), [onError]);
882
1010
  return {
883
1011
  buffer,
884
1012
  play,