@cartesia/cartesia-js 0.0.4-alpha.0 → 1.0.0-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.
Files changed (87) hide show
  1. package/.turbo/turbo-build.log +64 -46
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +123 -16
  4. package/dist/{chunk-XPIMIAAE.js → chunk-3FL2SNIR.js} +1 -1
  5. package/dist/chunk-3GBZUGUD.js +17 -0
  6. package/dist/chunk-4RMSIQLG.js +25 -0
  7. package/dist/chunk-BCQ63627.js +32 -0
  8. package/dist/chunk-JOHSCOLW.js +106 -0
  9. package/dist/chunk-LYPTISWL.js +75 -0
  10. package/dist/chunk-NDNN326Q.js +207 -0
  11. package/dist/chunk-WBK6LLXX.js +58 -0
  12. package/dist/chunk-WE63M7PJ.js +119 -0
  13. package/dist/{chunk-R4P7LWVZ.js → chunk-WIFMLPT5.js} +31 -6
  14. package/dist/chunk-X7SJMF2R.js +22 -0
  15. package/dist/index.cjs +391 -158
  16. package/dist/index.d.cts +7 -3
  17. package/dist/index.d.ts +7 -3
  18. package/dist/index.js +13 -6
  19. package/dist/lib/client.cjs +46 -0
  20. package/dist/lib/client.d.cts +2 -0
  21. package/dist/lib/client.d.ts +2 -0
  22. package/dist/lib/client.js +3 -3
  23. package/dist/lib/constants.cjs +11 -7
  24. package/dist/lib/constants.d.cts +2 -3
  25. package/dist/lib/constants.d.ts +2 -3
  26. package/dist/lib/constants.js +4 -6
  27. package/dist/lib/index.cjs +276 -163
  28. package/dist/lib/index.d.cts +6 -2
  29. package/dist/lib/index.d.ts +6 -2
  30. package/dist/lib/index.js +9 -6
  31. package/dist/react/index.cjs +524 -275
  32. package/dist/react/index.d.cts +20 -14
  33. package/dist/react/index.d.ts +20 -14
  34. package/dist/react/index.js +142 -98
  35. package/dist/react/utils.js +2 -2
  36. package/dist/tts/index.cjs +470 -0
  37. package/dist/tts/index.d.cts +17 -0
  38. package/dist/tts/index.d.ts +17 -0
  39. package/dist/tts/index.js +12 -0
  40. package/dist/tts/player.cjs +198 -0
  41. package/dist/tts/player.d.cts +43 -0
  42. package/dist/tts/player.d.ts +43 -0
  43. package/dist/tts/player.js +8 -0
  44. package/dist/tts/source.cjs +167 -0
  45. package/dist/tts/source.d.cts +53 -0
  46. package/dist/tts/source.d.ts +53 -0
  47. package/dist/tts/source.js +7 -0
  48. package/dist/{audio → tts}/utils.cjs +12 -53
  49. package/dist/tts/utils.d.cts +67 -0
  50. package/dist/tts/utils.d.ts +67 -0
  51. package/dist/{audio → tts}/utils.js +2 -7
  52. package/dist/{audio/index.cjs → tts/websocket.cjs} +213 -164
  53. package/dist/tts/websocket.d.cts +53 -0
  54. package/dist/tts/websocket.d.ts +53 -0
  55. package/dist/tts/websocket.js +11 -0
  56. package/dist/types/index.d.cts +50 -1
  57. package/dist/types/index.d.ts +50 -1
  58. package/dist/voices/index.cjs +155 -0
  59. package/dist/voices/index.d.cts +12 -0
  60. package/dist/voices/index.d.ts +12 -0
  61. package/dist/voices/index.js +9 -0
  62. package/package.json +2 -1
  63. package/src/index.ts +1 -0
  64. package/src/lib/client.ts +14 -1
  65. package/src/lib/constants.ts +13 -3
  66. package/src/lib/index.ts +6 -3
  67. package/src/react/index.ts +157 -103
  68. package/src/tts/index.ts +17 -0
  69. package/src/tts/player.ts +109 -0
  70. package/src/tts/source.ts +98 -0
  71. package/src/{audio → tts}/utils.ts +19 -97
  72. package/src/tts/websocket.ts +210 -0
  73. package/src/types/index.ts +63 -0
  74. package/src/voices/index.ts +47 -0
  75. package/dist/audio/index.d.cts +0 -5
  76. package/dist/audio/index.d.ts +0 -5
  77. package/dist/audio/index.js +0 -10
  78. package/dist/audio/utils.d.cts +0 -5
  79. package/dist/audio/utils.d.ts +0 -5
  80. package/dist/chunk-4MHF74A7.js +0 -272
  81. package/dist/chunk-5TSWLYOW.js +0 -113
  82. package/dist/chunk-MJIFZWHS.js +0 -18
  83. package/dist/chunk-OVI3W3GG.js +0 -12
  84. package/dist/chunk-S6A27RQL.js +0 -18
  85. package/dist/index-C2_3XFxn.d.cts +0 -163
  86. package/dist/index-DgwnZezj.d.ts +0 -163
  87. package/src/audio/index.ts +0 -297
@@ -1,15 +1,14 @@
1
1
  "use strict";
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
8
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
9
  var __getProtoOf = Object.getPrototypeOf;
8
10
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
11
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
- var __knownSymbol = (name, symbol) => {
11
- return (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
12
- };
13
12
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
13
  var __spreadValues = (a, b) => {
15
14
  for (var prop in b || (b = {}))
@@ -22,6 +21,7 @@ var __spreadValues = (a, b) => {
22
21
  }
23
22
  return a;
24
23
  };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
25
  var __export = (target, all) => {
26
26
  for (var name in all)
27
27
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -43,6 +43,28 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
43
43
  mod
44
44
  ));
45
45
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
+ var __accessCheck = (obj, member, msg) => {
47
+ if (!member.has(obj))
48
+ throw TypeError("Cannot " + msg);
49
+ };
50
+ var __privateGet = (obj, member, getter) => {
51
+ __accessCheck(obj, member, "read from private field");
52
+ return getter ? getter.call(obj) : member.get(obj);
53
+ };
54
+ var __privateAdd = (obj, member, value) => {
55
+ if (member.has(obj))
56
+ throw TypeError("Cannot add the same private member more than once");
57
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
58
+ };
59
+ var __privateSet = (obj, member, value, setter) => {
60
+ __accessCheck(obj, member, "write to private field");
61
+ setter ? setter.call(obj, value) : member.set(obj, value);
62
+ return value;
63
+ };
64
+ var __privateMethod = (obj, member, method) => {
65
+ __accessCheck(obj, member, "access private method");
66
+ return method;
67
+ };
46
68
  var __async = (__this, __arguments, generator) => {
47
69
  return new Promise((resolve, reject) => {
48
70
  var fulfilled = (value) => {
@@ -63,7 +85,6 @@ var __async = (__this, __arguments, generator) => {
63
85
  step((generator = generator.apply(__this, __arguments)).next());
64
86
  });
65
87
  };
66
- var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
67
88
 
68
89
  // src/lib/index.ts
69
90
  var lib_exports = {};
@@ -72,16 +93,20 @@ __export(lib_exports, {
72
93
  });
73
94
  module.exports = __toCommonJS(lib_exports);
74
95
 
75
- // src/audio/index.ts
76
- var import_emittery = __toESM(require("emittery"), 1);
77
- var import_human_id = require("human-id");
78
- var import_partysocket = require("partysocket");
96
+ // src/lib/client.ts
97
+ var import_cross_fetch = __toESM(require("cross-fetch"), 1);
79
98
 
80
99
  // src/lib/constants.ts
81
100
  var BASE_URL = "https://api.cartesia.ai/v0";
82
- var SAMPLE_RATE = 44100;
83
- var constructWebsocketUrl = (baseUrl) => {
84
- return new URL(`${baseUrl.replace(/^http/, "ws")}/audio/websocket`);
101
+ var constructApiUrl = (baseUrl, path, protocol) => {
102
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
103
+ if (!protocol) {
104
+ return new URL(`${baseUrl}${normalizedPath}`);
105
+ }
106
+ if (!["http", "ws"].includes(protocol)) {
107
+ throw new Error(`Invalid protocol: ${protocol}`);
108
+ }
109
+ return new URL(`${baseUrl.replace(/^http/, protocol)}${normalizedPath}`);
85
110
  };
86
111
 
87
112
  // src/lib/client.ts
@@ -93,14 +118,119 @@ var Client = class {
93
118
  this.apiKey = options.apiKey || process.env.CARTESIA_API_KEY;
94
119
  this.baseUrl = options.baseUrl || BASE_URL;
95
120
  }
121
+ fetch(path, options = {}) {
122
+ const url = constructApiUrl(this.baseUrl, path);
123
+ return (0, import_cross_fetch.default)(url.toString(), __spreadProps(__spreadValues({}, options), {
124
+ headers: __spreadValues({
125
+ "X-API-KEY": this.apiKey
126
+ }, options.headers)
127
+ }));
128
+ }
129
+ };
130
+
131
+ // src/tts/websocket.ts
132
+ var import_emittery2 = __toESM(require("emittery"), 1);
133
+ var import_human_id = require("human-id");
134
+ var import_partysocket = require("partysocket");
135
+
136
+ // src/tts/source.ts
137
+ var import_emittery = __toESM(require("emittery"), 1);
138
+ var _emitter, _buffer, _readIndex, _closed, _sampleRate;
139
+ var Source = class {
140
+ /**
141
+ * Create a new Source.
142
+ *
143
+ * @param options - Options for the Source.
144
+ * @param options.sampleRate - The sample rate of the audio.
145
+ */
146
+ constructor({ sampleRate }) {
147
+ __privateAdd(this, _emitter, new import_emittery.default());
148
+ __privateAdd(this, _buffer, new Float32Array());
149
+ __privateAdd(this, _readIndex, 0);
150
+ __privateAdd(this, _closed, false);
151
+ __privateAdd(this, _sampleRate, void 0);
152
+ this.on = __privateGet(this, _emitter).on.bind(__privateGet(this, _emitter));
153
+ this.once = __privateGet(this, _emitter).once.bind(__privateGet(this, _emitter));
154
+ this.events = __privateGet(this, _emitter).events.bind(__privateGet(this, _emitter));
155
+ this.off = __privateGet(this, _emitter).off.bind(__privateGet(this, _emitter));
156
+ __privateSet(this, _sampleRate, sampleRate);
157
+ }
158
+ get sampleRate() {
159
+ return __privateGet(this, _sampleRate);
160
+ }
161
+ /**
162
+ * Append audio to the buffer.
163
+ *
164
+ * @param src The audio to append.
165
+ */
166
+ enqueue(src) {
167
+ return __async(this, null, function* () {
168
+ __privateSet(this, _buffer, new Float32Array([...__privateGet(this, _buffer), ...src]));
169
+ yield __privateGet(this, _emitter).emit("enqueue");
170
+ });
171
+ }
172
+ /**
173
+ * Read audio from the buffer.
174
+ *
175
+ * @param dst The buffer to read the audio into.
176
+ * @returns The number of samples read. If the source is closed, this will be
177
+ * less than the length of the provided buffer.
178
+ */
179
+ read(dst) {
180
+ return __async(this, null, function* () {
181
+ const targetReadIndex = __privateGet(this, _readIndex) + dst.length;
182
+ while (!__privateGet(this, _closed) && targetReadIndex > __privateGet(this, _buffer).length) {
183
+ yield __privateGet(this, _emitter).emit("wait");
184
+ yield Promise.race([
185
+ __privateGet(this, _emitter).once("enqueue"),
186
+ __privateGet(this, _emitter).once("close")
187
+ ]);
188
+ yield __privateGet(this, _emitter).emit("read");
189
+ }
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));
192
+ __privateSet(this, _readIndex, __privateGet(this, _readIndex) + read);
193
+ return read;
194
+ });
195
+ }
196
+ /**
197
+ * Get the number of samples in a given duration.
198
+ *
199
+ * @param durationSecs The duration in seconds.
200
+ * @returns The number of samples.
201
+ */
202
+ durationToSampleCount(durationSecs) {
203
+ return Math.trunc(durationSecs * __privateGet(this, _sampleRate));
204
+ }
205
+ get buffer() {
206
+ return __privateGet(this, _buffer);
207
+ }
208
+ get readIndex() {
209
+ return __privateGet(this, _readIndex);
210
+ }
211
+ /**
212
+ * Close the source. This signals that no more audio will be enqueued.
213
+ *
214
+ * This will emit a "close" event.
215
+ *
216
+ * @returns A promise that resolves when the source is closed.
217
+ */
218
+ close() {
219
+ return __async(this, null, function* () {
220
+ __privateSet(this, _closed, true);
221
+ yield __privateGet(this, _emitter).emit("close");
222
+ __privateGet(this, _emitter).clearListeners();
223
+ });
224
+ }
96
225
  };
226
+ _emitter = new WeakMap();
227
+ _buffer = new WeakMap();
228
+ _readIndex = new WeakMap();
229
+ _closed = new WeakMap();
230
+ _sampleRate = new WeakMap();
97
231
 
98
- // src/audio/utils.ts
232
+ // src/tts/utils.ts
99
233
  var import_base64_js = __toESM(require("base64-js"), 1);
100
- function getBufferDuration(b64) {
101
- const floats = base64ToArray(b64);
102
- return floats.length / SAMPLE_RATE;
103
- }
104
234
  function base64ToArray(b64) {
105
235
  return filterSentinel(b64).reduce((acc, b) => {
106
236
  const floats = new Float32Array(import_base64_js.default.toByteArray(b).buffer);
@@ -110,20 +240,11 @@ function base64ToArray(b64) {
110
240
  return newAcc;
111
241
  }, new Float32Array(0));
112
242
  }
113
- function playAudioBuffer(b64, context, maybeStartAt = null, onEnded = null) {
114
- const startAt = maybeStartAt != null ? maybeStartAt : context.currentTime;
115
- const floats = base64ToArray(b64);
116
- const source = context.createBufferSource();
117
- const buffer = context.createBuffer(1, floats.length, SAMPLE_RATE);
118
- buffer.getChannelData(0).set(floats);
119
- source.buffer = buffer;
120
- source.connect(context.destination);
121
- source.start(startAt);
122
- source.onended = onEnded;
123
- return buffer.duration;
124
- }
125
243
  function createMessageHandlerForContextId(contextId, handler) {
126
244
  return (event) => {
245
+ if (typeof event.data !== "string") {
246
+ return;
247
+ }
127
248
  const message = JSON.parse(event.data);
128
249
  if (message.context_id !== contextId) {
129
250
  return;
@@ -134,7 +255,7 @@ function createMessageHandlerForContextId(contextId, handler) {
134
255
  } else {
135
256
  chunk = message.data;
136
257
  }
137
- handler({ chunk, message });
258
+ handler({ chunk, message: event.data });
138
259
  };
139
260
  }
140
261
  function getSentinel() {
@@ -148,9 +269,6 @@ function filterSentinel(collection) {
148
269
  (x) => !isSentinel(x)
149
270
  );
150
271
  }
151
- function isComplete(chunks) {
152
- return isSentinel(chunks[chunks.length - 1]);
153
- }
154
272
  function getEmitteryCallbacks(emitter) {
155
273
  return {
156
274
  on: emitter.on.bind(emitter),
@@ -160,58 +278,75 @@ function getEmitteryCallbacks(emitter) {
160
278
  };
161
279
  }
162
280
 
163
- // src/audio/index.ts
164
- var audio_default = class extends Client {
165
- constructor() {
166
- super(...arguments);
167
- this.isConnected = false;
281
+ // src/tts/websocket.ts
282
+ var _isConnected, _sampleRate2, _generateId, generateId_fn;
283
+ var WebSocket = class extends Client {
284
+ /**
285
+ * Create a new WebSocket client.
286
+ *
287
+ * @param args - Arguments to pass to the Client constructor.
288
+ */
289
+ constructor({ sampleRate }, ...args) {
290
+ super(...args);
291
+ /**
292
+ * Generate a unique ID suitable for a streaming context.
293
+ *
294
+ * Not suitable for security purposes or as a primary key, since
295
+ * it lacks the amount of entropy required for those use cases.
296
+ *
297
+ * @returns A unique ID.
298
+ */
299
+ __privateAdd(this, _generateId);
300
+ __privateAdd(this, _isConnected, false);
301
+ __privateAdd(this, _sampleRate2, void 0);
302
+ __privateSet(this, _sampleRate2, sampleRate);
168
303
  }
169
304
  /**
170
- * Stream audio from a model.
305
+ * Send a message over the WebSocket in order to start a stream.
171
306
  *
172
- * @param inputs - Stream options. Includes a `model` key and some `parameters`, which
173
- * are model-specific and can be found in the model's documentation.
307
+ * @param inputs - Stream options.
174
308
  * @param options - Options for the stream.
175
309
  * @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
176
310
  * If `0`, the stream will not time out.
177
- * @returns An object with a method `play` of type `(bufferDuration: number) => Promise<void>`
178
- * that plays the audio as it arrives, with `bufferDuration` seconds of audio buffered before
179
- * starting playback.
311
+ * @returns A Source object that can be passed to a Player to play the audio.
180
312
  */
181
- stream(inputs, { timeout = 0 } = {}) {
313
+ send(inputs, { timeout = 0 } = {}) {
182
314
  var _a, _b, _c, _d;
183
- if (!this.isConnected) {
315
+ if (!__privateGet(this, _isConnected)) {
184
316
  throw new Error("Not connected to WebSocket. Call .connect() first.");
185
317
  }
186
- const contextId = this.generateId();
318
+ const contextId = __privateMethod(this, _generateId, generateId_fn).call(this);
187
319
  (_a = this.socket) == null ? void 0 : _a.send(
188
- JSON.stringify({
189
- data: inputs,
320
+ JSON.stringify(__spreadProps(__spreadValues({
190
321
  context_id: contextId
191
- })
322
+ }, inputs), {
323
+ output_format: {
324
+ container: "raw",
325
+ encoding: "pcm_f32le",
326
+ sample_rate: __privateGet(this, _sampleRate2)
327
+ }
328
+ }))
192
329
  );
330
+ const emitter = new import_emittery2.default();
331
+ const source = new Source({
332
+ sampleRate: __privateGet(this, _sampleRate2)
333
+ });
193
334
  const streamCompleteController = new AbortController();
194
335
  let timeoutId = null;
195
336
  if (timeout > 0) {
196
337
  timeoutId = setTimeout(streamCompleteController.abort, timeout);
197
338
  }
198
- const chunks = [];
199
- const emitter = new import_emittery.default();
200
339
  const handleMessage = createMessageHandlerForContextId(
201
340
  contextId,
202
341
  (_0) => __async(this, [_0], function* ({ chunk, message }) {
203
- chunks.push(chunk);
204
- yield emitter.emit("chunk", {
205
- chunk,
206
- chunks
207
- });
208
- yield emitter.emit("message", message);
342
+ emitter.emit("message", message);
209
343
  if (isSentinel(chunk)) {
210
- yield emitter.emit("streamed", {
211
- chunks
212
- });
344
+ yield source.close();
213
345
  streamCompleteController.abort();
214
- } else if (timeoutId) {
346
+ return;
347
+ }
348
+ yield source.enqueue(base64ToArray([chunk]));
349
+ if (timeoutId) {
215
350
  clearTimeout(timeoutId);
216
351
  timeoutId = setTimeout(streamCompleteController.abort, timeout);
217
352
  }
@@ -239,107 +374,12 @@ var audio_default = class extends Client {
239
374
  }
240
375
  );
241
376
  streamCompleteController.signal.addEventListener("abort", () => {
377
+ source.close();
242
378
  if (timeoutId) {
243
379
  clearTimeout(timeoutId);
244
380
  }
245
- emitter.clearListeners();
246
- });
247
- const play = (_0) => __async(this, [_0], function* ({ bufferDuration }) {
248
- const context = new AudioContext({
249
- sampleRate: SAMPLE_RATE
250
- });
251
- let startNextPlaybackAt = 0;
252
- const playLatestChunk = (chunk) => {
253
- if (isSentinel(chunk)) {
254
- return true;
255
- }
256
- startNextPlaybackAt = playAudioBuffer([chunk], context, startNextPlaybackAt) + Math.max(context.currentTime, startNextPlaybackAt);
257
- return false;
258
- };
259
- const playChunks = (chunks2) => {
260
- startNextPlaybackAt += playAudioBuffer(
261
- chunks2,
262
- context,
263
- startNextPlaybackAt
264
- );
265
- if (isComplete(chunks2)) {
266
- return;
267
- }
268
- };
269
- const tryStart = (chunks2) => __async(this, null, function* () {
270
- startNextPlaybackAt = context.currentTime;
271
- if (isComplete(chunks2) || streamCompleteController.signal.aborted) {
272
- emitter.emit("buffered");
273
- playChunks(chunks2);
274
- return true;
275
- }
276
- if (getBufferDuration(chunks2) > bufferDuration) {
277
- emitter.emit("buffered");
278
- playChunks(chunks2);
279
- try {
280
- for (var iter2 = __forAwait(emitter.events("chunk")), more2, temp2, error2; more2 = !(temp2 = yield iter2.next()).done; more2 = false) {
281
- const { chunk } = temp2.value;
282
- if (playLatestChunk(chunk)) {
283
- break;
284
- }
285
- }
286
- } catch (temp2) {
287
- error2 = [temp2];
288
- } finally {
289
- try {
290
- more2 && (temp2 = iter2.return) && (yield temp2.call(iter2));
291
- } finally {
292
- if (error2)
293
- throw error2[0];
294
- }
295
- }
296
- return true;
297
- }
298
- emitter.emit("buffering");
299
- return false;
300
- });
301
- if (!(yield tryStart(chunks))) {
302
- try {
303
- for (var iter = __forAwait(emitter.events("chunk")), more, temp, error; more = !(temp = yield iter.next()).done; more = false) {
304
- const { chunks: chunks2 } = temp.value;
305
- if (yield tryStart(chunks2)) {
306
- const playbackEndsIn = Math.max(0, startNextPlaybackAt - context.currentTime) * 1e3;
307
- emitter.emit("scheduled", { playbackEndsIn });
308
- break;
309
- }
310
- }
311
- } catch (temp) {
312
- error = [temp];
313
- } finally {
314
- try {
315
- more && (temp = iter.return) && (yield temp.call(iter));
316
- } finally {
317
- if (error)
318
- throw error[0];
319
- }
320
- }
321
- } else {
322
- const playbackEndsIn = Math.max(0, startNextPlaybackAt - context.currentTime) * 1e3;
323
- emitter.emit("scheduled", { playbackEndsIn });
324
- }
325
- });
326
- return __spreadValues({
327
- play
328
- }, getEmitteryCallbacks(emitter));
329
- }
330
- /**
331
- * Generate a unique ID suitable for a streaming context.
332
- *
333
- * Not suitable for security purposes or as a primary key, since
334
- * it lacks the amount of entropy required for those use cases.
335
- *
336
- * @returns A unique ID.
337
- */
338
- generateId() {
339
- return (0, import_human_id.humanId)({
340
- separator: "-",
341
- capitalize: false
342
381
  });
382
+ return __spreadValues({ source }, getEmitteryCallbacks(emitter));
343
383
  }
344
384
  /**
345
385
  * Authenticate and connect to a Cartesia streaming WebSocket.
@@ -348,16 +388,16 @@ var audio_default = class extends Client {
348
388
  * @throws {Error} If the WebSocket fails to connect.
349
389
  */
350
390
  connect() {
351
- const url = constructWebsocketUrl(this.baseUrl);
391
+ const url = constructApiUrl(this.baseUrl, "/tts/websocket", "ws");
352
392
  url.searchParams.set("api_key", this.apiKey);
353
- const emitter = new import_emittery.default();
393
+ const emitter = new import_emittery2.default();
354
394
  this.socket = new import_partysocket.WebSocket(url.toString());
355
395
  this.socket.onopen = () => {
356
- this.isConnected = true;
396
+ __privateSet(this, _isConnected, true);
357
397
  emitter.emit("open");
358
398
  };
359
399
  this.socket.onclose = () => {
360
- this.isConnected = false;
400
+ __privateSet(this, _isConnected, false);
361
401
  emitter.emit("close");
362
402
  };
363
403
  return new Promise(
@@ -404,12 +444,85 @@ var audio_default = class extends Client {
404
444
  (_a = this.socket) == null ? void 0 : _a.close();
405
445
  }
406
446
  };
447
+ _isConnected = new WeakMap();
448
+ _sampleRate2 = new WeakMap();
449
+ _generateId = new WeakSet();
450
+ generateId_fn = function() {
451
+ return (0, import_human_id.humanId)({
452
+ separator: "-",
453
+ capitalize: false
454
+ });
455
+ };
456
+
457
+ // src/tts/index.ts
458
+ var TTS = class extends Client {
459
+ /**
460
+ * Get a WebSocket client for streaming audio from the TTS API.
461
+ *
462
+ * @returns {WebSocket} A Cartesia WebSocket client.
463
+ */
464
+ websocket(options) {
465
+ return new WebSocket(options, {
466
+ apiKey: this.apiKey,
467
+ baseUrl: this.baseUrl
468
+ });
469
+ }
470
+ };
471
+
472
+ // src/voices/index.ts
473
+ var Voices = class extends Client {
474
+ list() {
475
+ return __async(this, null, function* () {
476
+ const response = yield this.fetch("/voices");
477
+ return response.json();
478
+ });
479
+ }
480
+ get(voiceId) {
481
+ return __async(this, null, function* () {
482
+ const response = yield this.fetch(`/voices/${voiceId}`);
483
+ return response.json();
484
+ });
485
+ }
486
+ create(voice) {
487
+ return __async(this, null, function* () {
488
+ const response = yield this.fetch("/voices", {
489
+ method: "POST",
490
+ body: JSON.stringify(voice)
491
+ });
492
+ return response.json();
493
+ });
494
+ }
495
+ clone(options) {
496
+ return __async(this, null, function* () {
497
+ if (options.mode === "url") {
498
+ const response = yield this.fetch(
499
+ `/voices/clone/url?link=${options.link}`,
500
+ {
501
+ method: "POST"
502
+ }
503
+ );
504
+ return response.json();
505
+ }
506
+ if (options.mode === "clip") {
507
+ const formData = new FormData();
508
+ formData.append("clip", options.clip);
509
+ const response = yield this.fetch("/voices/clone/clip", {
510
+ method: "POST",
511
+ body: formData
512
+ });
513
+ return response.json();
514
+ }
515
+ throw new Error("Invalid mode for clone()");
516
+ });
517
+ }
518
+ };
407
519
 
408
520
  // src/lib/index.ts
409
521
  var Cartesia = class extends Client {
410
522
  constructor(options = {}) {
411
523
  super(options);
412
- this.audio = new audio_default(options);
524
+ this.tts = new TTS(options);
525
+ this.voices = new Voices(options);
413
526
  }
414
527
  };
415
528
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,11 +1,15 @@
1
- import { e as export_default } from '../index-C2_3XFxn.cjs';
1
+ import TTS from '../tts/index.cjs';
2
2
  import { ClientOptions } from '../types/index.cjs';
3
+ import Voices from '../voices/index.cjs';
3
4
  import { Client } from './client.cjs';
5
+ import '../tts/websocket.cjs';
4
6
  import 'emittery';
5
7
  import 'partysocket';
8
+ import '../tts/source.cjs';
6
9
 
7
10
  declare class Cartesia extends Client {
8
- audio: export_default;
11
+ tts: TTS;
12
+ voices: Voices;
9
13
  constructor(options?: ClientOptions);
10
14
  }
11
15
 
@@ -1,11 +1,15 @@
1
- import { e as export_default } from '../index-DgwnZezj.js';
1
+ import TTS from '../tts/index.js';
2
2
  import { ClientOptions } from '../types/index.js';
3
+ import Voices from '../voices/index.js';
3
4
  import { Client } from './client.js';
5
+ import '../tts/websocket.js';
4
6
  import 'emittery';
5
7
  import 'partysocket';
8
+ import '../tts/source.js';
6
9
 
7
10
  declare class Cartesia extends Client {
8
- audio: export_default;
11
+ tts: TTS;
12
+ voices: Voices;
9
13
  constructor(options?: ClientOptions);
10
14
  }
11
15
 
package/dist/lib/index.js CHANGED
@@ -1,11 +1,14 @@
1
1
  import {
2
2
  Cartesia
3
- } from "../chunk-S6A27RQL.js";
4
- import "../chunk-4MHF74A7.js";
5
- import "../chunk-5TSWLYOW.js";
6
- import "../chunk-MJIFZWHS.js";
7
- import "../chunk-OVI3W3GG.js";
8
- import "../chunk-R4P7LWVZ.js";
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";
11
+ import "../chunk-WIFMLPT5.js";
9
12
  export {
10
13
  Cartesia
11
14
  };