@cartesia/cartesia-js 1.0.0-alpha.4 → 1.0.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.
Files changed (56) hide show
  1. package/.turbo/turbo-build.log +49 -49
  2. package/CHANGELOG.md +23 -0
  3. package/LICENSE.md +21 -0
  4. package/README.md +102 -21
  5. package/dist/{chunk-VK7LBMVI.js → chunk-2NA5SEML.js} +2 -2
  6. package/dist/{chunk-PQ5EVEEH.js → chunk-5M33ZF3Y.js} +1 -1
  7. package/dist/{chunk-PQ6CIPFW.js → chunk-6YQ6KDIQ.js} +44 -5
  8. package/dist/{chunk-IQAXBRHU.js → chunk-ASZKHN7Q.js} +53 -29
  9. package/dist/{chunk-RO7TY474.js → chunk-BHY7MNGT.js} +11 -6
  10. package/dist/{chunk-WIFMLPT5.js → chunk-GHY2WEOK.js} +13 -0
  11. package/dist/{chunk-SGXUEFII.js → chunk-KUSVZXDT.js} +2 -2
  12. package/dist/{chunk-36JBKJUN.js → chunk-LZO6K34D.js} +20 -7
  13. package/dist/{chunk-3FL2SNIR.js → chunk-NQVZNVOU.js} +1 -1
  14. package/dist/{chunk-ISRU7PLL.js → chunk-OFH3ML4L.js} +3 -3
  15. package/dist/index.cjs +129 -39
  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.js +2 -2
  20. package/dist/lib/constants.js +1 -1
  21. package/dist/lib/index.cjs +106 -33
  22. package/dist/lib/index.js +8 -8
  23. package/dist/react/index.cjs +231 -92
  24. package/dist/react/index.d.cts +4 -3
  25. package/dist/react/index.d.ts +4 -3
  26. package/dist/react/index.js +117 -64
  27. package/dist/react/utils.js +2 -2
  28. package/dist/tts/index.cjs +106 -33
  29. package/dist/tts/index.js +6 -6
  30. package/dist/tts/player.cjs +23 -5
  31. package/dist/tts/player.d.cts +6 -0
  32. package/dist/tts/player.d.ts +6 -0
  33. package/dist/tts/player.js +4 -3
  34. package/dist/tts/source.cjs +50 -4
  35. package/dist/tts/source.d.cts +16 -6
  36. package/dist/tts/source.d.ts +16 -6
  37. package/dist/tts/source.js +4 -2
  38. package/dist/tts/utils.cjs +18 -6
  39. package/dist/tts/utils.d.cts +7 -5
  40. package/dist/tts/utils.d.ts +7 -5
  41. package/dist/tts/utils.js +3 -2
  42. package/dist/tts/websocket.cjs +106 -33
  43. package/dist/tts/websocket.d.cts +20 -10
  44. package/dist/tts/websocket.d.ts +20 -10
  45. package/dist/tts/websocket.js +5 -5
  46. package/dist/types/index.d.cts +60 -4
  47. package/dist/types/index.d.ts +60 -4
  48. package/dist/voices/index.js +3 -3
  49. package/package.json +1 -1
  50. package/src/index.ts +2 -0
  51. package/src/react/index.ts +117 -62
  52. package/src/tts/player.ts +15 -8
  53. package/src/tts/source.ts +53 -7
  54. package/src/tts/utils.ts +26 -12
  55. package/src/tts/websocket.ts +42 -19
  56. package/src/types/index.ts +81 -3
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  Cartesia
3
- } from "../chunk-ISRU7PLL.js";
4
- import "../chunk-SGXUEFII.js";
3
+ } from "../chunk-OFH3ML4L.js";
4
+ import "../chunk-KUSVZXDT.js";
5
5
  import {
6
6
  pingServer
7
- } from "../chunk-3FL2SNIR.js";
8
- import "../chunk-VK7LBMVI.js";
9
- import "../chunk-IQAXBRHU.js";
10
- import "../chunk-PQ6CIPFW.js";
11
- import "../chunk-PQ5EVEEH.js";
7
+ } from "../chunk-NQVZNVOU.js";
8
+ import "../chunk-2NA5SEML.js";
9
+ import "../chunk-ASZKHN7Q.js";
10
+ import "../chunk-5M33ZF3Y.js";
12
11
  import "../chunk-2BFEKY3F.js";
13
12
  import {
14
13
  Player
15
- } from "../chunk-36JBKJUN.js";
16
- import "../chunk-RO7TY474.js";
14
+ } from "../chunk-LZO6K34D.js";
15
+ import "../chunk-BHY7MNGT.js";
16
+ import "../chunk-6YQ6KDIQ.js";
17
17
  import {
18
18
  __async
19
- } from "../chunk-WIFMLPT5.js";
19
+ } from "../chunk-GHY2WEOK.js";
20
20
 
21
21
  // src/react/index.ts
22
22
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -25,7 +25,8 @@ var DEFAULT_BUFFER_DURATION = 0.01;
25
25
  function useTTS({
26
26
  apiKey,
27
27
  baseUrl,
28
- sampleRate
28
+ sampleRate,
29
+ onError
29
30
  }) {
30
31
  var _a, _b;
31
32
  if (typeof window === "undefined") {
@@ -56,7 +57,11 @@ function useTTS({
56
57
  }
57
58
  const cartesia = new Cartesia({ apiKey, baseUrl });
58
59
  baseUrl = baseUrl != null ? baseUrl : cartesia.baseUrl;
59
- return cartesia.tts.websocket({ sampleRate });
60
+ return cartesia.tts.websocket({
61
+ container: "raw",
62
+ encoding: "pcm_f32le",
63
+ sampleRate
64
+ });
60
65
  }, [apiKey, baseUrl, sampleRate]);
61
66
  const websocketReturn = useRef(null);
62
67
  const player = useRef(null);
@@ -68,21 +73,34 @@ function useTTS({
68
73
  const [messages, setMessages] = useState([]);
69
74
  const buffer = useCallback(
70
75
  (options) => __async(this, null, function* () {
71
- var _a2;
72
- setMessages([]);
73
- setBufferStatus("buffering");
74
- websocketReturn.current = (_a2 = websocket == null ? void 0 : websocket.send(options)) != null ? _a2 : null;
75
- if (!websocketReturn.current) {
76
- return;
76
+ var _a2, _b2;
77
+ (_a2 = websocketReturn.current) == null ? void 0 : _a2.stop();
78
+ try {
79
+ setMessages([]);
80
+ setBufferStatus("buffering");
81
+ websocketReturn.current = (_b2 = websocket == null ? void 0 : websocket.send(options)) != null ? _b2 : null;
82
+ if (!websocketReturn.current) {
83
+ return;
84
+ }
85
+ const unsubscribe = websocketReturn.current.on("message", (message) => {
86
+ const parsedMessage = JSON.parse(message);
87
+ setMessages((messages2) => [...messages2, parsedMessage]);
88
+ if (parsedMessage.error) {
89
+ onError == null ? void 0 : onError(new Error(parsedMessage.error));
90
+ }
91
+ });
92
+ yield websocketReturn.current.source.once("close");
93
+ setBufferStatus("buffered");
94
+ unsubscribe();
95
+ } catch (error) {
96
+ if (error instanceof Error) {
97
+ onError == null ? void 0 : onError(error);
98
+ } else {
99
+ console.error(error);
100
+ }
77
101
  }
78
- const unsubscribe = websocketReturn.current.on("message", (message) => {
79
- setMessages((messages2) => [...messages2, JSON.parse(message)]);
80
- });
81
- yield websocketReturn.current.source.once("close");
82
- setBufferStatus("buffered");
83
- unsubscribe();
84
102
  }),
85
- [websocket]
103
+ [websocket, onError]
86
104
  );
87
105
  const metrics = useMemo(() => {
88
106
  var _a2;
@@ -151,53 +169,88 @@ function useTTS({
151
169
  return () => cleanup == null ? void 0 : cleanup();
152
170
  }, [websocket, baseUrl]);
153
171
  const play = useCallback(() => __async(this, null, function* () {
154
- if (playbackStatus === "playing" || !websocketReturn.current) {
155
- return;
156
- }
157
- setPlaybackStatus("playing");
158
- const unsubscribes = [];
159
- unsubscribes.push(
160
- websocketReturn.current.source.on("wait", () => {
161
- setIsWaiting(true);
162
- })
163
- );
164
- unsubscribes.push(
165
- websocketReturn.current.source.on("read", () => {
166
- setIsWaiting(false);
167
- })
168
- );
169
- player.current = new Player({
170
- bufferDuration: bufferDuration != null ? bufferDuration : DEFAULT_BUFFER_DURATION
171
- });
172
- yield player.current.play(websocketReturn.current.source);
173
- for (const unsubscribe of unsubscribes) {
174
- unsubscribe();
172
+ try {
173
+ if (playbackStatus === "playing" || !websocketReturn.current) {
174
+ return;
175
+ }
176
+ if (player.current) {
177
+ yield player.current.stop();
178
+ }
179
+ setPlaybackStatus("playing");
180
+ const unsubscribes = [];
181
+ unsubscribes.push(
182
+ websocketReturn.current.source.on("wait", () => {
183
+ setIsWaiting(true);
184
+ })
185
+ );
186
+ unsubscribes.push(
187
+ websocketReturn.current.source.on("read", () => {
188
+ setIsWaiting(false);
189
+ })
190
+ );
191
+ player.current = new Player({
192
+ bufferDuration: bufferDuration != null ? bufferDuration : DEFAULT_BUFFER_DURATION
193
+ });
194
+ yield player.current.play(websocketReturn.current.source);
195
+ for (const unsubscribe of unsubscribes) {
196
+ unsubscribe();
197
+ }
198
+ setPlaybackStatus("finished");
199
+ } catch (error) {
200
+ if (error instanceof Error) {
201
+ onError == null ? void 0 : onError(error);
202
+ } else {
203
+ console.error(error);
204
+ }
175
205
  }
176
- setPlaybackStatus("finished");
177
- }), [playbackStatus, bufferDuration]);
206
+ }), [playbackStatus, bufferDuration, onError]);
178
207
  const pause = useCallback(() => __async(this, null, function* () {
179
208
  var _a2;
180
- yield (_a2 = player.current) == null ? void 0 : _a2.pause();
181
- setPlaybackStatus("paused");
182
- }), []);
209
+ try {
210
+ yield (_a2 = player.current) == null ? void 0 : _a2.pause();
211
+ setPlaybackStatus("paused");
212
+ } catch (error) {
213
+ if (error instanceof Error) {
214
+ onError == null ? void 0 : onError(error);
215
+ } else {
216
+ console.error(error);
217
+ }
218
+ }
219
+ }), [onError]);
183
220
  const resume = useCallback(() => __async(this, null, function* () {
184
221
  var _a2;
185
- yield (_a2 = player.current) == null ? void 0 : _a2.resume();
186
- setPlaybackStatus("playing");
187
- }), []);
222
+ try {
223
+ yield (_a2 = player.current) == null ? void 0 : _a2.resume();
224
+ setPlaybackStatus("playing");
225
+ } catch (error) {
226
+ if (error instanceof Error) {
227
+ onError == null ? void 0 : onError(error);
228
+ } else {
229
+ console.error(error);
230
+ }
231
+ }
232
+ }), [onError]);
188
233
  const toggle = useCallback(() => __async(this, null, function* () {
189
234
  var _a2;
190
- yield (_a2 = player.current) == null ? void 0 : _a2.toggle();
191
- setPlaybackStatus((status) => {
192
- if (status === "playing") {
193
- return "paused";
194
- }
195
- if (status === "paused") {
196
- return "playing";
235
+ try {
236
+ yield (_a2 = player.current) == null ? void 0 : _a2.toggle();
237
+ setPlaybackStatus((status) => {
238
+ if (status === "playing") {
239
+ return "paused";
240
+ }
241
+ if (status === "paused") {
242
+ return "playing";
243
+ }
244
+ return status;
245
+ });
246
+ } catch (error) {
247
+ if (error instanceof Error) {
248
+ onError == null ? void 0 : onError(error);
249
+ } else {
250
+ console.error(error);
197
251
  }
198
- return status;
199
- });
200
- }), []);
252
+ }
253
+ }), [onError]);
201
254
  return {
202
255
  buffer,
203
256
  play,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  pingServer
3
- } from "../chunk-3FL2SNIR.js";
4
- import "../chunk-WIFMLPT5.js";
3
+ } from "../chunk-NQVZNVOU.js";
4
+ import "../chunk-GHY2WEOK.js";
5
5
  export {
6
6
  pingServer
7
7
  };
@@ -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 });
@@ -134,7 +146,13 @@ var import_partysocket = require("partysocket");
134
146
 
135
147
  // src/tts/source.ts
136
148
  var import_emittery = __toESM(require("emittery"), 1);
137
- var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate;
149
+ var ENCODING_MAP = {
150
+ pcm_f32le: { arrayType: Float32Array, bytesPerElement: 4 },
151
+ pcm_s16le: { arrayType: Int16Array, bytesPerElement: 2 },
152
+ pcm_alaw: { arrayType: Uint8Array, bytesPerElement: 1 },
153
+ pcm_mulaw: { arrayType: Uint8Array, bytesPerElement: 1 }
154
+ };
155
+ var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate, _encoding, _container, _createBuffer, createBuffer_fn;
138
156
  var Source = class {
139
157
  /**
140
158
  * Create a new Source.
@@ -142,23 +160,44 @@ var Source = class {
142
160
  * @param options - Options for the Source.
143
161
  * @param options.sampleRate - The sample rate of the audio.
144
162
  */
145
- constructor({ sampleRate }) {
163
+ constructor({
164
+ sampleRate,
165
+ encoding,
166
+ container
167
+ }) {
168
+ /**
169
+ * Create a new buffer for the source.
170
+ *
171
+ * @param size - The size of the buffer to create.
172
+ * @returns The new buffer as a TypedArray based on the encoding.
173
+ */
174
+ __privateAdd(this, _createBuffer);
146
175
  __privateAdd(this, _emitter, new import_emittery.default());
147
176
  __privateAdd(this, _buffer, void 0);
148
177
  __privateAdd(this, _readIndex, 0);
149
178
  __privateAdd(this, _writeIndex, 0);
150
179
  __privateAdd(this, _closed, false);
151
180
  __privateAdd(this, _sampleRate, void 0);
181
+ __privateAdd(this, _encoding, void 0);
182
+ __privateAdd(this, _container, void 0);
152
183
  this.on = __privateGet(this, _emitter).on.bind(__privateGet(this, _emitter));
153
184
  this.once = __privateGet(this, _emitter).once.bind(__privateGet(this, _emitter));
154
185
  this.events = __privateGet(this, _emitter).events.bind(__privateGet(this, _emitter));
155
186
  this.off = __privateGet(this, _emitter).off.bind(__privateGet(this, _emitter));
156
187
  __privateSet(this, _sampleRate, sampleRate);
157
- __privateSet(this, _buffer, new Float32Array(1024));
188
+ __privateSet(this, _encoding, encoding);
189
+ __privateSet(this, _container, container);
190
+ __privateSet(this, _buffer, __privateMethod(this, _createBuffer, createBuffer_fn).call(this, 1024));
158
191
  }
159
192
  get sampleRate() {
160
193
  return __privateGet(this, _sampleRate);
161
194
  }
195
+ get encoding() {
196
+ return __privateGet(this, _encoding);
197
+ }
198
+ get container() {
199
+ return __privateGet(this, _container);
200
+ }
162
201
  /**
163
202
  * Append audio to the buffer.
164
203
  *
@@ -172,7 +211,7 @@ var Source = class {
172
211
  while (newCapacity < requiredCapacity) {
173
212
  newCapacity *= 2;
174
213
  }
175
- const newBuffer = new Float32Array(newCapacity);
214
+ const newBuffer = __privateMethod(this, _createBuffer, createBuffer_fn).call(this, newCapacity);
176
215
  newBuffer.set(__privateGet(this, _buffer));
177
216
  __privateSet(this, _buffer, newBuffer);
178
217
  }
@@ -220,6 +259,9 @@ var Source = class {
220
259
  get readIndex() {
221
260
  return __privateGet(this, _readIndex);
222
261
  }
262
+ get writeIndex() {
263
+ return __privateGet(this, _writeIndex);
264
+ }
223
265
  /**
224
266
  * Close the source. This signals that no more audio will be enqueued.
225
267
  *
@@ -241,19 +283,27 @@ _readIndex = new WeakMap();
241
283
  _writeIndex = new WeakMap();
242
284
  _closed = new WeakMap();
243
285
  _sampleRate = new WeakMap();
286
+ _encoding = new WeakMap();
287
+ _container = new WeakMap();
288
+ _createBuffer = new WeakSet();
289
+ createBuffer_fn = function(size) {
290
+ const { arrayType: ArrayType } = ENCODING_MAP[__privateGet(this, _encoding)];
291
+ return new ArrayType(size);
292
+ };
244
293
 
245
294
  // src/tts/utils.ts
246
295
  var import_base64_js = __toESM(require("base64-js"), 1);
247
- function base64ToArray(b64) {
296
+ function base64ToArray(b64, encoding) {
248
297
  const byteArrays = filterSentinel(b64).map((b) => import_base64_js.default.toByteArray(b));
298
+ const { arrayType: ArrayType, bytesPerElement } = ENCODING_MAP[encoding];
249
299
  const totalLength = byteArrays.reduce(
250
- (acc, arr) => acc + arr.length / Float32Array.BYTES_PER_ELEMENT,
300
+ (acc, arr) => acc + arr.length / bytesPerElement,
251
301
  0
252
302
  );
253
- const result = new Float32Array(totalLength);
303
+ const result = new ArrayType(totalLength);
254
304
  let offset = 0;
255
305
  for (const arr of byteArrays) {
256
- const floats = new Float32Array(arr.buffer);
306
+ const floats = new ArrayType(arr.buffer);
257
307
  result.set(floats, offset);
258
308
  offset += floats.length;
259
309
  }
@@ -271,10 +321,10 @@ function createMessageHandlerForContextId(contextId, handler) {
271
321
  let chunk;
272
322
  if (message.done) {
273
323
  chunk = getSentinel();
274
- } else {
324
+ } else if (message.type === "chunk") {
275
325
  chunk = message.data;
276
326
  }
277
- handler({ chunk, message: event.data });
327
+ handler({ chunk, message: event.data, data: message });
278
328
  };
279
329
  }
280
330
  function getSentinel() {
@@ -298,14 +348,14 @@ function getEmitteryCallbacks(emitter) {
298
348
  }
299
349
 
300
350
  // src/tts/websocket.ts
301
- var _isConnected, _sampleRate2, _generateId, generateId_fn;
351
+ var _isConnected, _sampleRate2, _container2, _encoding2, _generateId, generateId_fn;
302
352
  var WebSocket = class extends Client {
303
353
  /**
304
354
  * Create a new WebSocket client.
305
355
  *
306
356
  * @param args - Arguments to pass to the Client constructor.
307
357
  */
308
- constructor({ sampleRate }, ...args) {
358
+ constructor({ sampleRate, container, encoding }, ...args) {
309
359
  super(...args);
310
360
  /**
311
361
  * Generate a unique ID suitable for a streaming context.
@@ -318,37 +368,47 @@ var WebSocket = class extends Client {
318
368
  __privateAdd(this, _generateId);
319
369
  __privateAdd(this, _isConnected, false);
320
370
  __privateAdd(this, _sampleRate2, void 0);
371
+ __privateAdd(this, _container2, void 0);
372
+ __privateAdd(this, _encoding2, void 0);
321
373
  __privateSet(this, _sampleRate2, sampleRate);
374
+ __privateSet(this, _container2, container != null ? container : "raw");
375
+ __privateSet(this, _encoding2, encoding != null ? encoding : "pcm_f32le");
322
376
  }
323
377
  /**
324
- * Send a message over the WebSocket in order to start a stream.
378
+ * Send a message over the WebSocket to start a stream.
325
379
  *
326
- * @param inputs - Stream options.
380
+ * @param inputs - Stream options. Defined in the StreamRequest type.
327
381
  * @param options - Options for the stream.
328
382
  * @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
329
- * If `0`, the stream will not time out.
383
+ * If set to `0`, the stream will not time out.
330
384
  * @returns A Source object that can be passed to a Player to play the audio.
385
+ * @returns An Emittery instance that emits messages from the WebSocket.
386
+ * @returns An abort function that can be called to cancel the stream.
331
387
  */
332
- send(inputs, { timeout = 0 } = {}) {
333
- var _a, _b, _c, _d;
388
+ send(_a, { timeout = 0 } = {}) {
389
+ var inputs = __objRest(_a, []);
390
+ var _a2, _b, _c, _d;
334
391
  if (!__privateGet(this, _isConnected)) {
335
392
  throw new Error("Not connected to WebSocket. Call .connect() first.");
336
393
  }
337
- const contextId = __privateMethod(this, _generateId, generateId_fn).call(this);
338
- (_a = this.socket) == null ? void 0 : _a.send(
339
- JSON.stringify(__spreadProps(__spreadValues({
340
- context_id: contextId
341
- }, inputs), {
342
- output_format: {
343
- container: "raw",
344
- encoding: "pcm_f32le",
345
- sample_rate: __privateGet(this, _sampleRate2)
346
- }
347
- }))
394
+ if (!inputs.context_id) {
395
+ inputs.context_id = __privateMethod(this, _generateId, generateId_fn).call(this);
396
+ }
397
+ if (!inputs.output_format) {
398
+ inputs.output_format = {
399
+ container: __privateGet(this, _container2),
400
+ encoding: __privateGet(this, _encoding2),
401
+ sample_rate: __privateGet(this, _sampleRate2)
402
+ };
403
+ }
404
+ (_a2 = this.socket) == null ? void 0 : _a2.send(
405
+ JSON.stringify(__spreadValues({}, inputs))
348
406
  );
349
407
  const emitter = new import_emittery2.default();
350
408
  const source = new Source({
351
- sampleRate: __privateGet(this, _sampleRate2)
409
+ sampleRate: __privateGet(this, _sampleRate2),
410
+ encoding: __privateGet(this, _encoding2),
411
+ container: __privateGet(this, _container2)
352
412
  });
353
413
  const streamCompleteController = new AbortController();
354
414
  let timeoutId = null;
@@ -356,19 +416,26 @@ var WebSocket = class extends Client {
356
416
  timeoutId = setTimeout(streamCompleteController.abort, timeout);
357
417
  }
358
418
  const handleMessage = createMessageHandlerForContextId(
359
- contextId,
360
- (_0) => __async(this, [_0], function* ({ chunk, message }) {
419
+ inputs.context_id,
420
+ (_0) => __async(this, [_0], function* ({ chunk, message, data }) {
361
421
  emitter.emit("message", message);
422
+ if (data.type === "timestamps") {
423
+ emitter.emit("timestamps", data.word_timestamps);
424
+ return;
425
+ }
362
426
  if (isSentinel(chunk)) {
363
427
  yield source.close();
364
428
  streamCompleteController.abort();
365
429
  return;
366
430
  }
367
- yield source.enqueue(base64ToArray([chunk]));
368
431
  if (timeoutId) {
369
432
  clearTimeout(timeoutId);
370
433
  timeoutId = setTimeout(streamCompleteController.abort, timeout);
371
434
  }
435
+ if (!chunk) {
436
+ return;
437
+ }
438
+ yield source.enqueue(base64ToArray([chunk], __privateGet(this, _encoding2)));
372
439
  })
373
440
  );
374
441
  (_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
@@ -398,7 +465,11 @@ var WebSocket = class extends Client {
398
465
  clearTimeout(timeoutId);
399
466
  }
400
467
  });
401
- return __spreadValues({ source }, getEmitteryCallbacks(emitter));
468
+ return __spreadProps(__spreadValues({
469
+ source
470
+ }, getEmitteryCallbacks(emitter)), {
471
+ stop: streamCompleteController.abort.bind(streamCompleteController)
472
+ });
402
473
  }
403
474
  /**
404
475
  * Authenticate and connect to a Cartesia streaming WebSocket.
@@ -468,6 +539,8 @@ var WebSocket = class extends Client {
468
539
  };
469
540
  _isConnected = new WeakMap();
470
541
  _sampleRate2 = new WeakMap();
542
+ _container2 = new WeakMap();
543
+ _encoding2 = new WeakMap();
471
544
  _generateId = new WeakSet();
472
545
  generateId_fn = function() {
473
546
  return (0, import_human_id.humanId)({
package/dist/tts/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  TTS
3
- } from "../chunk-VK7LBMVI.js";
4
- import "../chunk-IQAXBRHU.js";
5
- import "../chunk-PQ6CIPFW.js";
6
- import "../chunk-PQ5EVEEH.js";
3
+ } from "../chunk-2NA5SEML.js";
4
+ import "../chunk-ASZKHN7Q.js";
5
+ import "../chunk-5M33ZF3Y.js";
7
6
  import "../chunk-2BFEKY3F.js";
8
- import "../chunk-RO7TY474.js";
9
- import "../chunk-WIFMLPT5.js";
7
+ import "../chunk-BHY7MNGT.js";
8
+ import "../chunk-6YQ6KDIQ.js";
9
+ import "../chunk-GHY2WEOK.js";
10
10
  export {
11
11
  TTS as default
12
12
  };
@@ -75,10 +75,14 @@ __export(player_exports, {
75
75
  default: () => Player
76
76
  });
77
77
  module.exports = __toCommonJS(player_exports);
78
- var import_emittery = __toESM(require("emittery"), 1);
79
78
 
80
79
  // src/tts/utils.ts
81
80
  var import_base64_js = __toESM(require("base64-js"), 1);
81
+
82
+ // src/tts/source.ts
83
+ var import_emittery = __toESM(require("emittery"), 1);
84
+
85
+ // src/tts/utils.ts
82
86
  function playAudioBuffer(floats, context, startAt, sampleRate) {
83
87
  const source = context.createBufferSource();
84
88
  const buffer = context.createBuffer(1, floats.length, sampleRate);
@@ -94,7 +98,7 @@ function playAudioBuffer(floats, context, startAt, sampleRate) {
94
98
  }
95
99
 
96
100
  // src/tts/player.ts
97
- var _context, _startNextPlaybackAt, _bufferDuration, _emitter, _playBuffer, playBuffer_fn;
101
+ var _context, _startNextPlaybackAt, _bufferDuration, _playBuffer, playBuffer_fn;
98
102
  var Player = class {
99
103
  /**
100
104
  * Create a new Player.
@@ -107,7 +111,6 @@ var Player = class {
107
111
  __privateAdd(this, _context, null);
108
112
  __privateAdd(this, _startNextPlaybackAt, 0);
109
113
  __privateAdd(this, _bufferDuration, void 0);
110
- __privateAdd(this, _emitter, new import_emittery.default());
111
114
  __privateSet(this, _bufferDuration, bufferDuration);
112
115
  }
113
116
  /**
@@ -129,7 +132,6 @@ var Player = class {
129
132
  const playableAudio = buffer.subarray(0, read);
130
133
  plays.push(__privateMethod(this, _playBuffer, playBuffer_fn).call(this, playableAudio, source.sampleRate));
131
134
  if (read < buffer.length) {
132
- yield __privateGet(this, _emitter).emit("finish");
133
135
  break;
134
136
  }
135
137
  }
@@ -179,17 +181,33 @@ var Player = class {
179
181
  }
180
182
  });
181
183
  }
184
+ /**
185
+ * Stop the audio.
186
+ *
187
+ * @returns A promise that resolves when the audio has been stopped.
188
+ */
189
+ stop() {
190
+ return __async(this, null, function* () {
191
+ var _a;
192
+ if (!__privateGet(this, _context)) {
193
+ throw new Error("AudioContext not initialized.");
194
+ }
195
+ yield (_a = __privateGet(this, _context)) == null ? void 0 : _a.close();
196
+ });
197
+ }
182
198
  };
183
199
  _context = new WeakMap();
184
200
  _startNextPlaybackAt = new WeakMap();
185
201
  _bufferDuration = new WeakMap();
186
- _emitter = new WeakMap();
187
202
  _playBuffer = new WeakSet();
188
203
  playBuffer_fn = function(buf, sampleRate) {
189
204
  return __async(this, null, function* () {
190
205
  if (!__privateGet(this, _context)) {
191
206
  throw new Error("AudioContext not initialized.");
192
207
  }
208
+ if (buf.length === 0) {
209
+ return;
210
+ }
193
211
  const startAt = __privateGet(this, _startNextPlaybackAt);
194
212
  const duration = buf.length / sampleRate;
195
213
  __privateSet(this, _startNextPlaybackAt, duration + Math.max(__privateGet(this, _context).currentTime, __privateGet(this, _startNextPlaybackAt)));
@@ -38,6 +38,12 @@ declare class Player {
38
38
  * @returns A promise that resolves when the audio has been toggled.
39
39
  */
40
40
  toggle(): Promise<void>;
41
+ /**
42
+ * Stop the audio.
43
+ *
44
+ * @returns A promise that resolves when the audio has been stopped.
45
+ */
46
+ stop(): Promise<void>;
41
47
  }
42
48
 
43
49
  export { Player as default };
@@ -38,6 +38,12 @@ declare class Player {
38
38
  * @returns A promise that resolves when the audio has been toggled.
39
39
  */
40
40
  toggle(): Promise<void>;
41
+ /**
42
+ * Stop the audio.
43
+ *
44
+ * @returns A promise that resolves when the audio has been stopped.
45
+ */
46
+ stop(): Promise<void>;
41
47
  }
42
48
 
43
49
  export { Player as default };
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  Player
3
- } from "../chunk-36JBKJUN.js";
4
- import "../chunk-RO7TY474.js";
5
- import "../chunk-WIFMLPT5.js";
3
+ } from "../chunk-LZO6K34D.js";
4
+ import "../chunk-BHY7MNGT.js";
5
+ import "../chunk-6YQ6KDIQ.js";
6
+ import "../chunk-GHY2WEOK.js";
6
7
  export {
7
8
  Player as default
8
9
  };