@cartesia/cartesia-js 0.0.2 → 0.0.4-alpha.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.
- package/.turbo/turbo-build.log +45 -33
- package/CHANGELOG.md +12 -0
- package/dist/audio/index.cjs +404 -0
- package/dist/audio/index.d.cts +5 -0
- package/dist/audio/index.d.ts +1 -1
- package/dist/audio/index.js +9 -395
- package/dist/audio/utils.cjs +157 -0
- package/dist/audio/{utils.d.mts → utils.d.cts} +3 -3
- package/dist/audio/utils.d.ts +1 -1
- package/dist/audio/utils.js +16 -147
- package/dist/{chunk-3CYTAFLF.mjs → chunk-4MHF74A7.js} +15 -5
- package/dist/{chunk-FRIBQZPN.mjs → chunk-5TSWLYOW.js} +1 -1
- package/dist/{chunk-XSFPHPPG.mjs → chunk-MJIFZWHS.js} +1 -1
- package/dist/chunk-OVI3W3GG.js +12 -0
- package/dist/{chunk-HNLIBHEN.mjs → chunk-R4P7LWVZ.js} +1 -11
- package/dist/{lib/index.mjs → chunk-S6A27RQL.js} +3 -4
- package/dist/chunk-XPIMIAAE.js +17 -0
- package/dist/{index-DSBmfK9-.d.mts → index-C2_3XFxn.d.cts} +9 -4
- package/dist/{index-qwAyxV5I.d.ts → index-DgwnZezj.d.ts} +8 -3
- package/dist/index.cjs +419 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +13 -0
- package/dist/lib/client.cjs +43 -0
- package/dist/lib/{client.d.mts → client.d.cts} +1 -1
- package/dist/lib/client.js +7 -42
- package/dist/lib/constants.cjs +38 -0
- package/dist/lib/constants.js +8 -35
- package/dist/lib/index.cjs +418 -0
- package/dist/lib/{index.d.mts → index.d.cts} +3 -3
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +10 -409
- package/dist/react/index.cjs +597 -0
- package/dist/react/{index.d.mts → index.d.cts} +4 -3
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +71 -455
- package/dist/react/utils.cjs +57 -0
- package/dist/react/utils.d.cts +7 -0
- package/dist/react/utils.d.ts +7 -0
- package/dist/react/utils.js +7 -0
- package/dist/types/index.cjs +18 -0
- package/dist/types/index.js +1 -18
- package/package.json +10 -7
- package/src/audio/index.ts +15 -0
- package/src/index.ts +3 -0
- package/src/react/index.ts +48 -10
- package/src/react/utils.ts +11 -0
- package/dist/audio/index.d.mts +0 -5
- package/dist/audio/index.mjs +0 -9
- package/dist/audio/utils.mjs +0 -25
- package/dist/lib/client.mjs +0 -7
- package/dist/lib/constants.mjs +0 -10
- package/dist/react/index.mjs +0 -130
- package/index.ts +0 -3
- /package/dist/{types/index.mjs → chunk-FXPGR372.js} +0 -0
- /package/dist/lib/{constants.d.mts → constants.d.cts} +0 -0
- /package/dist/types/{index.d.mts → index.d.cts} +0 -0
package/dist/react/index.js
CHANGED
|
@@ -1,436 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (__getOwnPropSymbols)
|
|
19
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
20
|
-
if (__propIsEnum.call(b, prop))
|
|
21
|
-
__defNormalProp(a, prop, b[prop]);
|
|
22
|
-
}
|
|
23
|
-
return a;
|
|
24
|
-
};
|
|
25
|
-
var __export = (target, all) => {
|
|
26
|
-
for (var name in all)
|
|
27
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
28
|
-
};
|
|
29
|
-
var __copyProps = (to, from, except, desc) => {
|
|
30
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
31
|
-
for (let key of __getOwnPropNames(from))
|
|
32
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
33
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
34
|
-
}
|
|
35
|
-
return to;
|
|
36
|
-
};
|
|
37
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
38
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
39
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
40
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
41
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
42
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
43
|
-
mod
|
|
44
|
-
));
|
|
45
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
46
|
-
var __async = (__this, __arguments, generator) => {
|
|
47
|
-
return new Promise((resolve, reject) => {
|
|
48
|
-
var fulfilled = (value) => {
|
|
49
|
-
try {
|
|
50
|
-
step(generator.next(value));
|
|
51
|
-
} catch (e) {
|
|
52
|
-
reject(e);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
var rejected = (value) => {
|
|
56
|
-
try {
|
|
57
|
-
step(generator.throw(value));
|
|
58
|
-
} catch (e) {
|
|
59
|
-
reject(e);
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
63
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
64
|
-
});
|
|
65
|
-
};
|
|
66
|
-
var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
|
|
67
|
-
|
|
68
|
-
// src/react/index.ts
|
|
69
|
-
var react_exports = {};
|
|
70
|
-
__export(react_exports, {
|
|
71
|
-
useAudio: () => useAudio
|
|
72
|
-
});
|
|
73
|
-
module.exports = __toCommonJS(react_exports);
|
|
74
|
-
var import_react = require("react");
|
|
75
|
-
|
|
76
|
-
// src/audio/index.ts
|
|
77
|
-
var import_emittery = __toESM(require("emittery"));
|
|
78
|
-
var import_human_id = require("human-id");
|
|
79
|
-
var import_partysocket = require("partysocket");
|
|
80
|
-
|
|
81
|
-
// src/lib/constants.ts
|
|
82
|
-
var BASE_URL = "https://api.cartesia.ai/v0";
|
|
83
|
-
var SAMPLE_RATE = 44100;
|
|
84
|
-
var constructWebsocketUrl = (baseUrl) => {
|
|
85
|
-
return new URL(`${baseUrl.replace(/^http/, "ws")}/audio/websocket`);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// src/lib/client.ts
|
|
89
|
-
var Client = class {
|
|
90
|
-
constructor(options = {}) {
|
|
91
|
-
if (!(options.apiKey || process.env.CARTESIA_API_KEY)) {
|
|
92
|
-
throw new Error("Missing Cartesia API key.");
|
|
93
|
-
}
|
|
94
|
-
this.apiKey = options.apiKey || process.env.CARTESIA_API_KEY;
|
|
95
|
-
this.baseUrl = options.baseUrl || BASE_URL;
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
// src/audio/utils.ts
|
|
100
|
-
var import_base64_js = __toESM(require("base64-js"));
|
|
101
|
-
function getBufferDuration(b64) {
|
|
102
|
-
const floats = base64ToArray(b64);
|
|
103
|
-
return floats.length / SAMPLE_RATE;
|
|
104
|
-
}
|
|
105
|
-
function base64ToArray(b64) {
|
|
106
|
-
return filterSentinel(b64).reduce((acc, b) => {
|
|
107
|
-
const floats = new Float32Array(import_base64_js.default.toByteArray(b).buffer);
|
|
108
|
-
const newAcc = new Float32Array(acc.length + floats.length);
|
|
109
|
-
newAcc.set(acc, 0);
|
|
110
|
-
newAcc.set(floats, acc.length);
|
|
111
|
-
return newAcc;
|
|
112
|
-
}, new Float32Array(0));
|
|
113
|
-
}
|
|
114
|
-
function playAudioBuffer(b64, context, maybeStartAt = null, onEnded = null) {
|
|
115
|
-
const startAt = maybeStartAt != null ? maybeStartAt : context.currentTime;
|
|
116
|
-
const floats = base64ToArray(b64);
|
|
117
|
-
const source = context.createBufferSource();
|
|
118
|
-
const buffer = context.createBuffer(1, floats.length, SAMPLE_RATE);
|
|
119
|
-
buffer.getChannelData(0).set(floats);
|
|
120
|
-
source.buffer = buffer;
|
|
121
|
-
source.connect(context.destination);
|
|
122
|
-
source.start(startAt);
|
|
123
|
-
source.onended = onEnded;
|
|
124
|
-
return buffer.duration;
|
|
125
|
-
}
|
|
126
|
-
function createMessageHandlerForContextId(contextId, handler) {
|
|
127
|
-
return (event) => {
|
|
128
|
-
const message = JSON.parse(event.data);
|
|
129
|
-
if (message.context_id !== contextId) {
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
let chunk;
|
|
133
|
-
if (message.done) {
|
|
134
|
-
chunk = getSentinel();
|
|
135
|
-
} else {
|
|
136
|
-
chunk = message.data;
|
|
137
|
-
}
|
|
138
|
-
handler({ chunk, message });
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
function getSentinel() {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
function isSentinel(x) {
|
|
145
|
-
return x === getSentinel();
|
|
146
|
-
}
|
|
147
|
-
function filterSentinel(collection) {
|
|
148
|
-
return collection.filter(
|
|
149
|
-
(x) => !isSentinel(x)
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
function isComplete(chunks) {
|
|
153
|
-
return isSentinel(chunks[chunks.length - 1]);
|
|
154
|
-
}
|
|
155
|
-
function getEmitteryCallbacks(emitter) {
|
|
156
|
-
return {
|
|
157
|
-
on: emitter.on.bind(emitter),
|
|
158
|
-
off: emitter.off.bind(emitter),
|
|
159
|
-
once: emitter.once.bind(emitter),
|
|
160
|
-
events: emitter.events.bind(emitter)
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
function bufferToWav(sampleRate, channelBuffers) {
|
|
164
|
-
const totalSamples = channelBuffers[0].length * channelBuffers.length;
|
|
165
|
-
const buffer = new ArrayBuffer(44 + totalSamples * 2);
|
|
166
|
-
const view = new DataView(buffer);
|
|
167
|
-
const writeString = (view2, offset2, string) => {
|
|
168
|
-
for (let i = 0; i < string.length; i++) {
|
|
169
|
-
view2.setUint8(offset2 + i, string.charCodeAt(i));
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
writeString(view, 0, "RIFF");
|
|
173
|
-
view.setUint32(4, 36 + totalSamples * 2, true);
|
|
174
|
-
writeString(view, 8, "WAVE");
|
|
175
|
-
writeString(view, 12, "fmt ");
|
|
176
|
-
view.setUint32(16, 16, true);
|
|
177
|
-
view.setUint16(20, 1, true);
|
|
178
|
-
view.setUint16(22, channelBuffers.length, true);
|
|
179
|
-
view.setUint32(24, sampleRate, true);
|
|
180
|
-
view.setUint32(28, sampleRate * 4, true);
|
|
181
|
-
view.setUint16(32, channelBuffers.length * 2, true);
|
|
182
|
-
view.setUint16(34, 16, true);
|
|
183
|
-
writeString(view, 36, "data");
|
|
184
|
-
view.setUint32(40, totalSamples * 2, true);
|
|
185
|
-
let offset = 44;
|
|
186
|
-
for (let i = 0; i < channelBuffers[0].length; i++) {
|
|
187
|
-
for (let channel = 0; channel < channelBuffers.length; channel++) {
|
|
188
|
-
const s = Math.max(-1, Math.min(1, channelBuffers[channel][i]));
|
|
189
|
-
view.setInt16(offset, s < 0 ? s * 32768 : s * 32767, true);
|
|
190
|
-
offset += 2;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return buffer;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// src/audio/index.ts
|
|
197
|
-
var audio_default = class extends Client {
|
|
198
|
-
constructor() {
|
|
199
|
-
super(...arguments);
|
|
200
|
-
this.isConnected = false;
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Stream audio from a model.
|
|
204
|
-
*
|
|
205
|
-
* @param inputs - Stream options. Includes a `model` key and some `parameters`, which
|
|
206
|
-
* are model-specific and can be found in the model's documentation.
|
|
207
|
-
* @param options - Options for the stream.
|
|
208
|
-
* @param options.timeout - The maximum time to wait for a chunk before cancelling the stream.
|
|
209
|
-
* If `0`, the stream will not time out.
|
|
210
|
-
* @returns An object with a method `play` of type `(bufferDuration: number) => Promise<void>`
|
|
211
|
-
* that plays the audio as it arrives, with `bufferDuration` seconds of audio buffered before
|
|
212
|
-
* starting playback.
|
|
213
|
-
*/
|
|
214
|
-
stream(inputs, { timeout = 0 } = {}) {
|
|
215
|
-
var _a, _b, _c, _d;
|
|
216
|
-
if (!this.isConnected) {
|
|
217
|
-
throw new Error("Not connected to WebSocket. Call .connect() first.");
|
|
218
|
-
}
|
|
219
|
-
const contextId = this.generateId();
|
|
220
|
-
(_a = this.socket) == null ? void 0 : _a.send(
|
|
221
|
-
JSON.stringify({
|
|
222
|
-
data: inputs,
|
|
223
|
-
context_id: contextId
|
|
224
|
-
})
|
|
225
|
-
);
|
|
226
|
-
const streamCompleteController = new AbortController();
|
|
227
|
-
let timeoutId = null;
|
|
228
|
-
if (timeout > 0) {
|
|
229
|
-
timeoutId = setTimeout(streamCompleteController.abort, timeout);
|
|
230
|
-
}
|
|
231
|
-
const chunks = [];
|
|
232
|
-
const emitter = new import_emittery.default();
|
|
233
|
-
const handleMessage = createMessageHandlerForContextId(
|
|
234
|
-
contextId,
|
|
235
|
-
(_0) => __async(this, [_0], function* ({ chunk, message }) {
|
|
236
|
-
chunks.push(chunk);
|
|
237
|
-
yield emitter.emit("chunk", {
|
|
238
|
-
chunk,
|
|
239
|
-
chunks
|
|
240
|
-
});
|
|
241
|
-
yield emitter.emit("message", message);
|
|
242
|
-
if (isSentinel(chunk)) {
|
|
243
|
-
yield emitter.emit("streamed", {
|
|
244
|
-
chunks
|
|
245
|
-
});
|
|
246
|
-
streamCompleteController.abort();
|
|
247
|
-
} else if (timeoutId) {
|
|
248
|
-
clearTimeout(timeoutId);
|
|
249
|
-
timeoutId = setTimeout(streamCompleteController.abort, timeout);
|
|
250
|
-
}
|
|
251
|
-
})
|
|
252
|
-
);
|
|
253
|
-
(_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
|
|
254
|
-
signal: streamCompleteController.signal
|
|
255
|
-
});
|
|
256
|
-
(_c = this.socket) == null ? void 0 : _c.addEventListener(
|
|
257
|
-
"close",
|
|
258
|
-
() => {
|
|
259
|
-
streamCompleteController.abort();
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
once: true
|
|
263
|
-
}
|
|
264
|
-
);
|
|
265
|
-
(_d = this.socket) == null ? void 0 : _d.addEventListener(
|
|
266
|
-
"error",
|
|
267
|
-
() => {
|
|
268
|
-
streamCompleteController.abort();
|
|
269
|
-
},
|
|
270
|
-
{
|
|
271
|
-
once: true
|
|
272
|
-
}
|
|
273
|
-
);
|
|
274
|
-
streamCompleteController.signal.addEventListener("abort", () => {
|
|
275
|
-
if (timeoutId) {
|
|
276
|
-
clearTimeout(timeoutId);
|
|
277
|
-
}
|
|
278
|
-
emitter.clearListeners();
|
|
279
|
-
});
|
|
280
|
-
const play = (_0) => __async(this, [_0], function* ({ bufferDuration }) {
|
|
281
|
-
const context = new AudioContext({
|
|
282
|
-
sampleRate: SAMPLE_RATE
|
|
283
|
-
});
|
|
284
|
-
let startNextPlaybackAt = 0;
|
|
285
|
-
const playLatestChunk = (chunk) => {
|
|
286
|
-
if (isSentinel(chunk)) {
|
|
287
|
-
return true;
|
|
288
|
-
}
|
|
289
|
-
startNextPlaybackAt = playAudioBuffer([chunk], context, startNextPlaybackAt) + Math.max(context.currentTime, startNextPlaybackAt);
|
|
290
|
-
return false;
|
|
291
|
-
};
|
|
292
|
-
const playChunks = (chunks2) => {
|
|
293
|
-
startNextPlaybackAt += playAudioBuffer(
|
|
294
|
-
chunks2,
|
|
295
|
-
context,
|
|
296
|
-
startNextPlaybackAt
|
|
297
|
-
);
|
|
298
|
-
if (isComplete(chunks2)) {
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
};
|
|
302
|
-
const tryStart = (chunks2) => __async(this, null, function* () {
|
|
303
|
-
startNextPlaybackAt = context.currentTime;
|
|
304
|
-
if (isComplete(chunks2) || streamCompleteController.signal.aborted) {
|
|
305
|
-
playChunks(chunks2);
|
|
306
|
-
return true;
|
|
307
|
-
}
|
|
308
|
-
if (getBufferDuration(chunks2) > bufferDuration) {
|
|
309
|
-
playChunks(chunks2);
|
|
310
|
-
try {
|
|
311
|
-
for (var iter2 = __forAwait(emitter.events("chunk")), more2, temp2, error2; more2 = !(temp2 = yield iter2.next()).done; more2 = false) {
|
|
312
|
-
const { chunk } = temp2.value;
|
|
313
|
-
if (playLatestChunk(chunk)) {
|
|
314
|
-
break;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
} catch (temp2) {
|
|
318
|
-
error2 = [temp2];
|
|
319
|
-
} finally {
|
|
320
|
-
try {
|
|
321
|
-
more2 && (temp2 = iter2.return) && (yield temp2.call(iter2));
|
|
322
|
-
} finally {
|
|
323
|
-
if (error2)
|
|
324
|
-
throw error2[0];
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
return true;
|
|
328
|
-
}
|
|
329
|
-
return false;
|
|
330
|
-
});
|
|
331
|
-
if (!(yield tryStart(chunks))) {
|
|
332
|
-
try {
|
|
333
|
-
for (var iter = __forAwait(emitter.events("chunk")), more, temp, error; more = !(temp = yield iter.next()).done; more = false) {
|
|
334
|
-
const { chunks: chunks2 } = temp.value;
|
|
335
|
-
if (yield tryStart(chunks2)) {
|
|
336
|
-
break;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
} catch (temp) {
|
|
340
|
-
error = [temp];
|
|
341
|
-
} finally {
|
|
342
|
-
try {
|
|
343
|
-
more && (temp = iter.return) && (yield temp.call(iter));
|
|
344
|
-
} finally {
|
|
345
|
-
if (error)
|
|
346
|
-
throw error[0];
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
return __spreadValues({
|
|
352
|
-
play
|
|
353
|
-
}, getEmitteryCallbacks(emitter));
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Generate a unique ID suitable for a streaming context.
|
|
357
|
-
*
|
|
358
|
-
* Not suitable for security purposes or as a primary key, since
|
|
359
|
-
* it lacks the amount of entropy required for those use cases.
|
|
360
|
-
*
|
|
361
|
-
* @returns A unique ID.
|
|
362
|
-
*/
|
|
363
|
-
generateId() {
|
|
364
|
-
return (0, import_human_id.humanId)({
|
|
365
|
-
separator: "-",
|
|
366
|
-
capitalize: false
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* Authenticate and connect to a Cartesia streaming WebSocket.
|
|
371
|
-
*
|
|
372
|
-
* @returns A promise that resolves when the WebSocket is connected.
|
|
373
|
-
* @throws {Error} If the WebSocket fails to connect.
|
|
374
|
-
*/
|
|
375
|
-
connect() {
|
|
376
|
-
const url = constructWebsocketUrl(this.baseUrl);
|
|
377
|
-
url.searchParams.set("api_key", this.apiKey);
|
|
378
|
-
const emitter = new import_emittery.default();
|
|
379
|
-
this.socket = new import_partysocket.WebSocket(url.toString());
|
|
380
|
-
this.socket.onopen = () => {
|
|
381
|
-
this.isConnected = true;
|
|
382
|
-
emitter.emit("open");
|
|
383
|
-
};
|
|
384
|
-
this.socket.onclose = () => {
|
|
385
|
-
this.isConnected = false;
|
|
386
|
-
emitter.emit("close");
|
|
387
|
-
};
|
|
388
|
-
return new Promise(
|
|
389
|
-
(resolve, reject) => {
|
|
390
|
-
var _a, _b, _c;
|
|
391
|
-
(_a = this.socket) == null ? void 0 : _a.addEventListener(
|
|
392
|
-
"open",
|
|
393
|
-
() => {
|
|
394
|
-
resolve(getEmitteryCallbacks(emitter));
|
|
395
|
-
},
|
|
396
|
-
{
|
|
397
|
-
once: true
|
|
398
|
-
}
|
|
399
|
-
);
|
|
400
|
-
const aborter = new AbortController();
|
|
401
|
-
(_b = this.socket) == null ? void 0 : _b.addEventListener(
|
|
402
|
-
"error",
|
|
403
|
-
() => {
|
|
404
|
-
aborter.abort();
|
|
405
|
-
reject(new Error("WebSocket failed to connect."));
|
|
406
|
-
},
|
|
407
|
-
{
|
|
408
|
-
signal: aborter.signal
|
|
409
|
-
}
|
|
410
|
-
);
|
|
411
|
-
(_c = this.socket) == null ? void 0 : _c.addEventListener(
|
|
412
|
-
"close",
|
|
413
|
-
() => {
|
|
414
|
-
aborter.abort();
|
|
415
|
-
reject(new Error("WebSocket closed before it could connect."));
|
|
416
|
-
},
|
|
417
|
-
{
|
|
418
|
-
signal: aborter.signal
|
|
419
|
-
}
|
|
420
|
-
);
|
|
421
|
-
}
|
|
422
|
-
);
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* Disconnect from the Cartesia streaming WebSocket.
|
|
426
|
-
*/
|
|
427
|
-
disconnect() {
|
|
428
|
-
var _a;
|
|
429
|
-
(_a = this.socket) == null ? void 0 : _a.close();
|
|
430
|
-
}
|
|
431
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
audio_default
|
|
3
|
+
} from "../chunk-4MHF74A7.js";
|
|
4
|
+
import {
|
|
5
|
+
base64ToArray,
|
|
6
|
+
bufferToWav
|
|
7
|
+
} from "../chunk-5TSWLYOW.js";
|
|
8
|
+
import "../chunk-MJIFZWHS.js";
|
|
9
|
+
import {
|
|
10
|
+
SAMPLE_RATE
|
|
11
|
+
} from "../chunk-OVI3W3GG.js";
|
|
12
|
+
import {
|
|
13
|
+
pingServer
|
|
14
|
+
} from "../chunk-XPIMIAAE.js";
|
|
15
|
+
import {
|
|
16
|
+
__async
|
|
17
|
+
} from "../chunk-R4P7LWVZ.js";
|
|
432
18
|
|
|
433
19
|
// src/react/index.ts
|
|
20
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
434
21
|
function useAudio({ apiKey, baseUrl }) {
|
|
435
22
|
if (typeof window === "undefined") {
|
|
436
23
|
return {
|
|
@@ -442,26 +29,30 @@ function useAudio({ apiKey, baseUrl }) {
|
|
|
442
29
|
isConnected: false,
|
|
443
30
|
isPlaying: false,
|
|
444
31
|
isStreamed: false,
|
|
32
|
+
isBuffering: false,
|
|
445
33
|
chunks: [],
|
|
446
34
|
messages: []
|
|
447
35
|
};
|
|
448
36
|
}
|
|
449
|
-
const audio =
|
|
37
|
+
const audio = useMemo(() => {
|
|
450
38
|
if (!apiKey) {
|
|
451
39
|
return null;
|
|
452
40
|
}
|
|
453
41
|
const audio2 = new audio_default({ apiKey, baseUrl });
|
|
454
42
|
return audio2;
|
|
455
43
|
}, [apiKey, baseUrl]);
|
|
456
|
-
const streamReturn =
|
|
457
|
-
const [isStreamed, setIsStreamed] =
|
|
458
|
-
const [isPlaying, setIsPlaying] =
|
|
459
|
-
const [
|
|
460
|
-
const [
|
|
461
|
-
const [
|
|
462
|
-
const
|
|
44
|
+
const streamReturn = useRef(null);
|
|
45
|
+
const [isStreamed, setIsStreamed] = useState(false);
|
|
46
|
+
const [isPlaying, setIsPlaying] = useState(false);
|
|
47
|
+
const [isBuffering, setIsBuffering] = useState(false);
|
|
48
|
+
const [isConnected, setIsConnected] = useState(false);
|
|
49
|
+
const [chunks, setChunks] = useState([]);
|
|
50
|
+
const [messages, setMessages] = useState([]);
|
|
51
|
+
const latencyEndpoint = "https://api.cartesia.ai";
|
|
52
|
+
const stream = useCallback(
|
|
463
53
|
(options) => __async(this, null, function* () {
|
|
464
54
|
var _a;
|
|
55
|
+
setIsStreamed(false);
|
|
465
56
|
streamReturn.current = (_a = audio == null ? void 0 : audio.stream(options)) != null ? _a : null;
|
|
466
57
|
if (!streamReturn.current) {
|
|
467
58
|
return;
|
|
@@ -485,14 +76,14 @@ function useAudio({ apiKey, baseUrl }) {
|
|
|
485
76
|
}),
|
|
486
77
|
[audio]
|
|
487
78
|
);
|
|
488
|
-
const download =
|
|
79
|
+
const download = useCallback(() => {
|
|
489
80
|
if (!isStreamed) {
|
|
490
81
|
return null;
|
|
491
82
|
}
|
|
492
83
|
const audio2 = bufferToWav(SAMPLE_RATE, [base64ToArray(chunks)]);
|
|
493
84
|
return new Blob([audio2], { type: "audio/wav" });
|
|
494
85
|
}, [isStreamed, chunks]);
|
|
495
|
-
|
|
86
|
+
useEffect(() => {
|
|
496
87
|
let cleanup = () => {
|
|
497
88
|
};
|
|
498
89
|
function setupConnection() {
|
|
@@ -503,6 +94,9 @@ function useAudio({ apiKey, baseUrl }) {
|
|
|
503
94
|
return;
|
|
504
95
|
}
|
|
505
96
|
setIsConnected(true);
|
|
97
|
+
connection.on("open", () => {
|
|
98
|
+
setIsConnected(true);
|
|
99
|
+
});
|
|
506
100
|
const unsubscribe = connection.on("close", () => {
|
|
507
101
|
setIsConnected(false);
|
|
508
102
|
});
|
|
@@ -520,18 +114,40 @@ function useAudio({ apiKey, baseUrl }) {
|
|
|
520
114
|
});
|
|
521
115
|
return () => cleanup == null ? void 0 : cleanup();
|
|
522
116
|
}, [audio]);
|
|
523
|
-
const play = (
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
117
|
+
const play = useCallback(() => __async(this, null, function* () {
|
|
118
|
+
var _a;
|
|
119
|
+
if (isPlaying || !streamReturn.current) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
setIsPlaying(true);
|
|
123
|
+
const ping = yield pingServer(latencyEndpoint);
|
|
124
|
+
let bufferingTimeout;
|
|
125
|
+
let bufferDuration;
|
|
126
|
+
if (ping < 300) {
|
|
127
|
+
bufferDuration = 0;
|
|
128
|
+
} else if (ping > 1500) {
|
|
129
|
+
bufferDuration = 6;
|
|
130
|
+
} else {
|
|
131
|
+
bufferDuration = ping / 1e3 * 4;
|
|
132
|
+
}
|
|
133
|
+
streamReturn.current.once("buffering").then(() => {
|
|
134
|
+
bufferingTimeout = setTimeout(() => {
|
|
135
|
+
setIsBuffering(true);
|
|
136
|
+
}, 250);
|
|
137
|
+
});
|
|
138
|
+
streamReturn.current.once("buffered").then(() => {
|
|
139
|
+
if (bufferingTimeout) {
|
|
140
|
+
clearTimeout(bufferingTimeout);
|
|
528
141
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
142
|
+
setIsBuffering(false);
|
|
143
|
+
});
|
|
144
|
+
streamReturn.current.once("scheduled").then((data) => {
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
setIsPlaying(false);
|
|
147
|
+
}, data.playbackEndsIn);
|
|
148
|
+
});
|
|
149
|
+
yield (_a = streamReturn.current) == null ? void 0 : _a.play({ bufferDuration });
|
|
150
|
+
}), [isPlaying]);
|
|
535
151
|
return {
|
|
536
152
|
stream,
|
|
537
153
|
play,
|
|
@@ -539,11 +155,11 @@ function useAudio({ apiKey, baseUrl }) {
|
|
|
539
155
|
isPlaying,
|
|
540
156
|
isConnected,
|
|
541
157
|
isStreamed,
|
|
158
|
+
isBuffering,
|
|
542
159
|
chunks,
|
|
543
160
|
messages
|
|
544
161
|
};
|
|
545
162
|
}
|
|
546
|
-
|
|
547
|
-
0 && (module.exports = {
|
|
163
|
+
export {
|
|
548
164
|
useAudio
|
|
549
|
-
}
|
|
165
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
var __async = (__this, __arguments, generator) => {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
var fulfilled = (value) => {
|
|
22
|
+
try {
|
|
23
|
+
step(generator.next(value));
|
|
24
|
+
} catch (e) {
|
|
25
|
+
reject(e);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var rejected = (value) => {
|
|
29
|
+
try {
|
|
30
|
+
step(generator.throw(value));
|
|
31
|
+
} catch (e) {
|
|
32
|
+
reject(e);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
36
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// src/react/utils.ts
|
|
41
|
+
var utils_exports = {};
|
|
42
|
+
__export(utils_exports, {
|
|
43
|
+
pingServer: () => pingServer
|
|
44
|
+
});
|
|
45
|
+
module.exports = __toCommonJS(utils_exports);
|
|
46
|
+
function pingServer(url) {
|
|
47
|
+
return __async(this, null, function* () {
|
|
48
|
+
const start = (/* @__PURE__ */ new Date()).getTime();
|
|
49
|
+
yield fetch(url);
|
|
50
|
+
const end = (/* @__PURE__ */ new Date()).getTime();
|
|
51
|
+
return end - start;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
55
|
+
0 && (module.exports = {
|
|
56
|
+
pingServer
|
|
57
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
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 __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
|
|
16
|
+
// src/types/index.ts
|
|
17
|
+
var types_exports = {};
|
|
18
|
+
module.exports = __toCommonJS(types_exports);
|