@cartesia/cartesia-js 1.0.0-alpha.1 → 1.0.0-alpha.3

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 (44) hide show
  1. package/.turbo/turbo-build.log +26 -26
  2. package/CHANGELOG.md +12 -0
  3. package/dist/chunk-2BFEKY3F.js +16 -0
  4. package/dist/{chunk-WE63M7PJ.js → chunk-36JBKJUN.js} +2 -2
  5. package/dist/{chunk-NDNN326Q.js → chunk-IQAXBRHU.js} +9 -5
  6. package/dist/{chunk-X7SJMF2R.js → chunk-ISRU7PLL.js} +3 -3
  7. package/dist/{chunk-BCQ63627.js → chunk-PQ5EVEEH.js} +4 -2
  8. package/dist/{chunk-JOHSCOLW.js → chunk-PQ6CIPFW.js} +20 -6
  9. package/dist/{chunk-LYPTISWL.js → chunk-RO7TY474.js} +13 -7
  10. package/dist/{chunk-WBK6LLXX.js → chunk-SGXUEFII.js} +1 -1
  11. package/dist/{chunk-4RMSIQLG.js → chunk-VK7LBMVI.js} +2 -2
  12. package/dist/index.cjs +47 -25
  13. package/dist/index.js +9 -9
  14. package/dist/lib/client.cjs +9 -10
  15. package/dist/lib/client.js +2 -2
  16. package/dist/lib/constants.cjs +9 -9
  17. package/dist/lib/constants.d.cts +15 -3
  18. package/dist/lib/constants.d.ts +15 -3
  19. package/dist/lib/constants.js +3 -1
  20. package/dist/lib/index.cjs +46 -24
  21. package/dist/lib/index.js +8 -8
  22. package/dist/react/index.cjs +63 -33
  23. package/dist/react/index.js +25 -17
  24. package/dist/tts/index.cjs +46 -24
  25. package/dist/tts/index.js +6 -6
  26. package/dist/tts/player.cjs +1 -1
  27. package/dist/tts/player.js +2 -2
  28. package/dist/tts/source.cjs +20 -6
  29. package/dist/tts/source.js +1 -1
  30. package/dist/tts/utils.cjs +13 -7
  31. package/dist/tts/utils.js +1 -1
  32. package/dist/tts/websocket.cjs +46 -24
  33. package/dist/tts/websocket.js +5 -5
  34. package/dist/voices/index.cjs +9 -10
  35. package/dist/voices/index.js +3 -3
  36. package/package.json +1 -1
  37. package/src/lib/client.ts +3 -2
  38. package/src/lib/constants.ts +18 -9
  39. package/src/react/index.ts +20 -8
  40. package/src/tts/player.ts +2 -1
  41. package/src/tts/source.ts +22 -5
  42. package/src/tts/utils.ts +15 -7
  43. package/src/tts/websocket.ts +5 -2
  44. package/dist/chunk-3GBZUGUD.js +0 -17
@@ -97,16 +97,14 @@ module.exports = __toCommonJS(lib_exports);
97
97
  var import_cross_fetch = __toESM(require("cross-fetch"), 1);
98
98
 
99
99
  // src/lib/constants.ts
100
- var BASE_URL = "https://api.cartesia.ai/v0";
101
- var constructApiUrl = (baseUrl, path, protocol) => {
102
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
103
- if (!protocol) {
104
- return new URL(`${baseUrl}${normalizedPath}`);
100
+ var BASE_URL = "https://api.cartesia.ai";
101
+ var CARTESIA_VERSION = "2024-06-10";
102
+ var constructApiUrl = (baseUrl, path, { websocket = false } = {}) => {
103
+ const url = new URL(path, baseUrl);
104
+ if (websocket) {
105
+ url.protocol = baseUrl.replace(/^http/, "ws");
105
106
  }
106
- if (!["http", "ws"].includes(protocol)) {
107
- throw new Error(`Invalid protocol: ${protocol}`);
108
- }
109
- return new URL(`${baseUrl.replace(/^http/, protocol)}${normalizedPath}`);
107
+ return url;
110
108
  };
111
109
 
112
110
  // src/lib/client.ts
@@ -122,7 +120,8 @@ var Client = class {
122
120
  const url = constructApiUrl(this.baseUrl, path);
123
121
  return (0, import_cross_fetch.default)(url.toString(), __spreadProps(__spreadValues({}, options), {
124
122
  headers: __spreadValues({
125
- "X-API-KEY": this.apiKey
123
+ "X-API-Key": this.apiKey,
124
+ "Cartesia-Version": CARTESIA_VERSION
126
125
  }, options.headers)
127
126
  }));
128
127
  }
@@ -135,7 +134,7 @@ var import_partysocket = require("partysocket");
135
134
 
136
135
  // src/tts/source.ts
137
136
  var import_emittery = __toESM(require("emittery"), 1);
138
- var _emitter, _buffer, _readIndex, _closed, _sampleRate;
137
+ var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate;
139
138
  var Source = class {
140
139
  /**
141
140
  * Create a new Source.
@@ -145,8 +144,9 @@ var Source = class {
145
144
  */
146
145
  constructor({ sampleRate }) {
147
146
  __privateAdd(this, _emitter, new import_emittery.default());
148
- __privateAdd(this, _buffer, new Float32Array());
147
+ __privateAdd(this, _buffer, void 0);
149
148
  __privateAdd(this, _readIndex, 0);
149
+ __privateAdd(this, _writeIndex, 0);
150
150
  __privateAdd(this, _closed, false);
151
151
  __privateAdd(this, _sampleRate, void 0);
152
152
  this.on = __privateGet(this, _emitter).on.bind(__privateGet(this, _emitter));
@@ -154,6 +154,7 @@ var Source = class {
154
154
  this.events = __privateGet(this, _emitter).events.bind(__privateGet(this, _emitter));
155
155
  this.off = __privateGet(this, _emitter).off.bind(__privateGet(this, _emitter));
156
156
  __privateSet(this, _sampleRate, sampleRate);
157
+ __privateSet(this, _buffer, new Float32Array(1024));
157
158
  }
158
159
  get sampleRate() {
159
160
  return __privateGet(this, _sampleRate);
@@ -165,7 +166,18 @@ var Source = class {
165
166
  */
166
167
  enqueue(src) {
167
168
  return __async(this, null, function* () {
168
- __privateSet(this, _buffer, new Float32Array([...__privateGet(this, _buffer), ...src]));
169
+ const requiredCapacity = __privateGet(this, _writeIndex) + src.length;
170
+ if (requiredCapacity > __privateGet(this, _buffer).length) {
171
+ let newCapacity = __privateGet(this, _buffer).length;
172
+ while (newCapacity < requiredCapacity) {
173
+ newCapacity *= 2;
174
+ }
175
+ const newBuffer = new Float32Array(newCapacity);
176
+ newBuffer.set(__privateGet(this, _buffer));
177
+ __privateSet(this, _buffer, newBuffer);
178
+ }
179
+ __privateGet(this, _buffer).set(src, __privateGet(this, _writeIndex));
180
+ __privateSet(this, _writeIndex, __privateGet(this, _writeIndex) + src.length);
169
181
  yield __privateGet(this, _emitter).emit("enqueue");
170
182
  });
171
183
  }
@@ -179,7 +191,7 @@ var Source = class {
179
191
  read(dst) {
180
192
  return __async(this, null, function* () {
181
193
  const targetReadIndex = __privateGet(this, _readIndex) + dst.length;
182
- while (!__privateGet(this, _closed) && targetReadIndex > __privateGet(this, _buffer).length) {
194
+ while (!__privateGet(this, _closed) && targetReadIndex > __privateGet(this, _writeIndex)) {
183
195
  yield __privateGet(this, _emitter).emit("wait");
184
196
  yield Promise.race([
185
197
  __privateGet(this, _emitter).once("enqueue"),
@@ -187,8 +199,8 @@ var Source = class {
187
199
  ]);
188
200
  yield __privateGet(this, _emitter).emit("read");
189
201
  }
190
- const read = Math.min(dst.length, __privateGet(this, _buffer).length - __privateGet(this, _readIndex));
191
- dst.set(__privateGet(this, _buffer).slice(__privateGet(this, _readIndex), __privateGet(this, _readIndex) + read));
202
+ const read = Math.min(dst.length, __privateGet(this, _writeIndex) - __privateGet(this, _readIndex));
203
+ dst.set(__privateGet(this, _buffer).subarray(__privateGet(this, _readIndex), __privateGet(this, _readIndex) + read));
192
204
  __privateSet(this, _readIndex, __privateGet(this, _readIndex) + read);
193
205
  return read;
194
206
  });
@@ -226,19 +238,26 @@ var Source = class {
226
238
  _emitter = new WeakMap();
227
239
  _buffer = new WeakMap();
228
240
  _readIndex = new WeakMap();
241
+ _writeIndex = new WeakMap();
229
242
  _closed = new WeakMap();
230
243
  _sampleRate = new WeakMap();
231
244
 
232
245
  // src/tts/utils.ts
233
246
  var import_base64_js = __toESM(require("base64-js"), 1);
234
247
  function base64ToArray(b64) {
235
- return filterSentinel(b64).reduce((acc, b) => {
236
- const floats = new Float32Array(import_base64_js.default.toByteArray(b).buffer);
237
- const newAcc = new Float32Array(acc.length + floats.length);
238
- newAcc.set(acc, 0);
239
- newAcc.set(floats, acc.length);
240
- return newAcc;
241
- }, new Float32Array(0));
248
+ const byteArrays = filterSentinel(b64).map((b) => import_base64_js.default.toByteArray(b));
249
+ const totalLength = byteArrays.reduce(
250
+ (acc, arr) => acc + arr.length / Float32Array.BYTES_PER_ELEMENT,
251
+ 0
252
+ );
253
+ const result = new Float32Array(totalLength);
254
+ let offset = 0;
255
+ for (const arr of byteArrays) {
256
+ const floats = new Float32Array(arr.buffer);
257
+ result.set(floats, offset);
258
+ offset += floats.length;
259
+ }
260
+ return result;
242
261
  }
243
262
  function createMessageHandlerForContextId(contextId, handler) {
244
263
  return (event) => {
@@ -388,8 +407,11 @@ var WebSocket = class extends Client {
388
407
  * @throws {Error} If the WebSocket fails to connect.
389
408
  */
390
409
  connect() {
391
- const url = constructApiUrl(this.baseUrl, "/tts/websocket", "ws");
410
+ const url = constructApiUrl(this.baseUrl, "/tts/websocket", {
411
+ websocket: true
412
+ });
392
413
  url.searchParams.set("api_key", this.apiKey);
414
+ url.searchParams.set("cartesia_version", CARTESIA_VERSION);
393
415
  const emitter = new import_emittery2.default();
394
416
  this.socket = new import_partysocket.WebSocket(url.toString());
395
417
  this.socket.onopen = () => {
package/dist/lib/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  Cartesia
3
- } from "../chunk-X7SJMF2R.js";
4
- import "../chunk-WBK6LLXX.js";
5
- import "../chunk-4RMSIQLG.js";
6
- import "../chunk-NDNN326Q.js";
7
- import "../chunk-JOHSCOLW.js";
8
- import "../chunk-BCQ63627.js";
9
- import "../chunk-3GBZUGUD.js";
10
- import "../chunk-LYPTISWL.js";
3
+ } from "../chunk-ISRU7PLL.js";
4
+ import "../chunk-SGXUEFII.js";
5
+ import "../chunk-VK7LBMVI.js";
6
+ import "../chunk-IQAXBRHU.js";
7
+ import "../chunk-PQ6CIPFW.js";
8
+ import "../chunk-PQ5EVEEH.js";
9
+ import "../chunk-2BFEKY3F.js";
10
+ import "../chunk-RO7TY474.js";
11
11
  import "../chunk-WIFMLPT5.js";
12
12
  export {
13
13
  Cartesia
@@ -98,16 +98,14 @@ var import_react = require("react");
98
98
  var import_cross_fetch = __toESM(require("cross-fetch"), 1);
99
99
 
100
100
  // src/lib/constants.ts
101
- var BASE_URL = "https://api.cartesia.ai/v0";
102
- var constructApiUrl = (baseUrl, path, protocol) => {
103
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
104
- if (!protocol) {
105
- return new URL(`${baseUrl}${normalizedPath}`);
101
+ var BASE_URL = "https://api.cartesia.ai";
102
+ var CARTESIA_VERSION = "2024-06-10";
103
+ var constructApiUrl = (baseUrl, path, { websocket = false } = {}) => {
104
+ const url = new URL(path, baseUrl);
105
+ if (websocket) {
106
+ url.protocol = baseUrl.replace(/^http/, "ws");
106
107
  }
107
- if (!["http", "ws"].includes(protocol)) {
108
- throw new Error(`Invalid protocol: ${protocol}`);
109
- }
110
- return new URL(`${baseUrl.replace(/^http/, protocol)}${normalizedPath}`);
108
+ return url;
111
109
  };
112
110
 
113
111
  // src/lib/client.ts
@@ -123,7 +121,8 @@ var Client = class {
123
121
  const url = constructApiUrl(this.baseUrl, path);
124
122
  return (0, import_cross_fetch.default)(url.toString(), __spreadProps(__spreadValues({}, options), {
125
123
  headers: __spreadValues({
126
- "X-API-KEY": this.apiKey
124
+ "X-API-Key": this.apiKey,
125
+ "Cartesia-Version": CARTESIA_VERSION
127
126
  }, options.headers)
128
127
  }));
129
128
  }
@@ -136,7 +135,7 @@ var import_partysocket = require("partysocket");
136
135
 
137
136
  // src/tts/source.ts
138
137
  var import_emittery = __toESM(require("emittery"), 1);
139
- var _emitter, _buffer, _readIndex, _closed, _sampleRate;
138
+ var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate;
140
139
  var Source = class {
141
140
  /**
142
141
  * Create a new Source.
@@ -146,8 +145,9 @@ var Source = class {
146
145
  */
147
146
  constructor({ sampleRate }) {
148
147
  __privateAdd(this, _emitter, new import_emittery.default());
149
- __privateAdd(this, _buffer, new Float32Array());
148
+ __privateAdd(this, _buffer, void 0);
150
149
  __privateAdd(this, _readIndex, 0);
150
+ __privateAdd(this, _writeIndex, 0);
151
151
  __privateAdd(this, _closed, false);
152
152
  __privateAdd(this, _sampleRate, void 0);
153
153
  this.on = __privateGet(this, _emitter).on.bind(__privateGet(this, _emitter));
@@ -155,6 +155,7 @@ var Source = class {
155
155
  this.events = __privateGet(this, _emitter).events.bind(__privateGet(this, _emitter));
156
156
  this.off = __privateGet(this, _emitter).off.bind(__privateGet(this, _emitter));
157
157
  __privateSet(this, _sampleRate, sampleRate);
158
+ __privateSet(this, _buffer, new Float32Array(1024));
158
159
  }
159
160
  get sampleRate() {
160
161
  return __privateGet(this, _sampleRate);
@@ -166,7 +167,18 @@ var Source = class {
166
167
  */
167
168
  enqueue(src) {
168
169
  return __async(this, null, function* () {
169
- __privateSet(this, _buffer, new Float32Array([...__privateGet(this, _buffer), ...src]));
170
+ const requiredCapacity = __privateGet(this, _writeIndex) + src.length;
171
+ if (requiredCapacity > __privateGet(this, _buffer).length) {
172
+ let newCapacity = __privateGet(this, _buffer).length;
173
+ while (newCapacity < requiredCapacity) {
174
+ newCapacity *= 2;
175
+ }
176
+ const newBuffer = new Float32Array(newCapacity);
177
+ newBuffer.set(__privateGet(this, _buffer));
178
+ __privateSet(this, _buffer, newBuffer);
179
+ }
180
+ __privateGet(this, _buffer).set(src, __privateGet(this, _writeIndex));
181
+ __privateSet(this, _writeIndex, __privateGet(this, _writeIndex) + src.length);
170
182
  yield __privateGet(this, _emitter).emit("enqueue");
171
183
  });
172
184
  }
@@ -180,7 +192,7 @@ var Source = class {
180
192
  read(dst) {
181
193
  return __async(this, null, function* () {
182
194
  const targetReadIndex = __privateGet(this, _readIndex) + dst.length;
183
- while (!__privateGet(this, _closed) && targetReadIndex > __privateGet(this, _buffer).length) {
195
+ while (!__privateGet(this, _closed) && targetReadIndex > __privateGet(this, _writeIndex)) {
184
196
  yield __privateGet(this, _emitter).emit("wait");
185
197
  yield Promise.race([
186
198
  __privateGet(this, _emitter).once("enqueue"),
@@ -188,8 +200,8 @@ var Source = class {
188
200
  ]);
189
201
  yield __privateGet(this, _emitter).emit("read");
190
202
  }
191
- const read = Math.min(dst.length, __privateGet(this, _buffer).length - __privateGet(this, _readIndex));
192
- dst.set(__privateGet(this, _buffer).slice(__privateGet(this, _readIndex), __privateGet(this, _readIndex) + read));
203
+ const read = Math.min(dst.length, __privateGet(this, _writeIndex) - __privateGet(this, _readIndex));
204
+ dst.set(__privateGet(this, _buffer).subarray(__privateGet(this, _readIndex), __privateGet(this, _readIndex) + read));
193
205
  __privateSet(this, _readIndex, __privateGet(this, _readIndex) + read);
194
206
  return read;
195
207
  });
@@ -227,19 +239,26 @@ var Source = class {
227
239
  _emitter = new WeakMap();
228
240
  _buffer = new WeakMap();
229
241
  _readIndex = new WeakMap();
242
+ _writeIndex = new WeakMap();
230
243
  _closed = new WeakMap();
231
244
  _sampleRate = new WeakMap();
232
245
 
233
246
  // src/tts/utils.ts
234
247
  var import_base64_js = __toESM(require("base64-js"), 1);
235
248
  function base64ToArray(b64) {
236
- return filterSentinel(b64).reduce((acc, b) => {
237
- const floats = new Float32Array(import_base64_js.default.toByteArray(b).buffer);
238
- const newAcc = new Float32Array(acc.length + floats.length);
239
- newAcc.set(acc, 0);
240
- newAcc.set(floats, acc.length);
241
- return newAcc;
242
- }, new Float32Array(0));
249
+ const byteArrays = filterSentinel(b64).map((b) => import_base64_js.default.toByteArray(b));
250
+ const totalLength = byteArrays.reduce(
251
+ (acc, arr) => acc + arr.length / Float32Array.BYTES_PER_ELEMENT,
252
+ 0
253
+ );
254
+ const result = new Float32Array(totalLength);
255
+ let offset = 0;
256
+ for (const arr of byteArrays) {
257
+ const floats = new Float32Array(arr.buffer);
258
+ result.set(floats, offset);
259
+ offset += floats.length;
260
+ }
261
+ return result;
243
262
  }
244
263
  function playAudioBuffer(floats, context, startAt, sampleRate) {
245
264
  const source = context.createBufferSource();
@@ -402,8 +421,11 @@ var WebSocket = class extends Client {
402
421
  * @throws {Error} If the WebSocket fails to connect.
403
422
  */
404
423
  connect() {
405
- const url = constructApiUrl(this.baseUrl, "/tts/websocket", "ws");
424
+ const url = constructApiUrl(this.baseUrl, "/tts/websocket", {
425
+ websocket: true
426
+ });
406
427
  url.searchParams.set("api_key", this.apiKey);
428
+ url.searchParams.set("cartesia_version", CARTESIA_VERSION);
407
429
  const emitter = new import_emittery2.default();
408
430
  this.socket = new import_partysocket.WebSocket(url.toString());
409
431
  this.socket.onopen = () => {
@@ -574,7 +596,7 @@ var Player = class {
574
596
  const plays = [];
575
597
  while (true) {
576
598
  const read = yield source.read(buffer);
577
- const playableAudio = buffer.slice(0, read);
599
+ const playableAudio = buffer.subarray(0, read);
578
600
  plays.push(__privateMethod(this, _playBuffer, playBuffer_fn).call(this, playableAudio, source.sampleRate));
579
601
  if (read < buffer.length) {
580
602
  yield __privateGet(this, _emitter2).emit("finish");
@@ -711,11 +733,12 @@ function useTTS({
711
733
  if (!websocketReturn.current) {
712
734
  return;
713
735
  }
714
- websocketReturn.current.on("message", (message) => {
736
+ const unsubscribe = websocketReturn.current.on("message", (message) => {
715
737
  setMessages((messages2) => [...messages2, JSON.parse(message)]);
716
738
  });
717
739
  yield websocketReturn.current.source.once("close");
718
740
  setBufferStatus("buffered");
741
+ unsubscribe();
719
742
  }),
720
743
  [websocket]
721
744
  );
@@ -741,13 +764,18 @@ function useTTS({
741
764
  if (!connection) {
742
765
  return;
743
766
  }
767
+ const unsubscribes = [];
744
768
  setIsConnected(true);
745
- connection.on("open", () => {
746
- setIsConnected(true);
747
- });
748
- const unsubscribe = connection.on("close", () => {
749
- setIsConnected(false);
750
- });
769
+ unsubscribes.push(
770
+ connection.on("open", () => {
771
+ setIsConnected(true);
772
+ })
773
+ );
774
+ unsubscribes.push(
775
+ connection.on("close", () => {
776
+ setIsConnected(false);
777
+ })
778
+ );
751
779
  const intervalId = setInterval(() => {
752
780
  if (baseUrl) {
753
781
  pingServer(new URL(baseUrl).origin).then((ping) => {
@@ -764,7 +792,9 @@ function useTTS({
764
792
  }
765
793
  }, PING_INTERVAL);
766
794
  return () => {
767
- unsubscribe();
795
+ for (const unsubscribe of unsubscribes) {
796
+ unsubscribe();
797
+ }
768
798
  clearInterval(intervalId);
769
799
  websocket == null ? void 0 : websocket.disconnect();
770
800
  };
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  Cartesia
3
- } from "../chunk-X7SJMF2R.js";
4
- import "../chunk-WBK6LLXX.js";
3
+ } from "../chunk-ISRU7PLL.js";
4
+ import "../chunk-SGXUEFII.js";
5
5
  import {
6
6
  pingServer
7
7
  } from "../chunk-3FL2SNIR.js";
8
- import "../chunk-4RMSIQLG.js";
9
- import "../chunk-NDNN326Q.js";
10
- import "../chunk-JOHSCOLW.js";
11
- import "../chunk-BCQ63627.js";
12
- import "../chunk-3GBZUGUD.js";
8
+ import "../chunk-VK7LBMVI.js";
9
+ import "../chunk-IQAXBRHU.js";
10
+ import "../chunk-PQ6CIPFW.js";
11
+ import "../chunk-PQ5EVEEH.js";
12
+ import "../chunk-2BFEKY3F.js";
13
13
  import {
14
14
  Player
15
- } from "../chunk-WE63M7PJ.js";
16
- import "../chunk-LYPTISWL.js";
15
+ } from "../chunk-36JBKJUN.js";
16
+ import "../chunk-RO7TY474.js";
17
17
  import {
18
18
  __async
19
19
  } from "../chunk-WIFMLPT5.js";
@@ -75,11 +75,12 @@ function useTTS({
75
75
  if (!websocketReturn.current) {
76
76
  return;
77
77
  }
78
- websocketReturn.current.on("message", (message) => {
78
+ const unsubscribe = websocketReturn.current.on("message", (message) => {
79
79
  setMessages((messages2) => [...messages2, JSON.parse(message)]);
80
80
  });
81
81
  yield websocketReturn.current.source.once("close");
82
82
  setBufferStatus("buffered");
83
+ unsubscribe();
83
84
  }),
84
85
  [websocket]
85
86
  );
@@ -105,13 +106,18 @@ function useTTS({
105
106
  if (!connection) {
106
107
  return;
107
108
  }
109
+ const unsubscribes = [];
108
110
  setIsConnected(true);
109
- connection.on("open", () => {
110
- setIsConnected(true);
111
- });
112
- const unsubscribe = connection.on("close", () => {
113
- setIsConnected(false);
114
- });
111
+ unsubscribes.push(
112
+ connection.on("open", () => {
113
+ setIsConnected(true);
114
+ })
115
+ );
116
+ unsubscribes.push(
117
+ connection.on("close", () => {
118
+ setIsConnected(false);
119
+ })
120
+ );
115
121
  const intervalId = setInterval(() => {
116
122
  if (baseUrl) {
117
123
  pingServer(new URL(baseUrl).origin).then((ping) => {
@@ -128,7 +134,9 @@ function useTTS({
128
134
  }
129
135
  }, PING_INTERVAL);
130
136
  return () => {
131
- unsubscribe();
137
+ for (const unsubscribe of unsubscribes) {
138
+ unsubscribe();
139
+ }
132
140
  clearInterval(intervalId);
133
141
  websocket == null ? void 0 : websocket.disconnect();
134
142
  };
@@ -97,16 +97,14 @@ module.exports = __toCommonJS(tts_exports);
97
97
  var import_cross_fetch = __toESM(require("cross-fetch"), 1);
98
98
 
99
99
  // src/lib/constants.ts
100
- var BASE_URL = "https://api.cartesia.ai/v0";
101
- var constructApiUrl = (baseUrl, path, protocol) => {
102
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
103
- if (!protocol) {
104
- return new URL(`${baseUrl}${normalizedPath}`);
100
+ var BASE_URL = "https://api.cartesia.ai";
101
+ var CARTESIA_VERSION = "2024-06-10";
102
+ var constructApiUrl = (baseUrl, path, { websocket = false } = {}) => {
103
+ const url = new URL(path, baseUrl);
104
+ if (websocket) {
105
+ url.protocol = baseUrl.replace(/^http/, "ws");
105
106
  }
106
- if (!["http", "ws"].includes(protocol)) {
107
- throw new Error(`Invalid protocol: ${protocol}`);
108
- }
109
- return new URL(`${baseUrl.replace(/^http/, protocol)}${normalizedPath}`);
107
+ return url;
110
108
  };
111
109
 
112
110
  // src/lib/client.ts
@@ -122,7 +120,8 @@ var Client = class {
122
120
  const url = constructApiUrl(this.baseUrl, path);
123
121
  return (0, import_cross_fetch.default)(url.toString(), __spreadProps(__spreadValues({}, options), {
124
122
  headers: __spreadValues({
125
- "X-API-KEY": this.apiKey
123
+ "X-API-Key": this.apiKey,
124
+ "Cartesia-Version": CARTESIA_VERSION
126
125
  }, options.headers)
127
126
  }));
128
127
  }
@@ -135,7 +134,7 @@ var import_partysocket = require("partysocket");
135
134
 
136
135
  // src/tts/source.ts
137
136
  var import_emittery = __toESM(require("emittery"), 1);
138
- var _emitter, _buffer, _readIndex, _closed, _sampleRate;
137
+ var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate;
139
138
  var Source = class {
140
139
  /**
141
140
  * Create a new Source.
@@ -145,8 +144,9 @@ var Source = class {
145
144
  */
146
145
  constructor({ sampleRate }) {
147
146
  __privateAdd(this, _emitter, new import_emittery.default());
148
- __privateAdd(this, _buffer, new Float32Array());
147
+ __privateAdd(this, _buffer, void 0);
149
148
  __privateAdd(this, _readIndex, 0);
149
+ __privateAdd(this, _writeIndex, 0);
150
150
  __privateAdd(this, _closed, false);
151
151
  __privateAdd(this, _sampleRate, void 0);
152
152
  this.on = __privateGet(this, _emitter).on.bind(__privateGet(this, _emitter));
@@ -154,6 +154,7 @@ var Source = class {
154
154
  this.events = __privateGet(this, _emitter).events.bind(__privateGet(this, _emitter));
155
155
  this.off = __privateGet(this, _emitter).off.bind(__privateGet(this, _emitter));
156
156
  __privateSet(this, _sampleRate, sampleRate);
157
+ __privateSet(this, _buffer, new Float32Array(1024));
157
158
  }
158
159
  get sampleRate() {
159
160
  return __privateGet(this, _sampleRate);
@@ -165,7 +166,18 @@ var Source = class {
165
166
  */
166
167
  enqueue(src) {
167
168
  return __async(this, null, function* () {
168
- __privateSet(this, _buffer, new Float32Array([...__privateGet(this, _buffer), ...src]));
169
+ const requiredCapacity = __privateGet(this, _writeIndex) + src.length;
170
+ if (requiredCapacity > __privateGet(this, _buffer).length) {
171
+ let newCapacity = __privateGet(this, _buffer).length;
172
+ while (newCapacity < requiredCapacity) {
173
+ newCapacity *= 2;
174
+ }
175
+ const newBuffer = new Float32Array(newCapacity);
176
+ newBuffer.set(__privateGet(this, _buffer));
177
+ __privateSet(this, _buffer, newBuffer);
178
+ }
179
+ __privateGet(this, _buffer).set(src, __privateGet(this, _writeIndex));
180
+ __privateSet(this, _writeIndex, __privateGet(this, _writeIndex) + src.length);
169
181
  yield __privateGet(this, _emitter).emit("enqueue");
170
182
  });
171
183
  }
@@ -179,7 +191,7 @@ var Source = class {
179
191
  read(dst) {
180
192
  return __async(this, null, function* () {
181
193
  const targetReadIndex = __privateGet(this, _readIndex) + dst.length;
182
- while (!__privateGet(this, _closed) && targetReadIndex > __privateGet(this, _buffer).length) {
194
+ while (!__privateGet(this, _closed) && targetReadIndex > __privateGet(this, _writeIndex)) {
183
195
  yield __privateGet(this, _emitter).emit("wait");
184
196
  yield Promise.race([
185
197
  __privateGet(this, _emitter).once("enqueue"),
@@ -187,8 +199,8 @@ var Source = class {
187
199
  ]);
188
200
  yield __privateGet(this, _emitter).emit("read");
189
201
  }
190
- const read = Math.min(dst.length, __privateGet(this, _buffer).length - __privateGet(this, _readIndex));
191
- dst.set(__privateGet(this, _buffer).slice(__privateGet(this, _readIndex), __privateGet(this, _readIndex) + read));
202
+ const read = Math.min(dst.length, __privateGet(this, _writeIndex) - __privateGet(this, _readIndex));
203
+ dst.set(__privateGet(this, _buffer).subarray(__privateGet(this, _readIndex), __privateGet(this, _readIndex) + read));
192
204
  __privateSet(this, _readIndex, __privateGet(this, _readIndex) + read);
193
205
  return read;
194
206
  });
@@ -226,19 +238,26 @@ var Source = class {
226
238
  _emitter = new WeakMap();
227
239
  _buffer = new WeakMap();
228
240
  _readIndex = new WeakMap();
241
+ _writeIndex = new WeakMap();
229
242
  _closed = new WeakMap();
230
243
  _sampleRate = new WeakMap();
231
244
 
232
245
  // src/tts/utils.ts
233
246
  var import_base64_js = __toESM(require("base64-js"), 1);
234
247
  function base64ToArray(b64) {
235
- return filterSentinel(b64).reduce((acc, b) => {
236
- const floats = new Float32Array(import_base64_js.default.toByteArray(b).buffer);
237
- const newAcc = new Float32Array(acc.length + floats.length);
238
- newAcc.set(acc, 0);
239
- newAcc.set(floats, acc.length);
240
- return newAcc;
241
- }, new Float32Array(0));
248
+ const byteArrays = filterSentinel(b64).map((b) => import_base64_js.default.toByteArray(b));
249
+ const totalLength = byteArrays.reduce(
250
+ (acc, arr) => acc + arr.length / Float32Array.BYTES_PER_ELEMENT,
251
+ 0
252
+ );
253
+ const result = new Float32Array(totalLength);
254
+ let offset = 0;
255
+ for (const arr of byteArrays) {
256
+ const floats = new Float32Array(arr.buffer);
257
+ result.set(floats, offset);
258
+ offset += floats.length;
259
+ }
260
+ return result;
242
261
  }
243
262
  function createMessageHandlerForContextId(contextId, handler) {
244
263
  return (event) => {
@@ -388,8 +407,11 @@ var WebSocket = class extends Client {
388
407
  * @throws {Error} If the WebSocket fails to connect.
389
408
  */
390
409
  connect() {
391
- const url = constructApiUrl(this.baseUrl, "/tts/websocket", "ws");
410
+ const url = constructApiUrl(this.baseUrl, "/tts/websocket", {
411
+ websocket: true
412
+ });
392
413
  url.searchParams.set("api_key", this.apiKey);
414
+ url.searchParams.set("cartesia_version", CARTESIA_VERSION);
393
415
  const emitter = new import_emittery2.default();
394
416
  this.socket = new import_partysocket.WebSocket(url.toString());
395
417
  this.socket.onopen = () => {
package/dist/tts/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  TTS
3
- } from "../chunk-4RMSIQLG.js";
4
- import "../chunk-NDNN326Q.js";
5
- import "../chunk-JOHSCOLW.js";
6
- import "../chunk-BCQ63627.js";
7
- import "../chunk-3GBZUGUD.js";
8
- import "../chunk-LYPTISWL.js";
3
+ } from "../chunk-VK7LBMVI.js";
4
+ import "../chunk-IQAXBRHU.js";
5
+ import "../chunk-PQ6CIPFW.js";
6
+ import "../chunk-PQ5EVEEH.js";
7
+ import "../chunk-2BFEKY3F.js";
8
+ import "../chunk-RO7TY474.js";
9
9
  import "../chunk-WIFMLPT5.js";
10
10
  export {
11
11
  TTS as default
@@ -126,7 +126,7 @@ var Player = class {
126
126
  const plays = [];
127
127
  while (true) {
128
128
  const read = yield source.read(buffer);
129
- const playableAudio = buffer.slice(0, read);
129
+ const playableAudio = buffer.subarray(0, read);
130
130
  plays.push(__privateMethod(this, _playBuffer, playBuffer_fn).call(this, playableAudio, source.sampleRate));
131
131
  if (read < buffer.length) {
132
132
  yield __privateGet(this, _emitter).emit("finish");
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Player
3
- } from "../chunk-WE63M7PJ.js";
4
- import "../chunk-LYPTISWL.js";
3
+ } from "../chunk-36JBKJUN.js";
4
+ import "../chunk-RO7TY474.js";
5
5
  import "../chunk-WIFMLPT5.js";
6
6
  export {
7
7
  Player as default