@cartesia/cartesia-js 0.0.1 → 0.0.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.
@@ -1,23 +1,26 @@
1
1
  import {
2
2
  createMessageHandlerForContextId,
3
3
  getBufferDuration,
4
+ getEmitteryCallbacks,
4
5
  isComplete,
5
6
  isSentinel,
6
7
  playAudioBuffer
7
- } from "./chunk-BTFHUVNH.mjs";
8
+ } from "./chunk-FRIBQZPN.mjs";
8
9
  import {
9
10
  Client
10
- } from "./chunk-ERFCRIWU.mjs";
11
+ } from "./chunk-XSFPHPPG.mjs";
11
12
  import {
12
13
  SAMPLE_RATE,
13
14
  __async,
14
15
  __forAwait,
16
+ __spreadValues,
15
17
  constructWebsocketUrl
16
- } from "./chunk-35HX6ML3.mjs";
18
+ } from "./chunk-HNLIBHEN.mjs";
17
19
 
18
20
  // src/audio/index.ts
19
21
  import Emittery from "emittery";
20
22
  import { humanId } from "human-id";
23
+ import { WebSocket } from "partysocket";
21
24
  var audio_default = class extends Client {
22
25
  constructor() {
23
26
  super(...arguments);
@@ -64,6 +67,9 @@ var audio_default = class extends Client {
64
67
  });
65
68
  yield emitter.emit("message", message);
66
69
  if (isSentinel(chunk)) {
70
+ yield emitter.emit("streamed", {
71
+ chunks
72
+ });
67
73
  streamCompleteController.abort();
68
74
  } else if (timeoutId) {
69
75
  clearTimeout(timeoutId);
@@ -74,13 +80,28 @@ var audio_default = class extends Client {
74
80
  (_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
75
81
  signal: streamCompleteController.signal
76
82
  });
77
- (_c = this.socket) == null ? void 0 : _c.addEventListener("close", streamCompleteController.abort, {
78
- once: true
79
- });
80
- (_d = this.socket) == null ? void 0 : _d.addEventListener("error", streamCompleteController.abort, {
81
- once: true
82
- });
83
+ (_c = this.socket) == null ? void 0 : _c.addEventListener(
84
+ "close",
85
+ () => {
86
+ streamCompleteController.abort();
87
+ },
88
+ {
89
+ once: true
90
+ }
91
+ );
92
+ (_d = this.socket) == null ? void 0 : _d.addEventListener(
93
+ "error",
94
+ () => {
95
+ streamCompleteController.abort();
96
+ },
97
+ {
98
+ once: true
99
+ }
100
+ );
83
101
  streamCompleteController.signal.addEventListener("abort", () => {
102
+ if (timeoutId) {
103
+ clearTimeout(timeoutId);
104
+ }
84
105
  emitter.clearListeners();
85
106
  });
86
107
  const play = (_0) => __async(this, [_0], function* ({ bufferDuration }) {
@@ -154,13 +175,9 @@ var audio_default = class extends Client {
154
175
  }
155
176
  }
156
177
  });
157
- return {
158
- play,
159
- on: emitter.on.bind(emitter),
160
- off: emitter.off.bind(emitter),
161
- once: emitter.once.bind(emitter),
162
- events: emitter.events.bind(emitter)
163
- };
178
+ return __spreadValues({
179
+ play
180
+ }, getEmitteryCallbacks(emitter));
164
181
  }
165
182
  /**
166
183
  * Generate a unique ID suitable for a streaming context.
@@ -185,46 +202,51 @@ var audio_default = class extends Client {
185
202
  connect() {
186
203
  const url = constructWebsocketUrl(this.baseUrl);
187
204
  url.searchParams.set("api_key", this.apiKey);
188
- this.socket = new WebSocket(url);
205
+ const emitter = new Emittery();
206
+ this.socket = new WebSocket(url.toString());
189
207
  this.socket.onopen = () => {
190
208
  this.isConnected = true;
209
+ emitter.emit("open");
191
210
  };
192
211
  this.socket.onclose = () => {
193
212
  this.isConnected = false;
213
+ emitter.emit("close");
194
214
  };
195
- return new Promise((resolve, reject) => {
196
- var _a, _b, _c;
197
- (_a = this.socket) == null ? void 0 : _a.addEventListener(
198
- "open",
199
- () => {
200
- resolve();
201
- },
202
- {
203
- once: true
204
- }
205
- );
206
- const aborter = new AbortController();
207
- (_b = this.socket) == null ? void 0 : _b.addEventListener(
208
- "error",
209
- () => {
210
- aborter.abort();
211
- reject(new Error("WebSocket failed to connect."));
212
- },
213
- {
214
- signal: aborter.signal
215
- }
216
- );
217
- (_c = this.socket) == null ? void 0 : _c.addEventListener(
218
- "close",
219
- () => {
220
- aborter.abort();
221
- reject(new Error("WebSocket closed before it could connect."));
222
- },
223
- {
224
- signal: aborter.signal
225
- }
226
- );
227
- });
215
+ return new Promise(
216
+ (resolve, reject) => {
217
+ var _a, _b, _c;
218
+ (_a = this.socket) == null ? void 0 : _a.addEventListener(
219
+ "open",
220
+ () => {
221
+ resolve(getEmitteryCallbacks(emitter));
222
+ },
223
+ {
224
+ once: true
225
+ }
226
+ );
227
+ const aborter = new AbortController();
228
+ (_b = this.socket) == null ? void 0 : _b.addEventListener(
229
+ "error",
230
+ () => {
231
+ aborter.abort();
232
+ reject(new Error("WebSocket failed to connect."));
233
+ },
234
+ {
235
+ signal: aborter.signal
236
+ }
237
+ );
238
+ (_c = this.socket) == null ? void 0 : _c.addEventListener(
239
+ "close",
240
+ () => {
241
+ aborter.abort();
242
+ reject(new Error("WebSocket closed before it could connect."));
243
+ },
244
+ {
245
+ signal: aborter.signal
246
+ }
247
+ );
248
+ }
249
+ );
228
250
  }
229
251
  /**
230
252
  * Disconnect from the Cartesia streaming WebSocket.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SAMPLE_RATE
3
- } from "./chunk-35HX6ML3.mjs";
3
+ } from "./chunk-HNLIBHEN.mjs";
4
4
 
5
5
  // src/audio/utils.ts
6
6
  import base64 from "base64-js";
@@ -58,6 +58,46 @@ function filterSentinel(collection) {
58
58
  function isComplete(chunks) {
59
59
  return isSentinel(chunks[chunks.length - 1]);
60
60
  }
61
+ function getEmitteryCallbacks(emitter) {
62
+ return {
63
+ on: emitter.on.bind(emitter),
64
+ off: emitter.off.bind(emitter),
65
+ once: emitter.once.bind(emitter),
66
+ events: emitter.events.bind(emitter)
67
+ };
68
+ }
69
+ function bufferToWav(sampleRate, channelBuffers) {
70
+ const totalSamples = channelBuffers[0].length * channelBuffers.length;
71
+ const buffer = new ArrayBuffer(44 + totalSamples * 2);
72
+ const view = new DataView(buffer);
73
+ const writeString = (view2, offset2, string) => {
74
+ for (let i = 0; i < string.length; i++) {
75
+ view2.setUint8(offset2 + i, string.charCodeAt(i));
76
+ }
77
+ };
78
+ writeString(view, 0, "RIFF");
79
+ view.setUint32(4, 36 + totalSamples * 2, true);
80
+ writeString(view, 8, "WAVE");
81
+ writeString(view, 12, "fmt ");
82
+ view.setUint32(16, 16, true);
83
+ view.setUint16(20, 1, true);
84
+ view.setUint16(22, channelBuffers.length, true);
85
+ view.setUint32(24, sampleRate, true);
86
+ view.setUint32(28, sampleRate * 4, true);
87
+ view.setUint16(32, channelBuffers.length * 2, true);
88
+ view.setUint16(34, 16, true);
89
+ writeString(view, 36, "data");
90
+ view.setUint32(40, totalSamples * 2, true);
91
+ let offset = 44;
92
+ for (let i = 0; i < channelBuffers[0].length; i++) {
93
+ for (let channel = 0; channel < channelBuffers.length; channel++) {
94
+ const s = Math.max(-1, Math.min(1, channelBuffers[channel][i]));
95
+ view.setInt16(offset, s < 0 ? s * 32768 : s * 32767, true);
96
+ offset += 2;
97
+ }
98
+ }
99
+ return buffer;
100
+ }
61
101
 
62
102
  export {
63
103
  getBufferDuration,
@@ -67,5 +107,7 @@ export {
67
107
  getSentinel,
68
108
  isSentinel,
69
109
  filterSentinel,
70
- isComplete
110
+ isComplete,
111
+ getEmitteryCallbacks,
112
+ bufferToWav
71
113
  };
@@ -1,6 +1,22 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
1
5
  var __knownSymbol = (name, symbol) => {
2
6
  return (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
3
7
  };
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
4
20
  var __async = (__this, __arguments, generator) => {
5
21
  return new Promise((resolve, reject) => {
6
22
  var fulfilled = (value) => {
@@ -27,10 +43,11 @@ var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")])
27
43
  var BASE_URL = "https://api.cartesia.ai/v0";
28
44
  var SAMPLE_RATE = 44100;
29
45
  var constructWebsocketUrl = (baseUrl) => {
30
- return new URL(`${baseUrl.replace(/^http/, "ws")}/ws`);
46
+ return new URL(`${baseUrl.replace(/^http/, "ws")}/audio/websocket`);
31
47
  };
32
48
 
33
49
  export {
50
+ __spreadValues,
34
51
  __async,
35
52
  __forAwait,
36
53
  BASE_URL,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BASE_URL
3
- } from "./chunk-35HX6ML3.mjs";
3
+ } from "./chunk-HNLIBHEN.mjs";
4
4
 
5
5
  // src/lib/client.ts
6
6
  var Client = class {
@@ -1,4 +1,6 @@
1
1
  import * as emittery from 'emittery';
2
+ import emittery__default from 'emittery';
3
+ import { WebSocket } from 'partysocket';
2
4
  import { Client } from './lib/client.mjs';
3
5
 
4
6
  /**
@@ -67,6 +69,24 @@ declare function filterSentinel<T>(collection: T[]): Exclude<T, Sentinel>[];
67
69
  * @returns Whether the array of chunks is complete.
68
70
  */
69
71
  declare function isComplete(chunks: Chunk[]): boolean;
72
+ type EmitteryCallbacks<T> = {
73
+ on: emittery__default<T>["on"];
74
+ off: emittery__default<T>["off"];
75
+ once: emittery__default<T>["once"];
76
+ events: emittery__default<T>["events"];
77
+ };
78
+ /**
79
+ * Get user-facing emitter callbacks for an Emittery instance.
80
+ * @param emitter The Emittery instance to get callbacks for.
81
+ * @returns User-facing emitter callbacks.
82
+ */
83
+ declare function getEmitteryCallbacks<T>(emitter: emittery__default<T>): EmitteryCallbacks<T>;
84
+ /**
85
+ * Converts a base64-encoded audio buffer to a WAV file.
86
+ * Source: https://gist.github.com/Daninet/22edc59cf2aee0b9a90c18e553e49297
87
+ * @param b64 The base64-encoded audio buffer to convert to a WAV file.
88
+ */
89
+ declare function bufferToWav(sampleRate: number, channelBuffers: Float32Array[]): ArrayBuffer;
70
90
 
71
91
  type Chunk = string | Sentinel;
72
92
  type StreamEventData = {
@@ -74,8 +94,21 @@ type StreamEventData = {
74
94
  chunk: Chunk;
75
95
  chunks: Chunk[];
76
96
  };
97
+ streamed: {
98
+ chunks: Chunk[];
99
+ };
77
100
  message: unknown;
78
101
  };
102
+ type ConnectionEventData = {
103
+ open: never;
104
+ close: never;
105
+ };
106
+ type StreamRequest = {
107
+ inputs: object;
108
+ options: {
109
+ timeout?: number;
110
+ };
111
+ };
79
112
  declare class export_default extends Client {
80
113
  socket?: WebSocket;
81
114
  isConnected: boolean;
@@ -91,16 +124,14 @@ declare class export_default extends Client {
91
124
  * that plays the audio as it arrives, with `bufferDuration` seconds of audio buffered before
92
125
  * starting playback.
93
126
  */
94
- stream(inputs: object, { timeout }?: {
95
- timeout?: number;
96
- }): {
97
- play: ({ bufferDuration }: {
98
- bufferDuration: number;
99
- }) => Promise<void>;
127
+ stream(inputs: StreamRequest["inputs"], { timeout }?: StreamRequest["options"]): {
100
128
  on: <Name extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name | readonly Name[], listener: (eventData: (StreamEventData & emittery.OmnipresentEventData)[Name]) => void | Promise<void>) => emittery.UnsubscribeFunction;
101
129
  off: <Name_1 extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name_1 | readonly Name_1[], listener: (eventData: (StreamEventData & emittery.OmnipresentEventData)[Name_1]) => void | Promise<void>) => void;
102
130
  once: <Name_2 extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name_2 | readonly Name_2[]) => emittery.EmitteryOncePromise<(StreamEventData & emittery.OmnipresentEventData)[Name_2]>;
103
131
  events: <Name_3 extends keyof StreamEventData>(eventName: Name_3 | readonly Name_3[]) => AsyncIterableIterator<StreamEventData[Name_3]>;
132
+ play: ({ bufferDuration }: {
133
+ bufferDuration: number;
134
+ }) => Promise<void>;
104
135
  };
105
136
  /**
106
137
  * Generate a unique ID suitable for a streaming context.
@@ -117,11 +148,11 @@ declare class export_default extends Client {
117
148
  * @returns A promise that resolves when the WebSocket is connected.
118
149
  * @throws {Error} If the WebSocket fails to connect.
119
150
  */
120
- connect(): Promise<void>;
151
+ connect(): Promise<EmitteryCallbacks<ConnectionEventData>>;
121
152
  /**
122
153
  * Disconnect from the Cartesia streaming WebSocket.
123
154
  */
124
155
  disconnect(): void;
125
156
  }
126
157
 
127
- export { type Chunk as C, type StreamEventData as S, type Sentinel as a, base64ToArray as b, createMessageHandlerForContextId as c, getSentinel as d, export_default as e, filterSentinel as f, getBufferDuration as g, isComplete as h, isSentinel as i, playAudioBuffer as p };
158
+ export { type Chunk as C, type EmitteryCallbacks as E, type StreamEventData as S, type Sentinel as a, base64ToArray as b, createMessageHandlerForContextId as c, getSentinel as d, export_default as e, filterSentinel as f, getBufferDuration as g, isComplete as h, isSentinel as i, getEmitteryCallbacks as j, bufferToWav as k, type ConnectionEventData as l, type StreamRequest as m, playAudioBuffer as p };
@@ -1,4 +1,6 @@
1
1
  import * as emittery from 'emittery';
2
+ import emittery__default from 'emittery';
3
+ import { WebSocket } from 'partysocket';
2
4
  import { Client } from './lib/client.js';
3
5
 
4
6
  /**
@@ -67,6 +69,24 @@ declare function filterSentinel<T>(collection: T[]): Exclude<T, Sentinel>[];
67
69
  * @returns Whether the array of chunks is complete.
68
70
  */
69
71
  declare function isComplete(chunks: Chunk[]): boolean;
72
+ type EmitteryCallbacks<T> = {
73
+ on: emittery__default<T>["on"];
74
+ off: emittery__default<T>["off"];
75
+ once: emittery__default<T>["once"];
76
+ events: emittery__default<T>["events"];
77
+ };
78
+ /**
79
+ * Get user-facing emitter callbacks for an Emittery instance.
80
+ * @param emitter The Emittery instance to get callbacks for.
81
+ * @returns User-facing emitter callbacks.
82
+ */
83
+ declare function getEmitteryCallbacks<T>(emitter: emittery__default<T>): EmitteryCallbacks<T>;
84
+ /**
85
+ * Converts a base64-encoded audio buffer to a WAV file.
86
+ * Source: https://gist.github.com/Daninet/22edc59cf2aee0b9a90c18e553e49297
87
+ * @param b64 The base64-encoded audio buffer to convert to a WAV file.
88
+ */
89
+ declare function bufferToWav(sampleRate: number, channelBuffers: Float32Array[]): ArrayBuffer;
70
90
 
71
91
  type Chunk = string | Sentinel;
72
92
  type StreamEventData = {
@@ -74,8 +94,21 @@ type StreamEventData = {
74
94
  chunk: Chunk;
75
95
  chunks: Chunk[];
76
96
  };
97
+ streamed: {
98
+ chunks: Chunk[];
99
+ };
77
100
  message: unknown;
78
101
  };
102
+ type ConnectionEventData = {
103
+ open: never;
104
+ close: never;
105
+ };
106
+ type StreamRequest = {
107
+ inputs: object;
108
+ options: {
109
+ timeout?: number;
110
+ };
111
+ };
79
112
  declare class export_default extends Client {
80
113
  socket?: WebSocket;
81
114
  isConnected: boolean;
@@ -91,16 +124,14 @@ declare class export_default extends Client {
91
124
  * that plays the audio as it arrives, with `bufferDuration` seconds of audio buffered before
92
125
  * starting playback.
93
126
  */
94
- stream(inputs: object, { timeout }?: {
95
- timeout?: number;
96
- }): {
97
- play: ({ bufferDuration }: {
98
- bufferDuration: number;
99
- }) => Promise<void>;
127
+ stream(inputs: StreamRequest["inputs"], { timeout }?: StreamRequest["options"]): {
100
128
  on: <Name extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name | readonly Name[], listener: (eventData: (StreamEventData & emittery.OmnipresentEventData)[Name]) => void | Promise<void>) => emittery.UnsubscribeFunction;
101
129
  off: <Name_1 extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name_1 | readonly Name_1[], listener: (eventData: (StreamEventData & emittery.OmnipresentEventData)[Name_1]) => void | Promise<void>) => void;
102
130
  once: <Name_2 extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name_2 | readonly Name_2[]) => emittery.EmitteryOncePromise<(StreamEventData & emittery.OmnipresentEventData)[Name_2]>;
103
131
  events: <Name_3 extends keyof StreamEventData>(eventName: Name_3 | readonly Name_3[]) => AsyncIterableIterator<StreamEventData[Name_3]>;
132
+ play: ({ bufferDuration }: {
133
+ bufferDuration: number;
134
+ }) => Promise<void>;
104
135
  };
105
136
  /**
106
137
  * Generate a unique ID suitable for a streaming context.
@@ -117,11 +148,11 @@ declare class export_default extends Client {
117
148
  * @returns A promise that resolves when the WebSocket is connected.
118
149
  * @throws {Error} If the WebSocket fails to connect.
119
150
  */
120
- connect(): Promise<void>;
151
+ connect(): Promise<EmitteryCallbacks<ConnectionEventData>>;
121
152
  /**
122
153
  * Disconnect from the Cartesia streaming WebSocket.
123
154
  */
124
155
  disconnect(): void;
125
156
  }
126
157
 
127
- export { type Chunk as C, type StreamEventData as S, type Sentinel as a, base64ToArray as b, createMessageHandlerForContextId as c, getSentinel as d, export_default as e, filterSentinel as f, getBufferDuration as g, isComplete as h, isSentinel as i, playAudioBuffer as p };
158
+ export { type Chunk as C, type EmitteryCallbacks as E, type StreamEventData as S, type Sentinel as a, base64ToArray as b, createMessageHandlerForContextId as c, getSentinel as d, export_default as e, filterSentinel as f, getBufferDuration as g, isComplete as h, isSentinel as i, getEmitteryCallbacks as j, bufferToWav as k, type ConnectionEventData as l, type StreamRequest as m, playAudioBuffer as p };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Client
3
- } from "../chunk-ERFCRIWU.mjs";
4
- import "../chunk-35HX6ML3.mjs";
3
+ } from "../chunk-XSFPHPPG.mjs";
4
+ import "../chunk-HNLIBHEN.mjs";
5
5
  export {
6
6
  Client
7
7
  };
@@ -28,7 +28,7 @@ module.exports = __toCommonJS(constants_exports);
28
28
  var BASE_URL = "https://api.cartesia.ai/v0";
29
29
  var SAMPLE_RATE = 44100;
30
30
  var constructWebsocketUrl = (baseUrl) => {
31
- return new URL(`${baseUrl.replace(/^http/, "ws")}/ws`);
31
+ return new URL(`${baseUrl.replace(/^http/, "ws")}/audio/websocket`);
32
32
  };
33
33
  // Annotate the CommonJS export names for ESM import in node:
34
34
  0 && (module.exports = {
@@ -2,7 +2,7 @@ import {
2
2
  BASE_URL,
3
3
  SAMPLE_RATE,
4
4
  constructWebsocketUrl
5
- } from "../chunk-35HX6ML3.mjs";
5
+ } from "../chunk-HNLIBHEN.mjs";
6
6
  export {
7
7
  BASE_URL,
8
8
  SAMPLE_RATE,
@@ -1,7 +1,8 @@
1
- import { e as export_default } from '../index-Dt9A_pEb.mjs';
1
+ import { e as export_default } from '../index-DSBmfK9-.mjs';
2
2
  import { ClientOptions } from '../types/index.mjs';
3
3
  import { Client } from './client.mjs';
4
4
  import 'emittery';
5
+ import 'partysocket';
5
6
 
6
7
  declare class Cartesia extends Client {
7
8
  audio: export_default;
@@ -1,7 +1,8 @@
1
- import { e as export_default } from '../index-Ds4LDkmk.js';
1
+ import { e as export_default } from '../index-qwAyxV5I.js';
2
2
  import { ClientOptions } from '../types/index.js';
3
3
  import { Client } from './client.js';
4
4
  import 'emittery';
5
+ import 'partysocket';
5
6
 
6
7
  declare class Cartesia extends Client {
7
8
  audio: export_default;