@cartesia/cartesia-js 0.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.
- package/.turbo/turbo-build.log +47 -0
- package/CHANGELOG.md +7 -0
- package/README.md +38 -0
- package/dist/audio/index.d.mts +4 -0
- package/dist/audio/index.d.ts +4 -0
- package/dist/audio/index.js +354 -0
- package/dist/audio/index.mjs +9 -0
- package/dist/audio/utils.d.mts +4 -0
- package/dist/audio/utils.d.ts +4 -0
- package/dist/audio/utils.js +113 -0
- package/dist/audio/utils.mjs +21 -0
- package/dist/chunk-35HX6ML3.mjs +39 -0
- package/dist/chunk-5RMUZJV7.mjs +240 -0
- package/dist/chunk-BTFHUVNH.mjs +71 -0
- package/dist/chunk-ERFCRIWU.mjs +18 -0
- package/dist/index-Ds4LDkmk.d.ts +127 -0
- package/dist/index-Dt9A_pEb.d.mts +127 -0
- package/dist/lib/client.d.mts +9 -0
- package/dist/lib/client.d.ts +9 -0
- package/dist/lib/client.js +43 -0
- package/dist/lib/client.mjs +7 -0
- package/dist/lib/constants.d.mts +5 -0
- package/dist/lib/constants.d.ts +5 -0
- package/dist/lib/constants.js +38 -0
- package/dist/lib/constants.mjs +10 -0
- package/dist/lib/index.d.mts +11 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.js +368 -0
- package/dist/lib/index.mjs +19 -0
- package/dist/react/index.d.mts +22 -0
- package/dist/react/index.d.ts +22 -0
- package/dist/react/index.js +431 -0
- package/dist/react/index.mjs +82 -0
- package/dist/types/index.d.mts +6 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.js +18 -0
- package/dist/types/index.mjs +0 -0
- package/index.ts +3 -0
- package/package.json +50 -0
- package/src/audio/index.ts +242 -0
- package/src/audio/utils.ts +138 -0
- package/src/lib/client.ts +17 -0
- package/src/lib/constants.ts +6 -0
- package/src/lib/index.ts +13 -0
- package/src/react/index.ts +91 -0
- package/src/types/index.ts +4 -0
- package/tsconfig.json +3 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createMessageHandlerForContextId,
|
|
3
|
+
getBufferDuration,
|
|
4
|
+
isComplete,
|
|
5
|
+
isSentinel,
|
|
6
|
+
playAudioBuffer
|
|
7
|
+
} from "./chunk-BTFHUVNH.mjs";
|
|
8
|
+
import {
|
|
9
|
+
Client
|
|
10
|
+
} from "./chunk-ERFCRIWU.mjs";
|
|
11
|
+
import {
|
|
12
|
+
SAMPLE_RATE,
|
|
13
|
+
__async,
|
|
14
|
+
__forAwait,
|
|
15
|
+
constructWebsocketUrl
|
|
16
|
+
} from "./chunk-35HX6ML3.mjs";
|
|
17
|
+
|
|
18
|
+
// src/audio/index.ts
|
|
19
|
+
import Emittery from "emittery";
|
|
20
|
+
import { humanId } from "human-id";
|
|
21
|
+
var audio_default = class extends Client {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
this.isConnected = false;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Stream audio from a model.
|
|
28
|
+
*
|
|
29
|
+
* @param inputs - Stream options. Includes a `model` key and some `parameters`, which
|
|
30
|
+
* are model-specific and can be found in the model's documentation.
|
|
31
|
+
* @param options - Options for the stream.
|
|
32
|
+
* @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
|
|
33
|
+
* If `0`, the stream will not time out.
|
|
34
|
+
* @returns An object with a method `play` of type `(bufferDuration: number) => Promise<void>`
|
|
35
|
+
* that plays the audio as it arrives, with `bufferDuration` seconds of audio buffered before
|
|
36
|
+
* starting playback.
|
|
37
|
+
*/
|
|
38
|
+
stream(inputs, { timeout = 0 } = {}) {
|
|
39
|
+
var _a, _b, _c, _d;
|
|
40
|
+
if (!this.isConnected) {
|
|
41
|
+
throw new Error("Not connected to WebSocket. Call .connect() first.");
|
|
42
|
+
}
|
|
43
|
+
const contextId = this.generateId();
|
|
44
|
+
(_a = this.socket) == null ? void 0 : _a.send(
|
|
45
|
+
JSON.stringify({
|
|
46
|
+
data: inputs,
|
|
47
|
+
context_id: contextId
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
const streamCompleteController = new AbortController();
|
|
51
|
+
let timeoutId = null;
|
|
52
|
+
if (timeout > 0) {
|
|
53
|
+
timeoutId = setTimeout(streamCompleteController.abort, timeout);
|
|
54
|
+
}
|
|
55
|
+
const chunks = [];
|
|
56
|
+
const emitter = new Emittery();
|
|
57
|
+
const handleMessage = createMessageHandlerForContextId(
|
|
58
|
+
contextId,
|
|
59
|
+
(_0) => __async(this, [_0], function* ({ chunk, message }) {
|
|
60
|
+
chunks.push(chunk);
|
|
61
|
+
yield emitter.emit("chunk", {
|
|
62
|
+
chunk,
|
|
63
|
+
chunks
|
|
64
|
+
});
|
|
65
|
+
yield emitter.emit("message", message);
|
|
66
|
+
if (isSentinel(chunk)) {
|
|
67
|
+
streamCompleteController.abort();
|
|
68
|
+
} else if (timeoutId) {
|
|
69
|
+
clearTimeout(timeoutId);
|
|
70
|
+
timeoutId = setTimeout(streamCompleteController.abort, timeout);
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
(_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
|
|
75
|
+
signal: streamCompleteController.signal
|
|
76
|
+
});
|
|
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
|
+
streamCompleteController.signal.addEventListener("abort", () => {
|
|
84
|
+
emitter.clearListeners();
|
|
85
|
+
});
|
|
86
|
+
const play = (_0) => __async(this, [_0], function* ({ bufferDuration }) {
|
|
87
|
+
const context = new AudioContext({
|
|
88
|
+
sampleRate: SAMPLE_RATE
|
|
89
|
+
});
|
|
90
|
+
let startNextPlaybackAt = 0;
|
|
91
|
+
const playLatestChunk = (chunk) => {
|
|
92
|
+
if (isSentinel(chunk)) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
startNextPlaybackAt = playAudioBuffer([chunk], context, startNextPlaybackAt) + Math.max(context.currentTime, startNextPlaybackAt);
|
|
96
|
+
return false;
|
|
97
|
+
};
|
|
98
|
+
const playChunks = (chunks2) => {
|
|
99
|
+
startNextPlaybackAt += playAudioBuffer(
|
|
100
|
+
chunks2,
|
|
101
|
+
context,
|
|
102
|
+
startNextPlaybackAt
|
|
103
|
+
);
|
|
104
|
+
if (isComplete(chunks2)) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const tryStart = (chunks2) => __async(this, null, function* () {
|
|
109
|
+
startNextPlaybackAt = context.currentTime;
|
|
110
|
+
if (isComplete(chunks2) || streamCompleteController.signal.aborted) {
|
|
111
|
+
playChunks(chunks2);
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
if (getBufferDuration(chunks2) > bufferDuration) {
|
|
115
|
+
playChunks(chunks2);
|
|
116
|
+
try {
|
|
117
|
+
for (var iter2 = __forAwait(emitter.events("chunk")), more2, temp2, error2; more2 = !(temp2 = yield iter2.next()).done; more2 = false) {
|
|
118
|
+
const { chunk } = temp2.value;
|
|
119
|
+
if (playLatestChunk(chunk)) {
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
} catch (temp2) {
|
|
124
|
+
error2 = [temp2];
|
|
125
|
+
} finally {
|
|
126
|
+
try {
|
|
127
|
+
more2 && (temp2 = iter2.return) && (yield temp2.call(iter2));
|
|
128
|
+
} finally {
|
|
129
|
+
if (error2)
|
|
130
|
+
throw error2[0];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
});
|
|
137
|
+
if (!(yield tryStart(chunks))) {
|
|
138
|
+
try {
|
|
139
|
+
for (var iter = __forAwait(emitter.events("chunk")), more, temp, error; more = !(temp = yield iter.next()).done; more = false) {
|
|
140
|
+
const { chunks: chunks2 } = temp.value;
|
|
141
|
+
if (yield tryStart(chunks2)) {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
} catch (temp) {
|
|
146
|
+
error = [temp];
|
|
147
|
+
} finally {
|
|
148
|
+
try {
|
|
149
|
+
more && (temp = iter.return) && (yield temp.call(iter));
|
|
150
|
+
} finally {
|
|
151
|
+
if (error)
|
|
152
|
+
throw error[0];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
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
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Generate a unique ID suitable for a streaming context.
|
|
167
|
+
*
|
|
168
|
+
* Not suitable for security purposes or as a primary key, since
|
|
169
|
+
* it lacks the amount of entropy required for those use cases.
|
|
170
|
+
*
|
|
171
|
+
* @returns A unique ID.
|
|
172
|
+
*/
|
|
173
|
+
generateId() {
|
|
174
|
+
return humanId({
|
|
175
|
+
separator: "-",
|
|
176
|
+
capitalize: false
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Authenticate and connect to a Cartesia streaming WebSocket.
|
|
181
|
+
*
|
|
182
|
+
* @returns A promise that resolves when the WebSocket is connected.
|
|
183
|
+
* @throws {Error} If the WebSocket fails to connect.
|
|
184
|
+
*/
|
|
185
|
+
connect() {
|
|
186
|
+
const url = constructWebsocketUrl(this.baseUrl);
|
|
187
|
+
url.searchParams.set("api_key", this.apiKey);
|
|
188
|
+
this.socket = new WebSocket(url);
|
|
189
|
+
this.socket.onopen = () => {
|
|
190
|
+
this.isConnected = true;
|
|
191
|
+
};
|
|
192
|
+
this.socket.onclose = () => {
|
|
193
|
+
this.isConnected = false;
|
|
194
|
+
};
|
|
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
|
+
});
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Disconnect from the Cartesia streaming WebSocket.
|
|
231
|
+
*/
|
|
232
|
+
disconnect() {
|
|
233
|
+
var _a;
|
|
234
|
+
(_a = this.socket) == null ? void 0 : _a.close();
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export {
|
|
239
|
+
audio_default
|
|
240
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SAMPLE_RATE
|
|
3
|
+
} from "./chunk-35HX6ML3.mjs";
|
|
4
|
+
|
|
5
|
+
// src/audio/utils.ts
|
|
6
|
+
import base64 from "base64-js";
|
|
7
|
+
function getBufferDuration(b64) {
|
|
8
|
+
const floats = base64ToArray(b64);
|
|
9
|
+
return floats.length / SAMPLE_RATE;
|
|
10
|
+
}
|
|
11
|
+
function base64ToArray(b64) {
|
|
12
|
+
return filterSentinel(b64).reduce((acc, b) => {
|
|
13
|
+
const floats = new Float32Array(base64.toByteArray(b).buffer);
|
|
14
|
+
const newAcc = new Float32Array(acc.length + floats.length);
|
|
15
|
+
newAcc.set(acc, 0);
|
|
16
|
+
newAcc.set(floats, acc.length);
|
|
17
|
+
return newAcc;
|
|
18
|
+
}, new Float32Array(0));
|
|
19
|
+
}
|
|
20
|
+
function playAudioBuffer(b64, context, maybeStartAt = null, onEnded = null) {
|
|
21
|
+
const startAt = maybeStartAt != null ? maybeStartAt : context.currentTime;
|
|
22
|
+
const floats = base64ToArray(b64);
|
|
23
|
+
const source = context.createBufferSource();
|
|
24
|
+
const buffer = context.createBuffer(1, floats.length, SAMPLE_RATE);
|
|
25
|
+
buffer.getChannelData(0).set(floats);
|
|
26
|
+
source.buffer = buffer;
|
|
27
|
+
source.connect(context.destination);
|
|
28
|
+
source.start(startAt);
|
|
29
|
+
source.onended = onEnded;
|
|
30
|
+
return buffer.duration;
|
|
31
|
+
}
|
|
32
|
+
function createMessageHandlerForContextId(contextId, handler) {
|
|
33
|
+
return (event) => {
|
|
34
|
+
const message = JSON.parse(event.data);
|
|
35
|
+
if (message.context_id !== contextId) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
let chunk;
|
|
39
|
+
if (message.done) {
|
|
40
|
+
chunk = getSentinel();
|
|
41
|
+
} else {
|
|
42
|
+
chunk = message.data;
|
|
43
|
+
}
|
|
44
|
+
handler({ chunk, message });
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function getSentinel() {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
function isSentinel(x) {
|
|
51
|
+
return x === getSentinel();
|
|
52
|
+
}
|
|
53
|
+
function filterSentinel(collection) {
|
|
54
|
+
return collection.filter(
|
|
55
|
+
(x) => !isSentinel(x)
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
function isComplete(chunks) {
|
|
59
|
+
return isSentinel(chunks[chunks.length - 1]);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export {
|
|
63
|
+
getBufferDuration,
|
|
64
|
+
base64ToArray,
|
|
65
|
+
playAudioBuffer,
|
|
66
|
+
createMessageHandlerForContextId,
|
|
67
|
+
getSentinel,
|
|
68
|
+
isSentinel,
|
|
69
|
+
filterSentinel,
|
|
70
|
+
isComplete
|
|
71
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BASE_URL
|
|
3
|
+
} from "./chunk-35HX6ML3.mjs";
|
|
4
|
+
|
|
5
|
+
// src/lib/client.ts
|
|
6
|
+
var Client = class {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
if (!(options.apiKey || process.env.CARTESIA_API_KEY)) {
|
|
9
|
+
throw new Error("Missing Cartesia API key.");
|
|
10
|
+
}
|
|
11
|
+
this.apiKey = options.apiKey || process.env.CARTESIA_API_KEY;
|
|
12
|
+
this.baseUrl = options.baseUrl || BASE_URL;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
Client
|
|
18
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import * as emittery from 'emittery';
|
|
2
|
+
import { Client } from './lib/client.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get the duration of base64-encoded audio buffer(s) in seconds.
|
|
6
|
+
*
|
|
7
|
+
* @param b64 The base64-encoded audio buffer, or an array of base64-encoded
|
|
8
|
+
* audio buffers.
|
|
9
|
+
* @returns The duration of the buffer(s) in seconds.
|
|
10
|
+
*/
|
|
11
|
+
declare function getBufferDuration(b64: Chunk[]): number;
|
|
12
|
+
/**
|
|
13
|
+
* Convert base64-encoded audio buffer(s) to a Float32Array.
|
|
14
|
+
*
|
|
15
|
+
* @param b64 The base64-encoded audio buffer, or an array of base64-encoded
|
|
16
|
+
* audio buffers.
|
|
17
|
+
* @returns The audio buffer(s) as a Float32Array.
|
|
18
|
+
*/
|
|
19
|
+
declare function base64ToArray(b64: Chunk[]): Float32Array;
|
|
20
|
+
/**
|
|
21
|
+
* Schedule an audio buffer to play at a given time in the passed context.
|
|
22
|
+
*
|
|
23
|
+
* @param b64 The base64-encoded audio buffer to play.
|
|
24
|
+
* @param context The audio context to play the buffer in.
|
|
25
|
+
* @param maybeStartAt The time to start playing the buffer at, or null to play
|
|
26
|
+
* immediately.
|
|
27
|
+
* @param onEnded The callback to call when the buffer has finished playing.
|
|
28
|
+
* @returns The duration of the buffer in seconds.
|
|
29
|
+
*/
|
|
30
|
+
declare function playAudioBuffer(b64: Chunk[], context: AudioContext, maybeStartAt?: number | null, onEnded?: AudioScheduledSourceNode["onended"]): number;
|
|
31
|
+
/**
|
|
32
|
+
* Unwraps a chunk of audio data from a message event and calls the
|
|
33
|
+
* handler with it if the context ID matches.
|
|
34
|
+
*
|
|
35
|
+
* @param contextId The context ID to listen for.
|
|
36
|
+
* @param handler The handler to call with the chunk of audio data.
|
|
37
|
+
* @returns A message event handler.
|
|
38
|
+
*/
|
|
39
|
+
declare function createMessageHandlerForContextId(contextId: string, handler: ({ chunk, message, }: {
|
|
40
|
+
chunk: Chunk;
|
|
41
|
+
message: StreamEventData["message"];
|
|
42
|
+
}) => void): (event: MessageEvent) => void;
|
|
43
|
+
type Sentinel = null;
|
|
44
|
+
/**
|
|
45
|
+
* Get a sentinel value that indicates the end of a stream.
|
|
46
|
+
* @returns A sentinel value to indicate the end of a stream.
|
|
47
|
+
*/
|
|
48
|
+
declare function getSentinel(): Sentinel;
|
|
49
|
+
/**
|
|
50
|
+
* Check if a chunk is a sentinel value (i.e. null).
|
|
51
|
+
*
|
|
52
|
+
* @param chunk
|
|
53
|
+
* @returns Whether the chunk is a sentinel value.
|
|
54
|
+
*/
|
|
55
|
+
declare function isSentinel(x: unknown): x is Sentinel;
|
|
56
|
+
/**
|
|
57
|
+
* Filter out null values from a collection.
|
|
58
|
+
*
|
|
59
|
+
* @param collection The collection to filter.
|
|
60
|
+
* @returns The collection with null values removed.
|
|
61
|
+
*/
|
|
62
|
+
declare function filterSentinel<T>(collection: T[]): Exclude<T, Sentinel>[];
|
|
63
|
+
/**
|
|
64
|
+
* Check if an array of chunks is complete by testing if the last chunk is a sentinel
|
|
65
|
+
* value (i.e. null).
|
|
66
|
+
* @param chunk
|
|
67
|
+
* @returns Whether the array of chunks is complete.
|
|
68
|
+
*/
|
|
69
|
+
declare function isComplete(chunks: Chunk[]): boolean;
|
|
70
|
+
|
|
71
|
+
type Chunk = string | Sentinel;
|
|
72
|
+
type StreamEventData = {
|
|
73
|
+
chunk: {
|
|
74
|
+
chunk: Chunk;
|
|
75
|
+
chunks: Chunk[];
|
|
76
|
+
};
|
|
77
|
+
message: unknown;
|
|
78
|
+
};
|
|
79
|
+
declare class export_default extends Client {
|
|
80
|
+
socket?: WebSocket;
|
|
81
|
+
isConnected: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Stream audio from a model.
|
|
84
|
+
*
|
|
85
|
+
* @param inputs - Stream options. Includes a `model` key and some `parameters`, which
|
|
86
|
+
* are model-specific and can be found in the model's documentation.
|
|
87
|
+
* @param options - Options for the stream.
|
|
88
|
+
* @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
|
|
89
|
+
* If `0`, the stream will not time out.
|
|
90
|
+
* @returns An object with a method `play` of type `(bufferDuration: number) => Promise<void>`
|
|
91
|
+
* that plays the audio as it arrives, with `bufferDuration` seconds of audio buffered before
|
|
92
|
+
* starting playback.
|
|
93
|
+
*/
|
|
94
|
+
stream(inputs: object, { timeout }?: {
|
|
95
|
+
timeout?: number;
|
|
96
|
+
}): {
|
|
97
|
+
play: ({ bufferDuration }: {
|
|
98
|
+
bufferDuration: number;
|
|
99
|
+
}) => Promise<void>;
|
|
100
|
+
on: <Name extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name | readonly Name[], listener: (eventData: (StreamEventData & emittery.OmnipresentEventData)[Name]) => void | Promise<void>) => emittery.UnsubscribeFunction;
|
|
101
|
+
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
|
+
once: <Name_2 extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name_2 | readonly Name_2[]) => emittery.EmitteryOncePromise<(StreamEventData & emittery.OmnipresentEventData)[Name_2]>;
|
|
103
|
+
events: <Name_3 extends keyof StreamEventData>(eventName: Name_3 | readonly Name_3[]) => AsyncIterableIterator<StreamEventData[Name_3]>;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Generate a unique ID suitable for a streaming context.
|
|
107
|
+
*
|
|
108
|
+
* Not suitable for security purposes or as a primary key, since
|
|
109
|
+
* it lacks the amount of entropy required for those use cases.
|
|
110
|
+
*
|
|
111
|
+
* @returns A unique ID.
|
|
112
|
+
*/
|
|
113
|
+
generateId(): string;
|
|
114
|
+
/**
|
|
115
|
+
* Authenticate and connect to a Cartesia streaming WebSocket.
|
|
116
|
+
*
|
|
117
|
+
* @returns A promise that resolves when the WebSocket is connected.
|
|
118
|
+
* @throws {Error} If the WebSocket fails to connect.
|
|
119
|
+
*/
|
|
120
|
+
connect(): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Disconnect from the Cartesia streaming WebSocket.
|
|
123
|
+
*/
|
|
124
|
+
disconnect(): void;
|
|
125
|
+
}
|
|
126
|
+
|
|
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 };
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import * as emittery from 'emittery';
|
|
2
|
+
import { Client } from './lib/client.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get the duration of base64-encoded audio buffer(s) in seconds.
|
|
6
|
+
*
|
|
7
|
+
* @param b64 The base64-encoded audio buffer, or an array of base64-encoded
|
|
8
|
+
* audio buffers.
|
|
9
|
+
* @returns The duration of the buffer(s) in seconds.
|
|
10
|
+
*/
|
|
11
|
+
declare function getBufferDuration(b64: Chunk[]): number;
|
|
12
|
+
/**
|
|
13
|
+
* Convert base64-encoded audio buffer(s) to a Float32Array.
|
|
14
|
+
*
|
|
15
|
+
* @param b64 The base64-encoded audio buffer, or an array of base64-encoded
|
|
16
|
+
* audio buffers.
|
|
17
|
+
* @returns The audio buffer(s) as a Float32Array.
|
|
18
|
+
*/
|
|
19
|
+
declare function base64ToArray(b64: Chunk[]): Float32Array;
|
|
20
|
+
/**
|
|
21
|
+
* Schedule an audio buffer to play at a given time in the passed context.
|
|
22
|
+
*
|
|
23
|
+
* @param b64 The base64-encoded audio buffer to play.
|
|
24
|
+
* @param context The audio context to play the buffer in.
|
|
25
|
+
* @param maybeStartAt The time to start playing the buffer at, or null to play
|
|
26
|
+
* immediately.
|
|
27
|
+
* @param onEnded The callback to call when the buffer has finished playing.
|
|
28
|
+
* @returns The duration of the buffer in seconds.
|
|
29
|
+
*/
|
|
30
|
+
declare function playAudioBuffer(b64: Chunk[], context: AudioContext, maybeStartAt?: number | null, onEnded?: AudioScheduledSourceNode["onended"]): number;
|
|
31
|
+
/**
|
|
32
|
+
* Unwraps a chunk of audio data from a message event and calls the
|
|
33
|
+
* handler with it if the context ID matches.
|
|
34
|
+
*
|
|
35
|
+
* @param contextId The context ID to listen for.
|
|
36
|
+
* @param handler The handler to call with the chunk of audio data.
|
|
37
|
+
* @returns A message event handler.
|
|
38
|
+
*/
|
|
39
|
+
declare function createMessageHandlerForContextId(contextId: string, handler: ({ chunk, message, }: {
|
|
40
|
+
chunk: Chunk;
|
|
41
|
+
message: StreamEventData["message"];
|
|
42
|
+
}) => void): (event: MessageEvent) => void;
|
|
43
|
+
type Sentinel = null;
|
|
44
|
+
/**
|
|
45
|
+
* Get a sentinel value that indicates the end of a stream.
|
|
46
|
+
* @returns A sentinel value to indicate the end of a stream.
|
|
47
|
+
*/
|
|
48
|
+
declare function getSentinel(): Sentinel;
|
|
49
|
+
/**
|
|
50
|
+
* Check if a chunk is a sentinel value (i.e. null).
|
|
51
|
+
*
|
|
52
|
+
* @param chunk
|
|
53
|
+
* @returns Whether the chunk is a sentinel value.
|
|
54
|
+
*/
|
|
55
|
+
declare function isSentinel(x: unknown): x is Sentinel;
|
|
56
|
+
/**
|
|
57
|
+
* Filter out null values from a collection.
|
|
58
|
+
*
|
|
59
|
+
* @param collection The collection to filter.
|
|
60
|
+
* @returns The collection with null values removed.
|
|
61
|
+
*/
|
|
62
|
+
declare function filterSentinel<T>(collection: T[]): Exclude<T, Sentinel>[];
|
|
63
|
+
/**
|
|
64
|
+
* Check if an array of chunks is complete by testing if the last chunk is a sentinel
|
|
65
|
+
* value (i.e. null).
|
|
66
|
+
* @param chunk
|
|
67
|
+
* @returns Whether the array of chunks is complete.
|
|
68
|
+
*/
|
|
69
|
+
declare function isComplete(chunks: Chunk[]): boolean;
|
|
70
|
+
|
|
71
|
+
type Chunk = string | Sentinel;
|
|
72
|
+
type StreamEventData = {
|
|
73
|
+
chunk: {
|
|
74
|
+
chunk: Chunk;
|
|
75
|
+
chunks: Chunk[];
|
|
76
|
+
};
|
|
77
|
+
message: unknown;
|
|
78
|
+
};
|
|
79
|
+
declare class export_default extends Client {
|
|
80
|
+
socket?: WebSocket;
|
|
81
|
+
isConnected: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Stream audio from a model.
|
|
84
|
+
*
|
|
85
|
+
* @param inputs - Stream options. Includes a `model` key and some `parameters`, which
|
|
86
|
+
* are model-specific and can be found in the model's documentation.
|
|
87
|
+
* @param options - Options for the stream.
|
|
88
|
+
* @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
|
|
89
|
+
* If `0`, the stream will not time out.
|
|
90
|
+
* @returns An object with a method `play` of type `(bufferDuration: number) => Promise<void>`
|
|
91
|
+
* that plays the audio as it arrives, with `bufferDuration` seconds of audio buffered before
|
|
92
|
+
* starting playback.
|
|
93
|
+
*/
|
|
94
|
+
stream(inputs: object, { timeout }?: {
|
|
95
|
+
timeout?: number;
|
|
96
|
+
}): {
|
|
97
|
+
play: ({ bufferDuration }: {
|
|
98
|
+
bufferDuration: number;
|
|
99
|
+
}) => Promise<void>;
|
|
100
|
+
on: <Name extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name | readonly Name[], listener: (eventData: (StreamEventData & emittery.OmnipresentEventData)[Name]) => void | Promise<void>) => emittery.UnsubscribeFunction;
|
|
101
|
+
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
|
+
once: <Name_2 extends keyof StreamEventData | keyof emittery.OmnipresentEventData>(eventName: Name_2 | readonly Name_2[]) => emittery.EmitteryOncePromise<(StreamEventData & emittery.OmnipresentEventData)[Name_2]>;
|
|
103
|
+
events: <Name_3 extends keyof StreamEventData>(eventName: Name_3 | readonly Name_3[]) => AsyncIterableIterator<StreamEventData[Name_3]>;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Generate a unique ID suitable for a streaming context.
|
|
107
|
+
*
|
|
108
|
+
* Not suitable for security purposes or as a primary key, since
|
|
109
|
+
* it lacks the amount of entropy required for those use cases.
|
|
110
|
+
*
|
|
111
|
+
* @returns A unique ID.
|
|
112
|
+
*/
|
|
113
|
+
generateId(): string;
|
|
114
|
+
/**
|
|
115
|
+
* Authenticate and connect to a Cartesia streaming WebSocket.
|
|
116
|
+
*
|
|
117
|
+
* @returns A promise that resolves when the WebSocket is connected.
|
|
118
|
+
* @throws {Error} If the WebSocket fails to connect.
|
|
119
|
+
*/
|
|
120
|
+
connect(): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Disconnect from the Cartesia streaming WebSocket.
|
|
123
|
+
*/
|
|
124
|
+
disconnect(): void;
|
|
125
|
+
}
|
|
126
|
+
|
|
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 };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/lib/client.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
Client: () => Client
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(client_exports);
|
|
26
|
+
|
|
27
|
+
// src/lib/constants.ts
|
|
28
|
+
var BASE_URL = "https://api.cartesia.ai/v0";
|
|
29
|
+
|
|
30
|
+
// src/lib/client.ts
|
|
31
|
+
var Client = class {
|
|
32
|
+
constructor(options = {}) {
|
|
33
|
+
if (!(options.apiKey || process.env.CARTESIA_API_KEY)) {
|
|
34
|
+
throw new Error("Missing Cartesia API key.");
|
|
35
|
+
}
|
|
36
|
+
this.apiKey = options.apiKey || process.env.CARTESIA_API_KEY;
|
|
37
|
+
this.baseUrl = options.baseUrl || BASE_URL;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
41
|
+
0 && (module.exports = {
|
|
42
|
+
Client
|
|
43
|
+
});
|