@cartesia/cartesia-js 1.0.3 → 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 +34 -34
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +32 -3
  4. package/dist/{chunk-NQVZNVOU.js → chunk-3FL2SNIR.js} +1 -1
  5. package/dist/{chunk-ZF6HASZT.js → chunk-4GEDAGVY.js} +3 -3
  6. package/dist/{chunk-PISCPZK4.js → chunk-6PWLZAMS.js} +1 -1
  7. package/dist/{chunk-YFN6TFR4.js → chunk-CWIJUBG6.js} +12 -4
  8. package/dist/{chunk-EUW2435M.js → chunk-L3OMQKWL.js} +34 -10
  9. package/dist/{chunk-LZO6K34D.js → chunk-MNOPO7G6.js} +2 -2
  10. package/dist/{chunk-NWCW6C7H.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 +71 -19
  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 +71 -19
  21. package/dist/lib/index.js +8 -8
  22. package/dist/react/index.cjs +74 -19
  23. package/dist/react/index.js +13 -10
  24. package/dist/react/utils.js +2 -2
  25. package/dist/tts/index.cjs +61 -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 +61 -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 +18 -3
  38. package/dist/types/index.d.ts +18 -3
  39. package/dist/voices/index.cjs +10 -2
  40. package/dist/voices/index.d.cts +2 -1
  41. package/dist/voices/index.d.ts +2 -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 +33 -2
  47. package/src/types/index.ts +29 -2
  48. package/src/voices/index.ts +12 -3
@@ -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
  *
@@ -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-EUW2435M.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
  };
@@ -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,14 @@ 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
+ };
86
98
  interface VoiceToMix {
87
99
  id?: string;
88
100
  embedding?: number[];
@@ -99,13 +111,16 @@ type Voice = {
99
111
  is_public: boolean;
100
112
  user_id: string;
101
113
  created_at: string;
102
- language: string;
114
+ language: Language;
103
115
  };
104
116
  type CreateVoice = Pick<Voice, "name" | "description" | "embedding"> & Partial<Omit<Voice, "name" | "description" | "embedding">>;
105
117
  type UpdateVoice = Partial<Pick<Voice, "name" | "description" | "embedding">>;
106
118
  type CloneResponse = {
107
119
  embedding: number[];
108
120
  };
121
+ type LocalizeResponse = {
122
+ embedding: number[];
123
+ };
109
124
  type MixVoicesResponse = {
110
125
  embedding: number[];
111
126
  };
@@ -123,4 +138,4 @@ type SourceEventData = {
123
138
  type TypedArray = Float32Array | Int16Array | Uint8Array;
124
139
  type Encoding = "pcm_f32le" | "pcm_s16le" | "pcm_alaw" | "pcm_mulaw";
125
140
 
126
- export type { Chunk, ClientOptions, CloneOptions, CloneResponse, ConnectionEventData, CreateVoice, EmitteryCallbacks, Emotion, EmotionControl, Encoding, Intensity, MixVoicesOptions, MixVoicesResponse, Sentinel, SourceEventData, StreamOptions, StreamRequest, TypedArray, UpdateVoice, Voice, VoiceOptions, VoiceSpecifier, VoiceToMix, 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 };
@@ -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,14 @@ 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
+ };
86
98
  interface VoiceToMix {
87
99
  id?: string;
88
100
  embedding?: number[];
@@ -99,13 +111,16 @@ type Voice = {
99
111
  is_public: boolean;
100
112
  user_id: string;
101
113
  created_at: string;
102
- language: string;
114
+ language: Language;
103
115
  };
104
116
  type CreateVoice = Pick<Voice, "name" | "description" | "embedding"> & Partial<Omit<Voice, "name" | "description" | "embedding">>;
105
117
  type UpdateVoice = Partial<Pick<Voice, "name" | "description" | "embedding">>;
106
118
  type CloneResponse = {
107
119
  embedding: number[];
108
120
  };
121
+ type LocalizeResponse = {
122
+ embedding: number[];
123
+ };
109
124
  type MixVoicesResponse = {
110
125
  embedding: number[];
111
126
  };
@@ -123,4 +138,4 @@ type SourceEventData = {
123
138
  type TypedArray = Float32Array | Int16Array | Uint8Array;
124
139
  type Encoding = "pcm_f32le" | "pcm_s16le" | "pcm_alaw" | "pcm_mulaw";
125
140
 
126
- export type { Chunk, ClientOptions, CloneOptions, CloneResponse, ConnectionEventData, CreateVoice, EmitteryCallbacks, Emotion, EmotionControl, Encoding, Intensity, MixVoicesOptions, MixVoicesResponse, Sentinel, SourceEventData, StreamOptions, StreamRequest, TypedArray, UpdateVoice, Voice, VoiceOptions, VoiceSpecifier, VoiceToMix, 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 };
@@ -161,10 +161,18 @@ var Voices = class extends Client {
161
161
  }
162
162
  mix(options) {
163
163
  return __async(this, null, function* () {
164
- const request = options;
165
164
  const response = yield this._fetch("/voices/mix", {
166
165
  method: "POST",
167
- body: JSON.stringify(request)
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)
168
176
  });
169
177
  return response.json();
170
178
  });
@@ -1,5 +1,5 @@
1
1
  import { Client } from '../lib/client.cjs';
2
- import { Voice, CreateVoice, UpdateVoice, CloneOptions, CloneResponse, MixVoicesOptions, MixVoicesResponse } 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 {
@@ -9,6 +9,7 @@ declare class Voices extends Client {
9
9
  update(id: string, voice: UpdateVoice): Promise<Voice>;
10
10
  clone(options: CloneOptions): Promise<CloneResponse>;
11
11
  mix(options: MixVoicesOptions): Promise<MixVoicesResponse>;
12
+ localize(options: LocalizeOptions): Promise<LocalizeResponse>;
12
13
  }
13
14
 
14
15
  export { Voices as default };
@@ -1,5 +1,5 @@
1
1
  import { Client } from '../lib/client.js';
2
- import { Voice, CreateVoice, UpdateVoice, CloneOptions, CloneResponse, MixVoicesOptions, MixVoicesResponse } 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 {
@@ -9,6 +9,7 @@ declare class Voices extends Client {
9
9
  update(id: string, voice: UpdateVoice): Promise<Voice>;
10
10
  clone(options: CloneOptions): Promise<CloneResponse>;
11
11
  mix(options: MixVoicesOptions): Promise<MixVoicesResponse>;
12
+ localize(options: LocalizeOptions): Promise<LocalizeResponse>;
12
13
  }
13
14
 
14
15
  export { Voices as default };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Voices
3
- } from "../chunk-YFN6TFR4.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.3",
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
  *
@@ -52,10 +52,24 @@ export type StreamRequest = {
52
52
  context_id?: string;
53
53
  continue?: boolean;
54
54
  duration?: number;
55
- language?: string;
55
+ language?: Language;
56
56
  add_timestamps?: boolean;
57
57
  };
58
58
 
59
+ export type ContinueRequest = StreamRequest & {
60
+ context_id: string;
61
+ };
62
+
63
+ export type Language =
64
+ | "en"
65
+ | "es"
66
+ | "fr"
67
+ | "de"
68
+ | "ja"
69
+ | "zh"
70
+ | "pt"
71
+ | (string & {});
72
+
59
73
  export type StreamOptions = {
60
74
  timeout?: number;
61
75
  };
@@ -112,6 +126,15 @@ export type CloneOptions =
112
126
  enhance?: boolean;
113
127
  };
114
128
 
129
+ export type LocalizeOptions = {
130
+ mode: "embedding";
131
+ embedding: number[];
132
+ } & {
133
+ language: Language;
134
+ dialect: string & {};
135
+ original_speaker_gender: "male" | "female" | (string & {});
136
+ };
137
+
115
138
  export interface VoiceToMix {
116
139
  id?: string;
117
140
  embedding?: number[];
@@ -130,7 +153,7 @@ export type Voice = {
130
153
  is_public: boolean;
131
154
  user_id: string;
132
155
  created_at: string;
133
- language: string;
156
+ language: Language;
134
157
  };
135
158
 
136
159
  export type CreateVoice = Pick<Voice, "name" | "description" | "embedding"> &
@@ -144,6 +167,10 @@ export type CloneResponse = {
144
167
  embedding: number[];
145
168
  };
146
169
 
170
+ export type LocalizeResponse = {
171
+ embedding: number[];
172
+ };
173
+
147
174
  export type MixVoicesResponse = {
148
175
  embedding: number[];
149
176
  };
@@ -3,6 +3,8 @@ import type {
3
3
  CloneOptions,
4
4
  CloneResponse,
5
5
  CreateVoice,
6
+ LocalizeOptions,
7
+ LocalizeResponse,
6
8
  MixVoicesOptions,
7
9
  MixVoicesResponse,
8
10
  UpdateVoice,
@@ -55,13 +57,20 @@ export default class Voices extends Client {
55
57
  }
56
58
 
57
59
  async mix(options: MixVoicesOptions): Promise<MixVoicesResponse> {
58
- const request: MixVoicesOptions = options;
59
-
60
60
  const response = await this._fetch("/voices/mix", {
61
61
  method: "POST",
62
- body: JSON.stringify(request),
62
+ body: JSON.stringify(options),
63
63
  });
64
64
 
65
65
  return response.json() as Promise<MixVoicesResponse>;
66
66
  }
67
+
68
+ async localize(options: LocalizeOptions): Promise<LocalizeResponse> {
69
+ const response = await this._fetch("/voices/localize", {
70
+ method: "POST",
71
+ body: JSON.stringify(options),
72
+ });
73
+
74
+ return response.json() as Promise<LocalizeResponse>;
75
+ }
67
76
  }