@cartesia/cartesia-js 0.0.1 → 0.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.
@@ -1,47 +1,45 @@
1
-
2
- $ tsup src/ --format cjs,esm --dts --clean
3
- CLI Building entry: src/audio/index.ts, src/audio/utils.ts, src/types/index.ts, src/lib/client.ts, src/lib/constants.ts, src/lib/index.ts, src/react/index.ts
4
- CLI Using tsconfig: tsconfig.json
5
- CLI tsup v8.0.2
6
- CLI Target: es6
7
- CLI Cleaning output folder
8
- CJS Build start
9
- ESM Build start
10
- CJS dist/types/index.js 764.00 B
11
- CJS dist/lib/index.js 11.67 KB
12
- CJS dist/lib/constants.js 1.33 KB
13
- CJS dist/audio/utils.js 3.71 KB
14
- CJS dist/lib/client.js 1.40 KB
15
- CJS dist/react/index.js 13.52 KB
16
- CJS dist/audio/index.js 11.41 KB
17
- CJS ⚡️ Build success in 44ms
18
- ESM dist/types/index.mjs 0 B
19
- ESM dist/audio/utils.mjs 391.00 B
20
- ESM dist/lib/client.mjs 103.00 B
21
- ESM dist/lib/constants.mjs 155.00 B
22
- ESM dist/lib/index.mjs 355.00 B
23
- ESM dist/chunk-5RMUZJV7.mjs 7.01 KB
24
- ESM dist/chunk-BTFHUVNH.mjs 1.79 KB
25
- ESM dist/react/index.mjs 2.08 KB
26
- ESM dist/audio/index.mjs 192.00 B
27
- ESM dist/chunk-ERFCRIWU.mjs 386.00 B
28
- ESM dist/chunk-35HX6ML3.mjs 1.32 KB
29
- ESM ⚡️ Build success in 44ms
30
- DTS Build start
31
- DTS ⚡️ Build success in 3158ms
32
- DTS dist/lib/constants.d.ts 211.00 B
33
- DTS dist/lib/index.d.ts 302.00 B
34
- DTS dist/react/index.d.ts 587.00 B
35
- DTS dist/lib/client.d.ts 180.00 B
36
- DTS dist/types/index.d.ts 103.00 B
37
- DTS dist/audio/utils.d.ts 306.00 B
38
- DTS dist/audio/index.d.ts 161.00 B
39
- DTS dist/index-Ds4LDkmk.d.ts 5.28 KB
40
- DTS dist/lib/constants.d.mts 211.00 B
41
- DTS dist/lib/index.d.mts 305.00 B
42
- DTS dist/react/index.d.mts 590.00 B
43
- DTS dist/lib/client.d.mts 181.00 B
44
- DTS dist/types/index.d.mts 103.00 B
45
- DTS dist/audio/utils.d.mts 309.00 B
46
- DTS dist/audio/index.d.mts 164.00 B
47
- DTS dist/index-Dt9A_pEb.d.mts 5.29 KB
1
+ $ tsup src/ --format cjs,esm --dts
2
+ CLI Building entry: src/audio/index.ts, src/audio/utils.ts, src/lib/client.ts, src/lib/constants.ts, src/lib/index.ts, src/react/index.ts, src/types/index.ts
3
+ CLI Using tsconfig: tsconfig.json
4
+ CLI tsup v8.0.2
5
+ CLI Target: es6
6
+ CJS Build start
7
+ ESM Build start
8
+ CJS dist/audio/index.js 12.63 KB
9
+ CJS dist/lib/client.js 1.40 KB
10
+ CJS dist/react/index.js 17.16 KB
11
+ CJS dist/types/index.js 764.00 B
12
+ CJS dist/audio/utils.js 5.23 KB
13
+ CJS dist/lib/constants.js 1.35 KB
14
+ CJS dist/lib/index.js 12.89 KB
15
+ CJS ⚡️ Build success in 75ms
16
+ ESM dist/types/index.mjs 0 B
17
+ ESM dist/audio/index.mjs 192.00 B
18
+ ESM dist/audio/utils.mjs 469.00 B
19
+ ESM dist/lib/client.mjs 103.00 B
20
+ ESM dist/lib/constants.mjs 155.00 B
21
+ ESM dist/lib/index.mjs 355.00 B
22
+ ESM dist/react/index.mjs 3.31 KB
23
+ ESM dist/chunk-3CYTAFLF.mjs 7.43 KB
24
+ ESM dist/chunk-FRIBQZPN.mjs 3.22 KB
25
+ ESM dist/chunk-XSFPHPPG.mjs 386.00 B
26
+ ESM dist/chunk-HNLIBHEN.mjs 2.02 KB
27
+ ESM ⚡️ Build success in 80ms
28
+ DTS Build start
29
+ DTS ⚡️ Build success in 5605ms
30
+ DTS dist/lib/constants.d.ts 211.00 B
31
+ DTS dist/lib/index.d.ts 324.00 B
32
+ DTS dist/react/index.d.ts 720.00 B
33
+ DTS dist/lib/client.d.ts 180.00 B
34
+ DTS dist/types/index.d.ts 103.00 B
35
+ DTS dist/audio/utils.d.ts 397.00 B
36
+ DTS dist/audio/index.d.ts 229.00 B
37
+ DTS dist/index-qwAyxV5I.d.ts 6.49 KB
38
+ DTS dist/lib/constants.d.mts 211.00 B
39
+ DTS dist/lib/index.d.mts 327.00 B
40
+ DTS dist/react/index.d.mts 723.00 B
41
+ DTS dist/lib/client.d.mts 181.00 B
42
+ DTS dist/types/index.d.mts 103.00 B
43
+ DTS dist/audio/utils.d.mts 400.00 B
44
+ DTS dist/audio/index.d.mts 232.00 B
45
+ DTS dist/index-DSBmfK9-.d.mts 6.49 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @cartesia/cartesia-js
2
2
 
3
+ ## 0.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 9a31c66: Improve error handling logic, add connection info, make audio downloadable, add latency metrics, more robust reconnection handling, and misc. changes
8
+
3
9
  ## 0.0.1
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # JavaScript Client for Cartesia
2
2
 
3
- Usage:
3
+ ## Installation
4
+
5
+ ```bash
6
+ # NPM
7
+ npm install @cartesia/cartesia-js
8
+ # Yarn
9
+ yarn add @cartesia/cartesia-js
10
+ # PNPM
11
+ pnpm add @cartesia/cartesia-js
12
+ # Bun
13
+ bun add @cartesia/cartesia-js
14
+ ```
15
+
16
+ ## Usage
4
17
 
5
18
  ```javascript
6
19
  import Cartesia from "@cartesia/cartesia-js";
@@ -14,7 +27,7 @@ try {
14
27
  }
15
28
 
16
29
  const stream = await cartesia.audio.stream({
17
- model: "echo_tts_v0.0.6",
30
+ model: "upbeat-moon",
18
31
  options: {
19
32
  transcript: "Hello, world!",
20
33
  chunk_time: 0.1,
@@ -25,6 +38,7 @@ console.log(`Created stream ${stream.id}.`);
25
38
 
26
39
  stream.on("chunk", ({ chunk, chunks }) => {
27
40
  console.log("Received chunk:", chunk);
41
+ console.log("All chunks:", chunks);
28
42
  });
29
43
 
30
44
  stream.on("message", ({ message }) => {
@@ -32,6 +46,7 @@ stream.on("message", ({ message }) => {
32
46
  console.log("Received message:", message);
33
47
  });
34
48
 
49
+ // If you're using the client in the browser, you can play the stream like this:
35
50
  console.log("Playing stream...");
36
51
  await stream.play();
37
52
  console.log("Done playing.");
@@ -1,4 +1,5 @@
1
1
  import 'emittery';
2
+ import 'partysocket';
2
3
  import '../lib/client.mjs';
3
- export { C as Chunk, S as StreamEventData, e as default } from '../index-Dt9A_pEb.mjs';
4
+ export { C as Chunk, l as ConnectionEventData, S as StreamEventData, m as StreamRequest, e as default } from '../index-DSBmfK9-.mjs';
4
5
  import '../types/index.mjs';
@@ -1,4 +1,5 @@
1
1
  import 'emittery';
2
+ import 'partysocket';
2
3
  import '../lib/client.js';
3
- export { C as Chunk, S as StreamEventData, e as default } from '../index-Ds4LDkmk.js';
4
+ export { C as Chunk, l as ConnectionEventData, S as StreamEventData, m as StreamRequest, e as default } from '../index-qwAyxV5I.js';
4
5
  import '../types/index.js';
@@ -3,11 +3,25 @@ var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
7
  var __getProtoOf = Object.getPrototypeOf;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
10
  var __knownSymbol = (name, symbol) => {
9
11
  return (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
10
12
  };
13
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
+ var __spreadValues = (a, b) => {
15
+ for (var prop in b || (b = {}))
16
+ if (__hasOwnProp.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
18
+ if (__getOwnPropSymbols)
19
+ for (var prop of __getOwnPropSymbols(b)) {
20
+ if (__propIsEnum.call(b, prop))
21
+ __defNormalProp(a, prop, b[prop]);
22
+ }
23
+ return a;
24
+ };
11
25
  var __export = (target, all) => {
12
26
  for (var name in all)
13
27
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -59,12 +73,13 @@ __export(audio_exports, {
59
73
  module.exports = __toCommonJS(audio_exports);
60
74
  var import_emittery = __toESM(require("emittery"));
61
75
  var import_human_id = require("human-id");
76
+ var import_partysocket = require("partysocket");
62
77
 
63
78
  // src/lib/constants.ts
64
79
  var BASE_URL = "https://api.cartesia.ai/v0";
65
80
  var SAMPLE_RATE = 44100;
66
81
  var constructWebsocketUrl = (baseUrl) => {
67
- return new URL(`${baseUrl.replace(/^http/, "ws")}/ws`);
82
+ return new URL(`${baseUrl.replace(/^http/, "ws")}/audio/websocket`);
68
83
  };
69
84
 
70
85
  // src/lib/client.ts
@@ -134,6 +149,14 @@ function filterSentinel(collection) {
134
149
  function isComplete(chunks) {
135
150
  return isSentinel(chunks[chunks.length - 1]);
136
151
  }
152
+ function getEmitteryCallbacks(emitter) {
153
+ return {
154
+ on: emitter.on.bind(emitter),
155
+ off: emitter.off.bind(emitter),
156
+ once: emitter.once.bind(emitter),
157
+ events: emitter.events.bind(emitter)
158
+ };
159
+ }
137
160
 
138
161
  // src/audio/index.ts
139
162
  var audio_default = class extends Client {
@@ -182,6 +205,9 @@ var audio_default = class extends Client {
182
205
  });
183
206
  yield emitter.emit("message", message);
184
207
  if (isSentinel(chunk)) {
208
+ yield emitter.emit("streamed", {
209
+ chunks
210
+ });
185
211
  streamCompleteController.abort();
186
212
  } else if (timeoutId) {
187
213
  clearTimeout(timeoutId);
@@ -192,13 +218,28 @@ var audio_default = class extends Client {
192
218
  (_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
193
219
  signal: streamCompleteController.signal
194
220
  });
195
- (_c = this.socket) == null ? void 0 : _c.addEventListener("close", streamCompleteController.abort, {
196
- once: true
197
- });
198
- (_d = this.socket) == null ? void 0 : _d.addEventListener("error", streamCompleteController.abort, {
199
- once: true
200
- });
221
+ (_c = this.socket) == null ? void 0 : _c.addEventListener(
222
+ "close",
223
+ () => {
224
+ streamCompleteController.abort();
225
+ },
226
+ {
227
+ once: true
228
+ }
229
+ );
230
+ (_d = this.socket) == null ? void 0 : _d.addEventListener(
231
+ "error",
232
+ () => {
233
+ streamCompleteController.abort();
234
+ },
235
+ {
236
+ once: true
237
+ }
238
+ );
201
239
  streamCompleteController.signal.addEventListener("abort", () => {
240
+ if (timeoutId) {
241
+ clearTimeout(timeoutId);
242
+ }
202
243
  emitter.clearListeners();
203
244
  });
204
245
  const play = (_0) => __async(this, [_0], function* ({ bufferDuration }) {
@@ -272,13 +313,9 @@ var audio_default = class extends Client {
272
313
  }
273
314
  }
274
315
  });
275
- return {
276
- play,
277
- on: emitter.on.bind(emitter),
278
- off: emitter.off.bind(emitter),
279
- once: emitter.once.bind(emitter),
280
- events: emitter.events.bind(emitter)
281
- };
316
+ return __spreadValues({
317
+ play
318
+ }, getEmitteryCallbacks(emitter));
282
319
  }
283
320
  /**
284
321
  * Generate a unique ID suitable for a streaming context.
@@ -303,46 +340,51 @@ var audio_default = class extends Client {
303
340
  connect() {
304
341
  const url = constructWebsocketUrl(this.baseUrl);
305
342
  url.searchParams.set("api_key", this.apiKey);
306
- this.socket = new WebSocket(url);
343
+ const emitter = new import_emittery.default();
344
+ this.socket = new import_partysocket.WebSocket(url.toString());
307
345
  this.socket.onopen = () => {
308
346
  this.isConnected = true;
347
+ emitter.emit("open");
309
348
  };
310
349
  this.socket.onclose = () => {
311
350
  this.isConnected = false;
351
+ emitter.emit("close");
312
352
  };
313
- return new Promise((resolve, reject) => {
314
- var _a, _b, _c;
315
- (_a = this.socket) == null ? void 0 : _a.addEventListener(
316
- "open",
317
- () => {
318
- resolve();
319
- },
320
- {
321
- once: true
322
- }
323
- );
324
- const aborter = new AbortController();
325
- (_b = this.socket) == null ? void 0 : _b.addEventListener(
326
- "error",
327
- () => {
328
- aborter.abort();
329
- reject(new Error("WebSocket failed to connect."));
330
- },
331
- {
332
- signal: aborter.signal
333
- }
334
- );
335
- (_c = this.socket) == null ? void 0 : _c.addEventListener(
336
- "close",
337
- () => {
338
- aborter.abort();
339
- reject(new Error("WebSocket closed before it could connect."));
340
- },
341
- {
342
- signal: aborter.signal
343
- }
344
- );
345
- });
353
+ return new Promise(
354
+ (resolve, reject) => {
355
+ var _a, _b, _c;
356
+ (_a = this.socket) == null ? void 0 : _a.addEventListener(
357
+ "open",
358
+ () => {
359
+ resolve(getEmitteryCallbacks(emitter));
360
+ },
361
+ {
362
+ once: true
363
+ }
364
+ );
365
+ const aborter = new AbortController();
366
+ (_b = this.socket) == null ? void 0 : _b.addEventListener(
367
+ "error",
368
+ () => {
369
+ aborter.abort();
370
+ reject(new Error("WebSocket failed to connect."));
371
+ },
372
+ {
373
+ signal: aborter.signal
374
+ }
375
+ );
376
+ (_c = this.socket) == null ? void 0 : _c.addEventListener(
377
+ "close",
378
+ () => {
379
+ aborter.abort();
380
+ reject(new Error("WebSocket closed before it could connect."));
381
+ },
382
+ {
383
+ signal: aborter.signal
384
+ }
385
+ );
386
+ }
387
+ );
346
388
  }
347
389
  /**
348
390
  * Disconnect from the Cartesia streaming WebSocket.
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  audio_default
3
- } from "../chunk-5RMUZJV7.mjs";
4
- import "../chunk-BTFHUVNH.mjs";
5
- import "../chunk-ERFCRIWU.mjs";
6
- import "../chunk-35HX6ML3.mjs";
3
+ } from "../chunk-3CYTAFLF.mjs";
4
+ import "../chunk-FRIBQZPN.mjs";
5
+ import "../chunk-XSFPHPPG.mjs";
6
+ import "../chunk-HNLIBHEN.mjs";
7
7
  export {
8
8
  audio_default as default
9
9
  };
@@ -1,4 +1,5 @@
1
- export { a as Sentinel, b as base64ToArray, c as createMessageHandlerForContextId, f as filterSentinel, g as getBufferDuration, d as getSentinel, h as isComplete, i as isSentinel, p as playAudioBuffer } from '../index-Dt9A_pEb.mjs';
2
1
  import 'emittery';
2
+ export { E as EmitteryCallbacks, a as Sentinel, b as base64ToArray, k as bufferToWav, c as createMessageHandlerForContextId, f as filterSentinel, g as getBufferDuration, j as getEmitteryCallbacks, d as getSentinel, h as isComplete, i as isSentinel, p as playAudioBuffer } from '../index-DSBmfK9-.mjs';
3
+ import 'partysocket';
3
4
  import '../lib/client.mjs';
4
5
  import '../types/index.mjs';
@@ -1,4 +1,5 @@
1
- export { a as Sentinel, b as base64ToArray, c as createMessageHandlerForContextId, f as filterSentinel, g as getBufferDuration, d as getSentinel, h as isComplete, i as isSentinel, p as playAudioBuffer } from '../index-Ds4LDkmk.js';
2
1
  import 'emittery';
2
+ export { E as EmitteryCallbacks, a as Sentinel, b as base64ToArray, k as bufferToWav, c as createMessageHandlerForContextId, f as filterSentinel, g as getBufferDuration, j as getEmitteryCallbacks, d as getSentinel, h as isComplete, i as isSentinel, p as playAudioBuffer } from '../index-qwAyxV5I.js';
3
+ import 'partysocket';
3
4
  import '../lib/client.js';
4
5
  import '../types/index.js';
@@ -31,9 +31,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var utils_exports = {};
32
32
  __export(utils_exports, {
33
33
  base64ToArray: () => base64ToArray,
34
+ bufferToWav: () => bufferToWav,
34
35
  createMessageHandlerForContextId: () => createMessageHandlerForContextId,
35
36
  filterSentinel: () => filterSentinel,
36
37
  getBufferDuration: () => getBufferDuration,
38
+ getEmitteryCallbacks: () => getEmitteryCallbacks,
37
39
  getSentinel: () => getSentinel,
38
40
  isComplete: () => isComplete,
39
41
  isSentinel: () => isSentinel,
@@ -100,12 +102,54 @@ function filterSentinel(collection) {
100
102
  function isComplete(chunks) {
101
103
  return isSentinel(chunks[chunks.length - 1]);
102
104
  }
105
+ function getEmitteryCallbacks(emitter) {
106
+ return {
107
+ on: emitter.on.bind(emitter),
108
+ off: emitter.off.bind(emitter),
109
+ once: emitter.once.bind(emitter),
110
+ events: emitter.events.bind(emitter)
111
+ };
112
+ }
113
+ function bufferToWav(sampleRate, channelBuffers) {
114
+ const totalSamples = channelBuffers[0].length * channelBuffers.length;
115
+ const buffer = new ArrayBuffer(44 + totalSamples * 2);
116
+ const view = new DataView(buffer);
117
+ const writeString = (view2, offset2, string) => {
118
+ for (let i = 0; i < string.length; i++) {
119
+ view2.setUint8(offset2 + i, string.charCodeAt(i));
120
+ }
121
+ };
122
+ writeString(view, 0, "RIFF");
123
+ view.setUint32(4, 36 + totalSamples * 2, true);
124
+ writeString(view, 8, "WAVE");
125
+ writeString(view, 12, "fmt ");
126
+ view.setUint32(16, 16, true);
127
+ view.setUint16(20, 1, true);
128
+ view.setUint16(22, channelBuffers.length, true);
129
+ view.setUint32(24, sampleRate, true);
130
+ view.setUint32(28, sampleRate * 4, true);
131
+ view.setUint16(32, channelBuffers.length * 2, true);
132
+ view.setUint16(34, 16, true);
133
+ writeString(view, 36, "data");
134
+ view.setUint32(40, totalSamples * 2, true);
135
+ let offset = 44;
136
+ for (let i = 0; i < channelBuffers[0].length; i++) {
137
+ for (let channel = 0; channel < channelBuffers.length; channel++) {
138
+ const s = Math.max(-1, Math.min(1, channelBuffers[channel][i]));
139
+ view.setInt16(offset, s < 0 ? s * 32768 : s * 32767, true);
140
+ offset += 2;
141
+ }
142
+ }
143
+ return buffer;
144
+ }
103
145
  // Annotate the CommonJS export names for ESM import in node:
104
146
  0 && (module.exports = {
105
147
  base64ToArray,
148
+ bufferToWav,
106
149
  createMessageHandlerForContextId,
107
150
  filterSentinel,
108
151
  getBufferDuration,
152
+ getEmitteryCallbacks,
109
153
  getSentinel,
110
154
  isComplete,
111
155
  isSentinel,
@@ -1,19 +1,23 @@
1
1
  import {
2
2
  base64ToArray,
3
+ bufferToWav,
3
4
  createMessageHandlerForContextId,
4
5
  filterSentinel,
5
6
  getBufferDuration,
7
+ getEmitteryCallbacks,
6
8
  getSentinel,
7
9
  isComplete,
8
10
  isSentinel,
9
11
  playAudioBuffer
10
- } from "../chunk-BTFHUVNH.mjs";
11
- import "../chunk-35HX6ML3.mjs";
12
+ } from "../chunk-FRIBQZPN.mjs";
13
+ import "../chunk-HNLIBHEN.mjs";
12
14
  export {
13
15
  base64ToArray,
16
+ bufferToWav,
14
17
  createMessageHandlerForContextId,
15
18
  filterSentinel,
16
19
  getBufferDuration,
20
+ getEmitteryCallbacks,
17
21
  getSentinel,
18
22
  isComplete,
19
23
  isSentinel,