@cartesia/cartesia-js 1.0.2 → 1.1.0

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 (48) hide show
  1. package/.turbo/turbo-build.log +41 -41
  2. package/CHANGELOG.md +12 -0
  3. package/README.md +43 -9
  4. package/dist/{chunk-NQVZNVOU.js → chunk-3FL2SNIR.js} +1 -1
  5. package/dist/{chunk-NVOCUUOF.js → chunk-4GEDAGVY.js} +3 -3
  6. package/dist/{chunk-PISCPZK4.js → chunk-6PWLZAMS.js} +1 -1
  7. package/dist/{chunk-UCYL2SOX.js → chunk-CWIJUBG6.js} +20 -2
  8. package/dist/{chunk-IZBPLCGW.js → chunk-L3OMQKWL.js} +35 -10
  9. package/dist/{chunk-LZO6K34D.js → chunk-MNOPO7G6.js} +2 -2
  10. package/dist/{chunk-EDAAHENY.js → chunk-MUPVAEL7.js} +2 -2
  11. package/dist/{chunk-BHY7MNGT.js → chunk-VCZESWYA.js} +1 -1
  12. package/dist/{chunk-6YQ6KDIQ.js → chunk-VVDJR3OA.js} +32 -1
  13. package/dist/{chunk-GHY2WEOK.js → chunk-WIFMLPT5.js} +0 -13
  14. package/dist/index.cjs +80 -17
  15. package/dist/index.d.cts +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +9 -9
  18. package/dist/lib/client.js +2 -2
  19. package/dist/lib/constants.js +1 -1
  20. package/dist/lib/index.cjs +80 -17
  21. package/dist/lib/index.js +8 -8
  22. package/dist/react/index.cjs +83 -17
  23. package/dist/react/index.js +13 -10
  24. package/dist/react/utils.js +2 -2
  25. package/dist/tts/index.cjs +62 -17
  26. package/dist/tts/index.js +6 -6
  27. package/dist/tts/player.js +4 -4
  28. package/dist/tts/source.cjs +31 -0
  29. package/dist/tts/source.d.cts +9 -0
  30. package/dist/tts/source.d.ts +9 -0
  31. package/dist/tts/source.js +2 -2
  32. package/dist/tts/utils.js +3 -3
  33. package/dist/tts/websocket.cjs +62 -17
  34. package/dist/tts/websocket.d.cts +9 -3
  35. package/dist/tts/websocket.d.ts +9 -3
  36. package/dist/tts/websocket.js +5 -5
  37. package/dist/types/index.d.cts +32 -6
  38. package/dist/types/index.d.ts +32 -6
  39. package/dist/voices/index.cjs +18 -0
  40. package/dist/voices/index.d.cts +3 -1
  41. package/dist/voices/index.d.ts +3 -1
  42. package/dist/voices/index.js +3 -3
  43. package/package.json +1 -1
  44. package/src/react/index.ts +4 -0
  45. package/src/tts/source.ts +35 -0
  46. package/src/tts/websocket.ts +35 -2
  47. package/src/types/index.ts +46 -5
  48. package/src/voices/index.ts +22 -0
package/dist/tts/utils.js CHANGED
@@ -7,9 +7,9 @@ import {
7
7
  isComplete,
8
8
  isSentinel,
9
9
  playAudioBuffer
10
- } from "../chunk-BHY7MNGT.js";
11
- import "../chunk-6YQ6KDIQ.js";
12
- import "../chunk-GHY2WEOK.js";
10
+ } from "../chunk-VCZESWYA.js";
11
+ import "../chunk-VVDJR3OA.js";
12
+ import "../chunk-WIFMLPT5.js";
13
13
  export {
14
14
  base64ToArray,
15
15
  createMessageHandlerForContextId,
@@ -22,18 +22,6 @@ 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
- };
37
25
  var __export = (target, all) => {
38
26
  for (var name in all)
39
27
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -247,6 +235,37 @@ var Source = class {
247
235
  return read;
248
236
  });
249
237
  }
238
+ /**
239
+ * Seek in the buffer.
240
+ *
241
+ * @param offset The offset to seek to.
242
+ * @param whence The position to seek from.
243
+ * @returns The new position in the buffer.
244
+ * @throws {Error} If the seek is invalid.
245
+ */
246
+ seek(offset, whence) {
247
+ return __async(this, null, function* () {
248
+ let position = __privateGet(this, _readIndex);
249
+ switch (whence) {
250
+ case "start":
251
+ position = offset;
252
+ break;
253
+ case "current":
254
+ position += offset;
255
+ break;
256
+ case "end":
257
+ position = __privateGet(this, _writeIndex) + offset;
258
+ break;
259
+ default:
260
+ throw new Error(`Invalid seek mode: ${whence}`);
261
+ }
262
+ if (position < 0 || position > __privateGet(this, _writeIndex)) {
263
+ throw new Error("Seek out of bounds");
264
+ }
265
+ __privateSet(this, _readIndex, position);
266
+ return position;
267
+ });
268
+ }
250
269
  /**
251
270
  * Get the number of samples in a given duration.
252
271
  *
@@ -380,7 +399,7 @@ var WebSocket = class extends Client {
380
399
  /**
381
400
  * Send a message over the WebSocket to start a stream.
382
401
  *
383
- * @param inputs - Stream options. Defined in the StreamRequest type.
402
+ * @param inputs - Generation parameters. Defined in the StreamRequest type.
384
403
  * @param options - Options for the stream.
385
404
  * @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
386
405
  * If set to `0`, the stream will not time out.
@@ -388,9 +407,8 @@ var WebSocket = class extends Client {
388
407
  * @returns An Emittery instance that emits messages from the WebSocket.
389
408
  * @returns An abort function that can be called to cancel the stream.
390
409
  */
391
- send(_a, { timeout = 0 } = {}) {
392
- var inputs = __objRest(_a, []);
393
- var _a2, _b, _c, _d;
410
+ send(inputs, { timeout = 0 } = {}) {
411
+ var _a, _b, _c, _d;
394
412
  if (!__privateGet(this, _isConnected)) {
395
413
  throw new Error("Not connected to WebSocket. Call .connect() first.");
396
414
  }
@@ -404,7 +422,7 @@ var WebSocket = class extends Client {
404
422
  sample_rate: __privateGet(this, _sampleRate2)
405
423
  };
406
424
  }
407
- (_a2 = this.socket) == null ? void 0 : _a2.send(
425
+ (_a = this.socket) == null ? void 0 : _a.send(
408
426
  JSON.stringify(__spreadValues({}, inputs))
409
427
  );
410
428
  const emitter = new import_emittery2.default();
@@ -474,6 +492,32 @@ var WebSocket = class extends Client {
474
492
  stop: streamCompleteController.abort.bind(streamCompleteController)
475
493
  });
476
494
  }
495
+ /**
496
+ * Continue a stream.
497
+ *
498
+ * @param inputs - Generation parameters. Defined in the StreamRequest type, but must include a `context_id` field. `continue` is set to true by default.
499
+ */
500
+ continue(inputs) {
501
+ var _a;
502
+ if (!__privateGet(this, _isConnected)) {
503
+ throw new Error("Not connected to WebSocket. Call .connect() first.");
504
+ }
505
+ if (!inputs.context_id) {
506
+ throw new Error("context_id is required to continue a context.");
507
+ }
508
+ if (!inputs.output_format) {
509
+ inputs.output_format = {
510
+ container: __privateGet(this, _container2),
511
+ encoding: __privateGet(this, _encoding2),
512
+ sample_rate: __privateGet(this, _sampleRate2)
513
+ };
514
+ }
515
+ (_a = this.socket) == null ? void 0 : _a.send(
516
+ JSON.stringify(__spreadValues({
517
+ continue: true
518
+ }, inputs))
519
+ );
520
+ }
477
521
  /**
478
522
  * Authenticate and connect to a Cartesia streaming WebSocket.
479
523
  *
@@ -491,6 +535,7 @@ var WebSocket = class extends Client {
491
535
  url.searchParams.set("cartesia_version", CARTESIA_VERSION);
492
536
  return url.toString();
493
537
  }));
538
+ this.socket.binaryType = "arraybuffer";
494
539
  this.socket.onopen = () => {
495
540
  __privateSet(this, _isConnected, true);
496
541
  emitter.emit("open");
@@ -1,7 +1,7 @@
1
1
  import * as emittery from 'emittery';
2
2
  import { WebSocket as WebSocket$1 } from 'partysocket';
3
3
  import { Client } from '../lib/client.cjs';
4
- import { WebSocketOptions, StreamRequest, StreamOptions, WordTimestamps, EmitteryCallbacks, ConnectionEventData } from '../types/index.cjs';
4
+ import { WebSocketOptions, StreamRequest, StreamOptions, WordTimestamps, ContinueRequest, EmitteryCallbacks, ConnectionEventData } from '../types/index.cjs';
5
5
  import Source from './source.cjs';
6
6
 
7
7
  declare class WebSocket extends Client {
@@ -16,7 +16,7 @@ declare class WebSocket extends Client {
16
16
  /**
17
17
  * Send a message over the WebSocket to start a stream.
18
18
  *
19
- * @param inputs - Stream options. Defined in the StreamRequest type.
19
+ * @param inputs - Generation parameters. Defined in the StreamRequest type.
20
20
  * @param options - Options for the stream.
21
21
  * @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
22
22
  * If set to `0`, the stream will not time out.
@@ -24,7 +24,7 @@ declare class WebSocket extends Client {
24
24
  * @returns An Emittery instance that emits messages from the WebSocket.
25
25
  * @returns An abort function that can be called to cancel the stream.
26
26
  */
27
- send({ ...inputs }: StreamRequest, { timeout }?: StreamOptions): {
27
+ send(inputs: StreamRequest, { timeout }?: StreamOptions): {
28
28
  stop: {
29
29
  (reason?: any): void;
30
30
  (reason?: any): void;
@@ -47,6 +47,12 @@ declare class WebSocket extends Client {
47
47
  }[Name_3]>;
48
48
  source: Source;
49
49
  };
50
+ /**
51
+ * Continue a stream.
52
+ *
53
+ * @param inputs - Generation parameters. Defined in the StreamRequest type, but must include a `context_id` field. `continue` is set to true by default.
54
+ */
55
+ continue(inputs: ContinueRequest): void;
50
56
  /**
51
57
  * Authenticate and connect to a Cartesia streaming WebSocket.
52
58
  *
@@ -1,7 +1,7 @@
1
1
  import * as emittery from 'emittery';
2
2
  import { WebSocket as WebSocket$1 } from 'partysocket';
3
3
  import { Client } from '../lib/client.js';
4
- import { WebSocketOptions, StreamRequest, StreamOptions, WordTimestamps, EmitteryCallbacks, ConnectionEventData } from '../types/index.js';
4
+ import { WebSocketOptions, StreamRequest, StreamOptions, WordTimestamps, ContinueRequest, EmitteryCallbacks, ConnectionEventData } from '../types/index.js';
5
5
  import Source from './source.js';
6
6
 
7
7
  declare class WebSocket extends Client {
@@ -16,7 +16,7 @@ declare class WebSocket extends Client {
16
16
  /**
17
17
  * Send a message over the WebSocket to start a stream.
18
18
  *
19
- * @param inputs - Stream options. Defined in the StreamRequest type.
19
+ * @param inputs - Generation parameters. Defined in the StreamRequest type.
20
20
  * @param options - Options for the stream.
21
21
  * @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
22
22
  * If set to `0`, the stream will not time out.
@@ -24,7 +24,7 @@ declare class WebSocket extends Client {
24
24
  * @returns An Emittery instance that emits messages from the WebSocket.
25
25
  * @returns An abort function that can be called to cancel the stream.
26
26
  */
27
- send({ ...inputs }: StreamRequest, { timeout }?: StreamOptions): {
27
+ send(inputs: StreamRequest, { timeout }?: StreamOptions): {
28
28
  stop: {
29
29
  (reason?: any): void;
30
30
  (reason?: any): void;
@@ -47,6 +47,12 @@ declare class WebSocket extends Client {
47
47
  }[Name_3]>;
48
48
  source: Source;
49
49
  };
50
+ /**
51
+ * Continue a stream.
52
+ *
53
+ * @param inputs - Generation parameters. Defined in the StreamRequest type, but must include a `context_id` field. `continue` is set to true by default.
54
+ */
55
+ continue(inputs: ContinueRequest): void;
50
56
  /**
51
57
  * Authenticate and connect to a Cartesia streaming WebSocket.
52
58
  *
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  WebSocket
3
- } from "../chunk-IZBPLCGW.js";
4
- import "../chunk-PISCPZK4.js";
3
+ } from "../chunk-L3OMQKWL.js";
4
+ import "../chunk-6PWLZAMS.js";
5
5
  import "../chunk-2BFEKY3F.js";
6
- import "../chunk-BHY7MNGT.js";
7
- import "../chunk-6YQ6KDIQ.js";
8
- import "../chunk-GHY2WEOK.js";
6
+ import "../chunk-VCZESWYA.js";
7
+ import "../chunk-VVDJR3OA.js";
8
+ import "../chunk-WIFMLPT5.js";
9
9
  export {
10
10
  WebSocket as default
11
11
  };
@@ -11,10 +11,10 @@ type ConnectionEventData = {
11
11
  close: never;
12
12
  };
13
13
  type VoiceSpecifier = {
14
- mode: "id";
14
+ mode?: "id";
15
15
  id: string;
16
16
  } | {
17
- mode: "embedding";
17
+ mode?: "embedding";
18
18
  embedding: number[];
19
19
  };
20
20
  type Emotion = "anger" | "sadness" | "positivity" | "curiosity" | "surprise";
@@ -22,7 +22,7 @@ type Intensity = "lowest" | "low" | "high" | "highest";
22
22
  type EmotionControl = Emotion | `${Emotion}:${Intensity}`;
23
23
  type VoiceOptions = VoiceSpecifier & {
24
24
  __experimental_controls?: {
25
- speed?: "slowest" | "slow" | "normal" | "fast" | "fastest";
25
+ speed?: "slowest" | "slow" | "normal" | "fast" | "fastest" | number;
26
26
  emotion?: EmotionControl[];
27
27
  };
28
28
  };
@@ -38,9 +38,13 @@ type StreamRequest = {
38
38
  context_id?: string;
39
39
  continue?: boolean;
40
40
  duration?: number;
41
- language?: string;
41
+ language?: Language;
42
42
  add_timestamps?: boolean;
43
43
  };
44
+ type ContinueRequest = StreamRequest & {
45
+ context_id: string;
46
+ };
47
+ type Language = "en" | "es" | "fr" | "de" | "ja" | "zh" | "pt" | (string & {});
44
48
  type StreamOptions = {
45
49
  timeout?: number;
46
50
  };
@@ -83,6 +87,22 @@ type CloneOptions = {
83
87
  clip: Blob;
84
88
  enhance?: boolean;
85
89
  };
90
+ type LocalizeOptions = {
91
+ mode: "embedding";
92
+ embedding: number[];
93
+ } & {
94
+ language: Language;
95
+ dialect: string & {};
96
+ original_speaker_gender: "male" | "female" | (string & {});
97
+ };
98
+ interface VoiceToMix {
99
+ id?: string;
100
+ embedding?: number[];
101
+ weight: number;
102
+ }
103
+ interface MixVoicesOptions {
104
+ voices: VoiceToMix[];
105
+ }
86
106
  type Voice = {
87
107
  id: string;
88
108
  name: string;
@@ -91,13 +111,19 @@ type Voice = {
91
111
  is_public: boolean;
92
112
  user_id: string;
93
113
  created_at: string;
94
- language: string;
114
+ language: Language;
95
115
  };
96
116
  type CreateVoice = Pick<Voice, "name" | "description" | "embedding"> & Partial<Omit<Voice, "name" | "description" | "embedding">>;
97
117
  type UpdateVoice = Partial<Pick<Voice, "name" | "description" | "embedding">>;
98
118
  type CloneResponse = {
99
119
  embedding: number[];
100
120
  };
121
+ type LocalizeResponse = {
122
+ embedding: number[];
123
+ };
124
+ type MixVoicesResponse = {
125
+ embedding: number[];
126
+ };
101
127
  type WebSocketOptions = {
102
128
  container?: string;
103
129
  encoding?: string;
@@ -112,4 +138,4 @@ type SourceEventData = {
112
138
  type TypedArray = Float32Array | Int16Array | Uint8Array;
113
139
  type Encoding = "pcm_f32le" | "pcm_s16le" | "pcm_alaw" | "pcm_mulaw";
114
140
 
115
- export type { Chunk, ClientOptions, CloneOptions, CloneResponse, ConnectionEventData, CreateVoice, EmitteryCallbacks, Emotion, EmotionControl, Encoding, Intensity, Sentinel, SourceEventData, StreamOptions, StreamRequest, TypedArray, UpdateVoice, Voice, VoiceOptions, VoiceSpecifier, WebSocketBaseResponse, WebSocketChunkResponse, WebSocketErrorResponse, WebSocketOptions, WebSocketResponse, WebSocketTimestampsResponse, WordTimestamps };
141
+ export type { Chunk, ClientOptions, CloneOptions, CloneResponse, ConnectionEventData, ContinueRequest, CreateVoice, EmitteryCallbacks, Emotion, EmotionControl, Encoding, Intensity, Language, LocalizeOptions, LocalizeResponse, MixVoicesOptions, MixVoicesResponse, Sentinel, SourceEventData, StreamOptions, StreamRequest, TypedArray, UpdateVoice, Voice, VoiceOptions, VoiceSpecifier, VoiceToMix, WebSocketBaseResponse, WebSocketChunkResponse, WebSocketErrorResponse, WebSocketOptions, WebSocketResponse, WebSocketTimestampsResponse, WordTimestamps };
@@ -11,10 +11,10 @@ type ConnectionEventData = {
11
11
  close: never;
12
12
  };
13
13
  type VoiceSpecifier = {
14
- mode: "id";
14
+ mode?: "id";
15
15
  id: string;
16
16
  } | {
17
- mode: "embedding";
17
+ mode?: "embedding";
18
18
  embedding: number[];
19
19
  };
20
20
  type Emotion = "anger" | "sadness" | "positivity" | "curiosity" | "surprise";
@@ -22,7 +22,7 @@ type Intensity = "lowest" | "low" | "high" | "highest";
22
22
  type EmotionControl = Emotion | `${Emotion}:${Intensity}`;
23
23
  type VoiceOptions = VoiceSpecifier & {
24
24
  __experimental_controls?: {
25
- speed?: "slowest" | "slow" | "normal" | "fast" | "fastest";
25
+ speed?: "slowest" | "slow" | "normal" | "fast" | "fastest" | number;
26
26
  emotion?: EmotionControl[];
27
27
  };
28
28
  };
@@ -38,9 +38,13 @@ type StreamRequest = {
38
38
  context_id?: string;
39
39
  continue?: boolean;
40
40
  duration?: number;
41
- language?: string;
41
+ language?: Language;
42
42
  add_timestamps?: boolean;
43
43
  };
44
+ type ContinueRequest = StreamRequest & {
45
+ context_id: string;
46
+ };
47
+ type Language = "en" | "es" | "fr" | "de" | "ja" | "zh" | "pt" | (string & {});
44
48
  type StreamOptions = {
45
49
  timeout?: number;
46
50
  };
@@ -83,6 +87,22 @@ type CloneOptions = {
83
87
  clip: Blob;
84
88
  enhance?: boolean;
85
89
  };
90
+ type LocalizeOptions = {
91
+ mode: "embedding";
92
+ embedding: number[];
93
+ } & {
94
+ language: Language;
95
+ dialect: string & {};
96
+ original_speaker_gender: "male" | "female" | (string & {});
97
+ };
98
+ interface VoiceToMix {
99
+ id?: string;
100
+ embedding?: number[];
101
+ weight: number;
102
+ }
103
+ interface MixVoicesOptions {
104
+ voices: VoiceToMix[];
105
+ }
86
106
  type Voice = {
87
107
  id: string;
88
108
  name: string;
@@ -91,13 +111,19 @@ type Voice = {
91
111
  is_public: boolean;
92
112
  user_id: string;
93
113
  created_at: string;
94
- language: string;
114
+ language: Language;
95
115
  };
96
116
  type CreateVoice = Pick<Voice, "name" | "description" | "embedding"> & Partial<Omit<Voice, "name" | "description" | "embedding">>;
97
117
  type UpdateVoice = Partial<Pick<Voice, "name" | "description" | "embedding">>;
98
118
  type CloneResponse = {
99
119
  embedding: number[];
100
120
  };
121
+ type LocalizeResponse = {
122
+ embedding: number[];
123
+ };
124
+ type MixVoicesResponse = {
125
+ embedding: number[];
126
+ };
101
127
  type WebSocketOptions = {
102
128
  container?: string;
103
129
  encoding?: string;
@@ -112,4 +138,4 @@ type SourceEventData = {
112
138
  type TypedArray = Float32Array | Int16Array | Uint8Array;
113
139
  type Encoding = "pcm_f32le" | "pcm_s16le" | "pcm_alaw" | "pcm_mulaw";
114
140
 
115
- export type { Chunk, ClientOptions, CloneOptions, CloneResponse, ConnectionEventData, CreateVoice, EmitteryCallbacks, Emotion, EmotionControl, Encoding, Intensity, Sentinel, SourceEventData, StreamOptions, StreamRequest, TypedArray, UpdateVoice, Voice, VoiceOptions, VoiceSpecifier, WebSocketBaseResponse, WebSocketChunkResponse, WebSocketErrorResponse, WebSocketOptions, WebSocketResponse, WebSocketTimestampsResponse, WordTimestamps };
141
+ export type { Chunk, ClientOptions, CloneOptions, CloneResponse, ConnectionEventData, ContinueRequest, CreateVoice, EmitteryCallbacks, Emotion, EmotionControl, Encoding, Intensity, Language, LocalizeOptions, LocalizeResponse, MixVoicesOptions, MixVoicesResponse, Sentinel, SourceEventData, StreamOptions, StreamRequest, TypedArray, UpdateVoice, Voice, VoiceOptions, VoiceSpecifier, VoiceToMix, WebSocketBaseResponse, WebSocketChunkResponse, WebSocketErrorResponse, WebSocketOptions, WebSocketResponse, WebSocketTimestampsResponse, WordTimestamps };
@@ -159,4 +159,22 @@ var Voices = class extends Client {
159
159
  throw new Error("Invalid mode for clone()");
160
160
  });
161
161
  }
162
+ mix(options) {
163
+ return __async(this, null, function* () {
164
+ const response = yield this._fetch("/voices/mix", {
165
+ method: "POST",
166
+ body: JSON.stringify(options)
167
+ });
168
+ return response.json();
169
+ });
170
+ }
171
+ localize(options) {
172
+ return __async(this, null, function* () {
173
+ const response = yield this._fetch("/voices/localize", {
174
+ method: "POST",
175
+ body: JSON.stringify(options)
176
+ });
177
+ return response.json();
178
+ });
179
+ }
162
180
  };
@@ -1,5 +1,5 @@
1
1
  import { Client } from '../lib/client.cjs';
2
- import { Voice, CreateVoice, UpdateVoice, CloneOptions, CloneResponse } from '../types/index.cjs';
2
+ import { Voice, CreateVoice, UpdateVoice, CloneOptions, CloneResponse, MixVoicesOptions, MixVoicesResponse, LocalizeOptions, LocalizeResponse } from '../types/index.cjs';
3
3
  import 'emittery';
4
4
 
5
5
  declare class Voices extends Client {
@@ -8,6 +8,8 @@ declare class Voices extends Client {
8
8
  create(voice: CreateVoice): Promise<Voice>;
9
9
  update(id: string, voice: UpdateVoice): Promise<Voice>;
10
10
  clone(options: CloneOptions): Promise<CloneResponse>;
11
+ mix(options: MixVoicesOptions): Promise<MixVoicesResponse>;
12
+ localize(options: LocalizeOptions): Promise<LocalizeResponse>;
11
13
  }
12
14
 
13
15
  export { Voices as default };
@@ -1,5 +1,5 @@
1
1
  import { Client } from '../lib/client.js';
2
- import { Voice, CreateVoice, UpdateVoice, CloneOptions, CloneResponse } from '../types/index.js';
2
+ import { Voice, CreateVoice, UpdateVoice, CloneOptions, CloneResponse, MixVoicesOptions, MixVoicesResponse, LocalizeOptions, LocalizeResponse } from '../types/index.js';
3
3
  import 'emittery';
4
4
 
5
5
  declare class Voices extends Client {
@@ -8,6 +8,8 @@ declare class Voices extends Client {
8
8
  create(voice: CreateVoice): Promise<Voice>;
9
9
  update(id: string, voice: UpdateVoice): Promise<Voice>;
10
10
  clone(options: CloneOptions): Promise<CloneResponse>;
11
+ mix(options: MixVoicesOptions): Promise<MixVoicesResponse>;
12
+ localize(options: LocalizeOptions): Promise<LocalizeResponse>;
11
13
  }
12
14
 
13
15
  export { Voices as default };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Voices
3
- } from "../chunk-UCYL2SOX.js";
4
- import "../chunk-PISCPZK4.js";
3
+ } from "../chunk-CWIJUBG6.js";
4
+ import "../chunk-6PWLZAMS.js";
5
5
  import "../chunk-2BFEKY3F.js";
6
- import "../chunk-GHY2WEOK.js";
6
+ import "../chunk-WIFMLPT5.js";
7
7
  export {
8
8
  Voices as default
9
9
  };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "name": "Cartesia",
5
5
  "url": "https://cartesia.ai"
6
6
  },
7
- "version": "1.0.2",
7
+ "version": "1.1.0",
8
8
  "description": "Client for the Cartesia API.",
9
9
  "type": "module",
10
10
  "module": "./dist/index.js",
@@ -201,6 +201,10 @@ export function useTTS({
201
201
  await player.current.stop();
202
202
  }
203
203
 
204
+ if (playbackStatus === "finished") {
205
+ websocketReturn.current.source.seek(0, "start");
206
+ }
207
+
204
208
  setPlaybackStatus("playing");
205
209
 
206
210
  const unsubscribes = [];
package/src/tts/source.ts CHANGED
@@ -124,6 +124,41 @@ export default class Source {
124
124
  return read;
125
125
  }
126
126
 
127
+ /**
128
+ * Seek in the buffer.
129
+ *
130
+ * @param offset The offset to seek to.
131
+ * @param whence The position to seek from.
132
+ * @returns The new position in the buffer.
133
+ * @throws {Error} If the seek is invalid.
134
+ */
135
+ async seek(
136
+ offset: number,
137
+ whence: "start" | "current" | "end",
138
+ ): Promise<number> {
139
+ let position = this.#readIndex;
140
+ switch (whence) {
141
+ case "start":
142
+ position = offset;
143
+ break;
144
+ case "current":
145
+ position += offset;
146
+ break;
147
+ case "end":
148
+ position = this.#writeIndex + offset;
149
+ break;
150
+ default:
151
+ throw new Error(`Invalid seek mode: ${whence}`);
152
+ }
153
+
154
+ if (position < 0 || position > this.#writeIndex) {
155
+ throw new Error("Seek out of bounds");
156
+ }
157
+
158
+ this.#readIndex = position;
159
+ return position;
160
+ }
161
+
127
162
  /**
128
163
  * Get the number of samples in a given duration.
129
164
  *
@@ -5,6 +5,7 @@ import { Client } from "../lib/client";
5
5
  import { CARTESIA_VERSION, constructApiUrl } from "../lib/constants";
6
6
  import type {
7
7
  ConnectionEventData,
8
+ ContinueRequest,
8
9
  EmitteryCallbacks,
9
10
  StreamOptions,
10
11
  StreamRequest,
@@ -45,7 +46,7 @@ export default class WebSocket extends Client {
45
46
  /**
46
47
  * Send a message over the WebSocket to start a stream.
47
48
  *
48
- * @param inputs - Stream options. Defined in the StreamRequest type.
49
+ * @param inputs - Generation parameters. Defined in the StreamRequest type.
49
50
  * @param options - Options for the stream.
50
51
  * @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
51
52
  * If set to `0`, the stream will not time out.
@@ -53,7 +54,7 @@ export default class WebSocket extends Client {
53
54
  * @returns An Emittery instance that emits messages from the WebSocket.
54
55
  * @returns An abort function that can be called to cancel the stream.
55
56
  */
56
- send({ ...inputs }: StreamRequest, { timeout = 0 }: StreamOptions = {}) {
57
+ send(inputs: StreamRequest, { timeout = 0 }: StreamOptions = {}) {
57
58
  if (!this.#isConnected) {
58
59
  throw new Error("Not connected to WebSocket. Call .connect() first.");
59
60
  }
@@ -151,6 +152,36 @@ export default class WebSocket extends Client {
151
152
  };
152
153
  }
153
154
 
155
+ /**
156
+ * Continue a stream.
157
+ *
158
+ * @param inputs - Generation parameters. Defined in the StreamRequest type, but must include a `context_id` field. `continue` is set to true by default.
159
+ */
160
+ continue(inputs: ContinueRequest) {
161
+ if (!this.#isConnected) {
162
+ throw new Error("Not connected to WebSocket. Call .connect() first.");
163
+ }
164
+
165
+ if (!inputs.context_id) {
166
+ throw new Error("context_id is required to continue a context.");
167
+ }
168
+ if (!inputs.output_format) {
169
+ inputs.output_format = {
170
+ container: this.#container,
171
+ encoding: this.#encoding,
172
+ sample_rate: this.#sampleRate,
173
+ };
174
+ }
175
+
176
+ // Send continue request.
177
+ this.socket?.send(
178
+ JSON.stringify({
179
+ continue: true,
180
+ ...inputs,
181
+ }),
182
+ );
183
+ }
184
+
154
185
  /**
155
186
  * Generate a unique ID suitable for a streaming context.
156
187
  *
@@ -182,6 +213,8 @@ export default class WebSocket extends Client {
182
213
  url.searchParams.set("cartesia_version", CARTESIA_VERSION);
183
214
  return url.toString();
184
215
  });
216
+ this.socket.binaryType = "arraybuffer";
217
+
185
218
  this.socket.onopen = () => {
186
219
  this.#isConnected = true;
187
220
  emitter.emit("open");