@cartesia/cartesia-js 1.0.0-alpha.4 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.turbo/turbo-build.log +49 -49
  2. package/CHANGELOG.md +23 -0
  3. package/LICENSE.md +21 -0
  4. package/README.md +102 -21
  5. package/dist/{chunk-VK7LBMVI.js → chunk-2NA5SEML.js} +2 -2
  6. package/dist/{chunk-PQ5EVEEH.js → chunk-5M33ZF3Y.js} +1 -1
  7. package/dist/{chunk-PQ6CIPFW.js → chunk-6YQ6KDIQ.js} +44 -5
  8. package/dist/{chunk-IQAXBRHU.js → chunk-ASZKHN7Q.js} +53 -29
  9. package/dist/{chunk-RO7TY474.js → chunk-BHY7MNGT.js} +11 -6
  10. package/dist/{chunk-WIFMLPT5.js → chunk-GHY2WEOK.js} +13 -0
  11. package/dist/{chunk-SGXUEFII.js → chunk-KUSVZXDT.js} +2 -2
  12. package/dist/{chunk-36JBKJUN.js → chunk-LZO6K34D.js} +20 -7
  13. package/dist/{chunk-3FL2SNIR.js → chunk-NQVZNVOU.js} +1 -1
  14. package/dist/{chunk-ISRU7PLL.js → chunk-OFH3ML4L.js} +3 -3
  15. package/dist/index.cjs +129 -39
  16. package/dist/index.d.cts +4 -4
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.js +15 -9
  19. package/dist/lib/client.js +2 -2
  20. package/dist/lib/constants.js +1 -1
  21. package/dist/lib/index.cjs +106 -33
  22. package/dist/lib/index.js +8 -8
  23. package/dist/react/index.cjs +231 -92
  24. package/dist/react/index.d.cts +4 -3
  25. package/dist/react/index.d.ts +4 -3
  26. package/dist/react/index.js +117 -64
  27. package/dist/react/utils.js +2 -2
  28. package/dist/tts/index.cjs +106 -33
  29. package/dist/tts/index.js +6 -6
  30. package/dist/tts/player.cjs +23 -5
  31. package/dist/tts/player.d.cts +6 -0
  32. package/dist/tts/player.d.ts +6 -0
  33. package/dist/tts/player.js +4 -3
  34. package/dist/tts/source.cjs +50 -4
  35. package/dist/tts/source.d.cts +16 -6
  36. package/dist/tts/source.d.ts +16 -6
  37. package/dist/tts/source.js +4 -2
  38. package/dist/tts/utils.cjs +18 -6
  39. package/dist/tts/utils.d.cts +7 -5
  40. package/dist/tts/utils.d.ts +7 -5
  41. package/dist/tts/utils.js +3 -2
  42. package/dist/tts/websocket.cjs +106 -33
  43. package/dist/tts/websocket.d.cts +20 -10
  44. package/dist/tts/websocket.d.ts +20 -10
  45. package/dist/tts/websocket.js +5 -5
  46. package/dist/types/index.d.cts +60 -4
  47. package/dist/types/index.d.ts +60 -4
  48. package/dist/voices/index.js +3 -3
  49. package/package.json +1 -1
  50. package/src/index.ts +2 -0
  51. package/src/react/index.ts +117 -62
  52. package/src/tts/player.ts +15 -8
  53. package/src/tts/source.ts +53 -7
  54. package/src/tts/utils.ts +26 -12
  55. package/src/tts/websocket.ts +42 -19
  56. package/src/types/index.ts +81 -3
@@ -44,6 +44,10 @@ var __privateSet = (obj, member, value, setter) => {
44
44
  setter ? setter.call(obj, value) : member.set(obj, value);
45
45
  return value;
46
46
  };
47
+ var __privateMethod = (obj, member, method) => {
48
+ __accessCheck(obj, member, "access private method");
49
+ return method;
50
+ };
47
51
  var __async = (__this, __arguments, generator) => {
48
52
  return new Promise((resolve, reject) => {
49
53
  var fulfilled = (value) => {
@@ -68,11 +72,18 @@ var __async = (__this, __arguments, generator) => {
68
72
  // src/tts/source.ts
69
73
  var source_exports = {};
70
74
  __export(source_exports, {
75
+ ENCODING_MAP: () => ENCODING_MAP,
71
76
  default: () => Source
72
77
  });
73
78
  module.exports = __toCommonJS(source_exports);
74
79
  var import_emittery = __toESM(require("emittery"), 1);
75
- var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate;
80
+ var ENCODING_MAP = {
81
+ pcm_f32le: { arrayType: Float32Array, bytesPerElement: 4 },
82
+ pcm_s16le: { arrayType: Int16Array, bytesPerElement: 2 },
83
+ pcm_alaw: { arrayType: Uint8Array, bytesPerElement: 1 },
84
+ pcm_mulaw: { arrayType: Uint8Array, bytesPerElement: 1 }
85
+ };
86
+ var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate, _encoding, _container, _createBuffer, createBuffer_fn;
76
87
  var Source = class {
77
88
  /**
78
89
  * Create a new Source.
@@ -80,23 +91,44 @@ var Source = class {
80
91
  * @param options - Options for the Source.
81
92
  * @param options.sampleRate - The sample rate of the audio.
82
93
  */
83
- constructor({ sampleRate }) {
94
+ constructor({
95
+ sampleRate,
96
+ encoding,
97
+ container
98
+ }) {
99
+ /**
100
+ * Create a new buffer for the source.
101
+ *
102
+ * @param size - The size of the buffer to create.
103
+ * @returns The new buffer as a TypedArray based on the encoding.
104
+ */
105
+ __privateAdd(this, _createBuffer);
84
106
  __privateAdd(this, _emitter, new import_emittery.default());
85
107
  __privateAdd(this, _buffer, void 0);
86
108
  __privateAdd(this, _readIndex, 0);
87
109
  __privateAdd(this, _writeIndex, 0);
88
110
  __privateAdd(this, _closed, false);
89
111
  __privateAdd(this, _sampleRate, void 0);
112
+ __privateAdd(this, _encoding, void 0);
113
+ __privateAdd(this, _container, void 0);
90
114
  this.on = __privateGet(this, _emitter).on.bind(__privateGet(this, _emitter));
91
115
  this.once = __privateGet(this, _emitter).once.bind(__privateGet(this, _emitter));
92
116
  this.events = __privateGet(this, _emitter).events.bind(__privateGet(this, _emitter));
93
117
  this.off = __privateGet(this, _emitter).off.bind(__privateGet(this, _emitter));
94
118
  __privateSet(this, _sampleRate, sampleRate);
95
- __privateSet(this, _buffer, new Float32Array(1024));
119
+ __privateSet(this, _encoding, encoding);
120
+ __privateSet(this, _container, container);
121
+ __privateSet(this, _buffer, __privateMethod(this, _createBuffer, createBuffer_fn).call(this, 1024));
96
122
  }
97
123
  get sampleRate() {
98
124
  return __privateGet(this, _sampleRate);
99
125
  }
126
+ get encoding() {
127
+ return __privateGet(this, _encoding);
128
+ }
129
+ get container() {
130
+ return __privateGet(this, _container);
131
+ }
100
132
  /**
101
133
  * Append audio to the buffer.
102
134
  *
@@ -110,7 +142,7 @@ var Source = class {
110
142
  while (newCapacity < requiredCapacity) {
111
143
  newCapacity *= 2;
112
144
  }
113
- const newBuffer = new Float32Array(newCapacity);
145
+ const newBuffer = __privateMethod(this, _createBuffer, createBuffer_fn).call(this, newCapacity);
114
146
  newBuffer.set(__privateGet(this, _buffer));
115
147
  __privateSet(this, _buffer, newBuffer);
116
148
  }
@@ -158,6 +190,9 @@ var Source = class {
158
190
  get readIndex() {
159
191
  return __privateGet(this, _readIndex);
160
192
  }
193
+ get writeIndex() {
194
+ return __privateGet(this, _writeIndex);
195
+ }
161
196
  /**
162
197
  * Close the source. This signals that no more audio will be enqueued.
163
198
  *
@@ -179,3 +214,14 @@ _readIndex = new WeakMap();
179
214
  _writeIndex = new WeakMap();
180
215
  _closed = new WeakMap();
181
216
  _sampleRate = new WeakMap();
217
+ _encoding = new WeakMap();
218
+ _container = new WeakMap();
219
+ _createBuffer = new WeakSet();
220
+ createBuffer_fn = function(size) {
221
+ const { arrayType: ArrayType } = ENCODING_MAP[__privateGet(this, _encoding)];
222
+ return new ArrayType(size);
223
+ };
224
+ // Annotate the CommonJS export names for ESM import in node:
225
+ 0 && (module.exports = {
226
+ ENCODING_MAP
227
+ });
@@ -1,6 +1,11 @@
1
1
  import * as emittery from 'emittery';
2
- import { SourceEventData } from '../types/index.cjs';
2
+ import { Encoding, SourceEventData, TypedArray } from '../types/index.cjs';
3
3
 
4
+ type EncodingInfo = {
5
+ arrayType: Float32ArrayConstructor | Int16ArrayConstructor | Uint8ArrayConstructor;
6
+ bytesPerElement: number;
7
+ };
8
+ declare const ENCODING_MAP: Record<Encoding, EncodingInfo>;
4
9
  declare class Source {
5
10
  #private;
6
11
  on: <Name extends keyof SourceEventData | keyof emittery.OmnipresentEventData>(eventName: Name | readonly Name[], listener: (eventData: (SourceEventData & emittery.OmnipresentEventData)[Name]) => void | Promise<void>) => emittery.UnsubscribeFunction;
@@ -13,16 +18,20 @@ declare class Source {
13
18
  * @param options - Options for the Source.
14
19
  * @param options.sampleRate - The sample rate of the audio.
15
20
  */
16
- constructor({ sampleRate }: {
21
+ constructor({ sampleRate, encoding, container, }: {
17
22
  sampleRate: number;
23
+ encoding: string;
24
+ container: string;
18
25
  });
19
26
  get sampleRate(): number;
27
+ get encoding(): Encoding;
28
+ get container(): string;
20
29
  /**
21
30
  * Append audio to the buffer.
22
31
  *
23
32
  * @param src The audio to append.
24
33
  */
25
- enqueue(src: Float32Array): Promise<void>;
34
+ enqueue(src: TypedArray): Promise<void>;
26
35
  /**
27
36
  * Read audio from the buffer.
28
37
  *
@@ -30,7 +39,7 @@ declare class Source {
30
39
  * @returns The number of samples read. If the source is closed, this will be
31
40
  * less than the length of the provided buffer.
32
41
  */
33
- read(dst: Float32Array): Promise<number>;
42
+ read(dst: TypedArray): Promise<number>;
34
43
  /**
35
44
  * Get the number of samples in a given duration.
36
45
  *
@@ -38,8 +47,9 @@ declare class Source {
38
47
  * @returns The number of samples.
39
48
  */
40
49
  durationToSampleCount(durationSecs: number): number;
41
- get buffer(): Float32Array;
50
+ get buffer(): TypedArray;
42
51
  get readIndex(): number;
52
+ get writeIndex(): number;
43
53
  /**
44
54
  * Close the source. This signals that no more audio will be enqueued.
45
55
  *
@@ -50,4 +60,4 @@ declare class Source {
50
60
  close(): Promise<void>;
51
61
  }
52
62
 
53
- export { Source as default };
63
+ export { ENCODING_MAP, Source as default };
@@ -1,6 +1,11 @@
1
1
  import * as emittery from 'emittery';
2
- import { SourceEventData } from '../types/index.js';
2
+ import { Encoding, SourceEventData, TypedArray } from '../types/index.js';
3
3
 
4
+ type EncodingInfo = {
5
+ arrayType: Float32ArrayConstructor | Int16ArrayConstructor | Uint8ArrayConstructor;
6
+ bytesPerElement: number;
7
+ };
8
+ declare const ENCODING_MAP: Record<Encoding, EncodingInfo>;
4
9
  declare class Source {
5
10
  #private;
6
11
  on: <Name extends keyof SourceEventData | keyof emittery.OmnipresentEventData>(eventName: Name | readonly Name[], listener: (eventData: (SourceEventData & emittery.OmnipresentEventData)[Name]) => void | Promise<void>) => emittery.UnsubscribeFunction;
@@ -13,16 +18,20 @@ declare class Source {
13
18
  * @param options - Options for the Source.
14
19
  * @param options.sampleRate - The sample rate of the audio.
15
20
  */
16
- constructor({ sampleRate }: {
21
+ constructor({ sampleRate, encoding, container, }: {
17
22
  sampleRate: number;
23
+ encoding: string;
24
+ container: string;
18
25
  });
19
26
  get sampleRate(): number;
27
+ get encoding(): Encoding;
28
+ get container(): string;
20
29
  /**
21
30
  * Append audio to the buffer.
22
31
  *
23
32
  * @param src The audio to append.
24
33
  */
25
- enqueue(src: Float32Array): Promise<void>;
34
+ enqueue(src: TypedArray): Promise<void>;
26
35
  /**
27
36
  * Read audio from the buffer.
28
37
  *
@@ -30,7 +39,7 @@ declare class Source {
30
39
  * @returns The number of samples read. If the source is closed, this will be
31
40
  * less than the length of the provided buffer.
32
41
  */
33
- read(dst: Float32Array): Promise<number>;
42
+ read(dst: TypedArray): Promise<number>;
34
43
  /**
35
44
  * Get the number of samples in a given duration.
36
45
  *
@@ -38,8 +47,9 @@ declare class Source {
38
47
  * @returns The number of samples.
39
48
  */
40
49
  durationToSampleCount(durationSecs: number): number;
41
- get buffer(): Float32Array;
50
+ get buffer(): TypedArray;
42
51
  get readIndex(): number;
52
+ get writeIndex(): number;
43
53
  /**
44
54
  * Close the source. This signals that no more audio will be enqueued.
45
55
  *
@@ -50,4 +60,4 @@ declare class Source {
50
60
  close(): Promise<void>;
51
61
  }
52
62
 
53
- export { Source as default };
63
+ export { ENCODING_MAP, Source as default };
@@ -1,7 +1,9 @@
1
1
  import {
2
+ ENCODING_MAP,
2
3
  Source
3
- } from "../chunk-PQ6CIPFW.js";
4
- import "../chunk-WIFMLPT5.js";
4
+ } from "../chunk-6YQ6KDIQ.js";
5
+ import "../chunk-GHY2WEOK.js";
5
6
  export {
7
+ ENCODING_MAP,
6
8
  Source as default
7
9
  };
@@ -41,16 +41,28 @@ __export(utils_exports, {
41
41
  });
42
42
  module.exports = __toCommonJS(utils_exports);
43
43
  var import_base64_js = __toESM(require("base64-js"), 1);
44
- function base64ToArray(b64) {
44
+
45
+ // src/tts/source.ts
46
+ var import_emittery = __toESM(require("emittery"), 1);
47
+ var ENCODING_MAP = {
48
+ pcm_f32le: { arrayType: Float32Array, bytesPerElement: 4 },
49
+ pcm_s16le: { arrayType: Int16Array, bytesPerElement: 2 },
50
+ pcm_alaw: { arrayType: Uint8Array, bytesPerElement: 1 },
51
+ pcm_mulaw: { arrayType: Uint8Array, bytesPerElement: 1 }
52
+ };
53
+
54
+ // src/tts/utils.ts
55
+ function base64ToArray(b64, encoding) {
45
56
  const byteArrays = filterSentinel(b64).map((b) => import_base64_js.default.toByteArray(b));
57
+ const { arrayType: ArrayType, bytesPerElement } = ENCODING_MAP[encoding];
46
58
  const totalLength = byteArrays.reduce(
47
- (acc, arr) => acc + arr.length / Float32Array.BYTES_PER_ELEMENT,
59
+ (acc, arr) => acc + arr.length / bytesPerElement,
48
60
  0
49
61
  );
50
- const result = new Float32Array(totalLength);
62
+ const result = new ArrayType(totalLength);
51
63
  let offset = 0;
52
64
  for (const arr of byteArrays) {
53
- const floats = new Float32Array(arr.buffer);
65
+ const floats = new ArrayType(arr.buffer);
54
66
  result.set(floats, offset);
55
67
  offset += floats.length;
56
68
  }
@@ -81,10 +93,10 @@ function createMessageHandlerForContextId(contextId, handler) {
81
93
  let chunk;
82
94
  if (message.done) {
83
95
  chunk = getSentinel();
84
- } else {
96
+ } else if (message.type === "chunk") {
85
97
  chunk = message.data;
86
98
  }
87
- handler({ chunk, message: event.data });
99
+ handler({ chunk, message: event.data, data: message });
88
100
  };
89
101
  }
90
102
  function getSentinel() {
@@ -1,14 +1,15 @@
1
1
  import emittery__default from 'emittery';
2
- import { Chunk, Sentinel, EmitteryCallbacks } from '../types/index.cjs';
2
+ import { Chunk, TypedArray, WebSocketResponse, Sentinel, EmitteryCallbacks } from '../types/index.cjs';
3
3
 
4
4
  /**
5
- * Convert base64-encoded audio buffer(s) to a Float32Array.
5
+ * Convert base64-encoded audio buffer(s) to a TypedArray.
6
6
  *
7
7
  * @param b64 The base64-encoded audio buffer, or an array of base64-encoded
8
8
  * audio buffers.
9
- * @returns The audio buffer(s) as a Float32Array.
9
+ * @param encoding The encoding of the audio buffer(s).
10
+ * @returns The audio buffer(s) as a TypedArray.
10
11
  */
11
- declare function base64ToArray(b64: Chunk[]): Float32Array;
12
+ declare function base64ToArray(b64: Chunk[], encoding: string): TypedArray;
12
13
  /**
13
14
  * Schedule an audio buffer to play at a given time in the passed context.
14
15
  *
@@ -28,8 +29,9 @@ declare function playAudioBuffer(floats: Float32Array, context: AudioContext, st
28
29
  * @returns A message event handler.
29
30
  */
30
31
  declare function createMessageHandlerForContextId(contextId: string, handler: ({ chunk, message, }: {
31
- chunk: Chunk;
32
+ chunk?: Chunk;
32
33
  message: string;
34
+ data: WebSocketResponse;
33
35
  }) => void): (event: MessageEvent) => void;
34
36
  /**
35
37
  * Get a sentinel value that indicates the end of a stream.
@@ -1,14 +1,15 @@
1
1
  import emittery__default from 'emittery';
2
- import { Chunk, Sentinel, EmitteryCallbacks } from '../types/index.js';
2
+ import { Chunk, TypedArray, WebSocketResponse, Sentinel, EmitteryCallbacks } from '../types/index.js';
3
3
 
4
4
  /**
5
- * Convert base64-encoded audio buffer(s) to a Float32Array.
5
+ * Convert base64-encoded audio buffer(s) to a TypedArray.
6
6
  *
7
7
  * @param b64 The base64-encoded audio buffer, or an array of base64-encoded
8
8
  * audio buffers.
9
- * @returns The audio buffer(s) as a Float32Array.
9
+ * @param encoding The encoding of the audio buffer(s).
10
+ * @returns The audio buffer(s) as a TypedArray.
10
11
  */
11
- declare function base64ToArray(b64: Chunk[]): Float32Array;
12
+ declare function base64ToArray(b64: Chunk[], encoding: string): TypedArray;
12
13
  /**
13
14
  * Schedule an audio buffer to play at a given time in the passed context.
14
15
  *
@@ -28,8 +29,9 @@ declare function playAudioBuffer(floats: Float32Array, context: AudioContext, st
28
29
  * @returns A message event handler.
29
30
  */
30
31
  declare function createMessageHandlerForContextId(contextId: string, handler: ({ chunk, message, }: {
31
- chunk: Chunk;
32
+ chunk?: Chunk;
32
33
  message: string;
34
+ data: WebSocketResponse;
33
35
  }) => void): (event: MessageEvent) => void;
34
36
  /**
35
37
  * Get a sentinel value that indicates the end of a stream.
package/dist/tts/utils.js CHANGED
@@ -7,8 +7,9 @@ import {
7
7
  isComplete,
8
8
  isSentinel,
9
9
  playAudioBuffer
10
- } from "../chunk-RO7TY474.js";
11
- import "../chunk-WIFMLPT5.js";
10
+ } from "../chunk-BHY7MNGT.js";
11
+ import "../chunk-6YQ6KDIQ.js";
12
+ import "../chunk-GHY2WEOK.js";
12
13
  export {
13
14
  base64ToArray,
14
15
  createMessageHandlerForContextId,
@@ -22,6 +22,18 @@ var __spreadValues = (a, b) => {
22
22
  return a;
23
23
  };
24
24
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __objRest = (source, exclude) => {
26
+ var target = {};
27
+ for (var prop in source)
28
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
29
+ target[prop] = source[prop];
30
+ if (source != null && __getOwnPropSymbols)
31
+ for (var prop of __getOwnPropSymbols(source)) {
32
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
33
+ target[prop] = source[prop];
34
+ }
35
+ return target;
36
+ };
25
37
  var __export = (target, all) => {
26
38
  for (var name in all)
27
39
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -132,7 +144,13 @@ var Client = class {
132
144
 
133
145
  // src/tts/source.ts
134
146
  var import_emittery = __toESM(require("emittery"), 1);
135
- var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate;
147
+ var ENCODING_MAP = {
148
+ pcm_f32le: { arrayType: Float32Array, bytesPerElement: 4 },
149
+ pcm_s16le: { arrayType: Int16Array, bytesPerElement: 2 },
150
+ pcm_alaw: { arrayType: Uint8Array, bytesPerElement: 1 },
151
+ pcm_mulaw: { arrayType: Uint8Array, bytesPerElement: 1 }
152
+ };
153
+ var _emitter, _buffer, _readIndex, _writeIndex, _closed, _sampleRate, _encoding, _container, _createBuffer, createBuffer_fn;
136
154
  var Source = class {
137
155
  /**
138
156
  * Create a new Source.
@@ -140,23 +158,44 @@ var Source = class {
140
158
  * @param options - Options for the Source.
141
159
  * @param options.sampleRate - The sample rate of the audio.
142
160
  */
143
- constructor({ sampleRate }) {
161
+ constructor({
162
+ sampleRate,
163
+ encoding,
164
+ container
165
+ }) {
166
+ /**
167
+ * Create a new buffer for the source.
168
+ *
169
+ * @param size - The size of the buffer to create.
170
+ * @returns The new buffer as a TypedArray based on the encoding.
171
+ */
172
+ __privateAdd(this, _createBuffer);
144
173
  __privateAdd(this, _emitter, new import_emittery.default());
145
174
  __privateAdd(this, _buffer, void 0);
146
175
  __privateAdd(this, _readIndex, 0);
147
176
  __privateAdd(this, _writeIndex, 0);
148
177
  __privateAdd(this, _closed, false);
149
178
  __privateAdd(this, _sampleRate, void 0);
179
+ __privateAdd(this, _encoding, void 0);
180
+ __privateAdd(this, _container, void 0);
150
181
  this.on = __privateGet(this, _emitter).on.bind(__privateGet(this, _emitter));
151
182
  this.once = __privateGet(this, _emitter).once.bind(__privateGet(this, _emitter));
152
183
  this.events = __privateGet(this, _emitter).events.bind(__privateGet(this, _emitter));
153
184
  this.off = __privateGet(this, _emitter).off.bind(__privateGet(this, _emitter));
154
185
  __privateSet(this, _sampleRate, sampleRate);
155
- __privateSet(this, _buffer, new Float32Array(1024));
186
+ __privateSet(this, _encoding, encoding);
187
+ __privateSet(this, _container, container);
188
+ __privateSet(this, _buffer, __privateMethod(this, _createBuffer, createBuffer_fn).call(this, 1024));
156
189
  }
157
190
  get sampleRate() {
158
191
  return __privateGet(this, _sampleRate);
159
192
  }
193
+ get encoding() {
194
+ return __privateGet(this, _encoding);
195
+ }
196
+ get container() {
197
+ return __privateGet(this, _container);
198
+ }
160
199
  /**
161
200
  * Append audio to the buffer.
162
201
  *
@@ -170,7 +209,7 @@ var Source = class {
170
209
  while (newCapacity < requiredCapacity) {
171
210
  newCapacity *= 2;
172
211
  }
173
- const newBuffer = new Float32Array(newCapacity);
212
+ const newBuffer = __privateMethod(this, _createBuffer, createBuffer_fn).call(this, newCapacity);
174
213
  newBuffer.set(__privateGet(this, _buffer));
175
214
  __privateSet(this, _buffer, newBuffer);
176
215
  }
@@ -218,6 +257,9 @@ var Source = class {
218
257
  get readIndex() {
219
258
  return __privateGet(this, _readIndex);
220
259
  }
260
+ get writeIndex() {
261
+ return __privateGet(this, _writeIndex);
262
+ }
221
263
  /**
222
264
  * Close the source. This signals that no more audio will be enqueued.
223
265
  *
@@ -239,19 +281,27 @@ _readIndex = new WeakMap();
239
281
  _writeIndex = new WeakMap();
240
282
  _closed = new WeakMap();
241
283
  _sampleRate = new WeakMap();
284
+ _encoding = new WeakMap();
285
+ _container = new WeakMap();
286
+ _createBuffer = new WeakSet();
287
+ createBuffer_fn = function(size) {
288
+ const { arrayType: ArrayType } = ENCODING_MAP[__privateGet(this, _encoding)];
289
+ return new ArrayType(size);
290
+ };
242
291
 
243
292
  // src/tts/utils.ts
244
293
  var import_base64_js = __toESM(require("base64-js"), 1);
245
- function base64ToArray(b64) {
294
+ function base64ToArray(b64, encoding) {
246
295
  const byteArrays = filterSentinel(b64).map((b) => import_base64_js.default.toByteArray(b));
296
+ const { arrayType: ArrayType, bytesPerElement } = ENCODING_MAP[encoding];
247
297
  const totalLength = byteArrays.reduce(
248
- (acc, arr) => acc + arr.length / Float32Array.BYTES_PER_ELEMENT,
298
+ (acc, arr) => acc + arr.length / bytesPerElement,
249
299
  0
250
300
  );
251
- const result = new Float32Array(totalLength);
301
+ const result = new ArrayType(totalLength);
252
302
  let offset = 0;
253
303
  for (const arr of byteArrays) {
254
- const floats = new Float32Array(arr.buffer);
304
+ const floats = new ArrayType(arr.buffer);
255
305
  result.set(floats, offset);
256
306
  offset += floats.length;
257
307
  }
@@ -269,10 +319,10 @@ function createMessageHandlerForContextId(contextId, handler) {
269
319
  let chunk;
270
320
  if (message.done) {
271
321
  chunk = getSentinel();
272
- } else {
322
+ } else if (message.type === "chunk") {
273
323
  chunk = message.data;
274
324
  }
275
- handler({ chunk, message: event.data });
325
+ handler({ chunk, message: event.data, data: message });
276
326
  };
277
327
  }
278
328
  function getSentinel() {
@@ -296,14 +346,14 @@ function getEmitteryCallbacks(emitter) {
296
346
  }
297
347
 
298
348
  // src/tts/websocket.ts
299
- var _isConnected, _sampleRate2, _generateId, generateId_fn;
349
+ var _isConnected, _sampleRate2, _container2, _encoding2, _generateId, generateId_fn;
300
350
  var WebSocket = class extends Client {
301
351
  /**
302
352
  * Create a new WebSocket client.
303
353
  *
304
354
  * @param args - Arguments to pass to the Client constructor.
305
355
  */
306
- constructor({ sampleRate }, ...args) {
356
+ constructor({ sampleRate, container, encoding }, ...args) {
307
357
  super(...args);
308
358
  /**
309
359
  * Generate a unique ID suitable for a streaming context.
@@ -316,37 +366,47 @@ var WebSocket = class extends Client {
316
366
  __privateAdd(this, _generateId);
317
367
  __privateAdd(this, _isConnected, false);
318
368
  __privateAdd(this, _sampleRate2, void 0);
369
+ __privateAdd(this, _container2, void 0);
370
+ __privateAdd(this, _encoding2, void 0);
319
371
  __privateSet(this, _sampleRate2, sampleRate);
372
+ __privateSet(this, _container2, container != null ? container : "raw");
373
+ __privateSet(this, _encoding2, encoding != null ? encoding : "pcm_f32le");
320
374
  }
321
375
  /**
322
- * Send a message over the WebSocket in order to start a stream.
376
+ * Send a message over the WebSocket to start a stream.
323
377
  *
324
- * @param inputs - Stream options.
378
+ * @param inputs - Stream options. Defined in the StreamRequest type.
325
379
  * @param options - Options for the stream.
326
380
  * @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
327
- * If `0`, the stream will not time out.
381
+ * If set to `0`, the stream will not time out.
328
382
  * @returns A Source object that can be passed to a Player to play the audio.
383
+ * @returns An Emittery instance that emits messages from the WebSocket.
384
+ * @returns An abort function that can be called to cancel the stream.
329
385
  */
330
- send(inputs, { timeout = 0 } = {}) {
331
- var _a, _b, _c, _d;
386
+ send(_a, { timeout = 0 } = {}) {
387
+ var inputs = __objRest(_a, []);
388
+ var _a2, _b, _c, _d;
332
389
  if (!__privateGet(this, _isConnected)) {
333
390
  throw new Error("Not connected to WebSocket. Call .connect() first.");
334
391
  }
335
- const contextId = __privateMethod(this, _generateId, generateId_fn).call(this);
336
- (_a = this.socket) == null ? void 0 : _a.send(
337
- JSON.stringify(__spreadProps(__spreadValues({
338
- context_id: contextId
339
- }, inputs), {
340
- output_format: {
341
- container: "raw",
342
- encoding: "pcm_f32le",
343
- sample_rate: __privateGet(this, _sampleRate2)
344
- }
345
- }))
392
+ if (!inputs.context_id) {
393
+ inputs.context_id = __privateMethod(this, _generateId, generateId_fn).call(this);
394
+ }
395
+ if (!inputs.output_format) {
396
+ inputs.output_format = {
397
+ container: __privateGet(this, _container2),
398
+ encoding: __privateGet(this, _encoding2),
399
+ sample_rate: __privateGet(this, _sampleRate2)
400
+ };
401
+ }
402
+ (_a2 = this.socket) == null ? void 0 : _a2.send(
403
+ JSON.stringify(__spreadValues({}, inputs))
346
404
  );
347
405
  const emitter = new import_emittery2.default();
348
406
  const source = new Source({
349
- sampleRate: __privateGet(this, _sampleRate2)
407
+ sampleRate: __privateGet(this, _sampleRate2),
408
+ encoding: __privateGet(this, _encoding2),
409
+ container: __privateGet(this, _container2)
350
410
  });
351
411
  const streamCompleteController = new AbortController();
352
412
  let timeoutId = null;
@@ -354,19 +414,26 @@ var WebSocket = class extends Client {
354
414
  timeoutId = setTimeout(streamCompleteController.abort, timeout);
355
415
  }
356
416
  const handleMessage = createMessageHandlerForContextId(
357
- contextId,
358
- (_0) => __async(this, [_0], function* ({ chunk, message }) {
417
+ inputs.context_id,
418
+ (_0) => __async(this, [_0], function* ({ chunk, message, data }) {
359
419
  emitter.emit("message", message);
420
+ if (data.type === "timestamps") {
421
+ emitter.emit("timestamps", data.word_timestamps);
422
+ return;
423
+ }
360
424
  if (isSentinel(chunk)) {
361
425
  yield source.close();
362
426
  streamCompleteController.abort();
363
427
  return;
364
428
  }
365
- yield source.enqueue(base64ToArray([chunk]));
366
429
  if (timeoutId) {
367
430
  clearTimeout(timeoutId);
368
431
  timeoutId = setTimeout(streamCompleteController.abort, timeout);
369
432
  }
433
+ if (!chunk) {
434
+ return;
435
+ }
436
+ yield source.enqueue(base64ToArray([chunk], __privateGet(this, _encoding2)));
370
437
  })
371
438
  );
372
439
  (_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
@@ -396,7 +463,11 @@ var WebSocket = class extends Client {
396
463
  clearTimeout(timeoutId);
397
464
  }
398
465
  });
399
- return __spreadValues({ source }, getEmitteryCallbacks(emitter));
466
+ return __spreadProps(__spreadValues({
467
+ source
468
+ }, getEmitteryCallbacks(emitter)), {
469
+ stop: streamCompleteController.abort.bind(streamCompleteController)
470
+ });
400
471
  }
401
472
  /**
402
473
  * Authenticate and connect to a Cartesia streaming WebSocket.
@@ -466,6 +537,8 @@ var WebSocket = class extends Client {
466
537
  };
467
538
  _isConnected = new WeakMap();
468
539
  _sampleRate2 = new WeakMap();
540
+ _container2 = new WeakMap();
541
+ _encoding2 = new WeakMap();
469
542
  _generateId = new WeakSet();
470
543
  generateId_fn = function() {
471
544
  return (0, import_human_id.humanId)({