@cartesia/cartesia-js 0.0.1 → 0.0.2

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/dist/lib/index.js CHANGED
@@ -3,11 +3,25 @@ var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
7
  var __getProtoOf = Object.getPrototypeOf;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
10
  var __knownSymbol = (name, symbol) => {
9
11
  return (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
10
12
  };
13
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
+ var __spreadValues = (a, b) => {
15
+ for (var prop in b || (b = {}))
16
+ if (__hasOwnProp.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
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
+ };
11
25
  var __export = (target, all) => {
12
26
  for (var name in all)
13
27
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -61,12 +75,13 @@ module.exports = __toCommonJS(lib_exports);
61
75
  // src/audio/index.ts
62
76
  var import_emittery = __toESM(require("emittery"));
63
77
  var import_human_id = require("human-id");
78
+ var import_partysocket = require("partysocket");
64
79
 
65
80
  // src/lib/constants.ts
66
81
  var BASE_URL = "https://api.cartesia.ai/v0";
67
82
  var SAMPLE_RATE = 44100;
68
83
  var constructWebsocketUrl = (baseUrl) => {
69
- return new URL(`${baseUrl.replace(/^http/, "ws")}/ws`);
84
+ return new URL(`${baseUrl.replace(/^http/, "ws")}/audio/websocket`);
70
85
  };
71
86
 
72
87
  // src/lib/client.ts
@@ -136,6 +151,14 @@ function filterSentinel(collection) {
136
151
  function isComplete(chunks) {
137
152
  return isSentinel(chunks[chunks.length - 1]);
138
153
  }
154
+ function getEmitteryCallbacks(emitter) {
155
+ return {
156
+ on: emitter.on.bind(emitter),
157
+ off: emitter.off.bind(emitter),
158
+ once: emitter.once.bind(emitter),
159
+ events: emitter.events.bind(emitter)
160
+ };
161
+ }
139
162
 
140
163
  // src/audio/index.ts
141
164
  var audio_default = class extends Client {
@@ -184,6 +207,9 @@ var audio_default = class extends Client {
184
207
  });
185
208
  yield emitter.emit("message", message);
186
209
  if (isSentinel(chunk)) {
210
+ yield emitter.emit("streamed", {
211
+ chunks
212
+ });
187
213
  streamCompleteController.abort();
188
214
  } else if (timeoutId) {
189
215
  clearTimeout(timeoutId);
@@ -194,13 +220,28 @@ var audio_default = class extends Client {
194
220
  (_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
195
221
  signal: streamCompleteController.signal
196
222
  });
197
- (_c = this.socket) == null ? void 0 : _c.addEventListener("close", streamCompleteController.abort, {
198
- once: true
199
- });
200
- (_d = this.socket) == null ? void 0 : _d.addEventListener("error", streamCompleteController.abort, {
201
- once: true
202
- });
223
+ (_c = this.socket) == null ? void 0 : _c.addEventListener(
224
+ "close",
225
+ () => {
226
+ streamCompleteController.abort();
227
+ },
228
+ {
229
+ once: true
230
+ }
231
+ );
232
+ (_d = this.socket) == null ? void 0 : _d.addEventListener(
233
+ "error",
234
+ () => {
235
+ streamCompleteController.abort();
236
+ },
237
+ {
238
+ once: true
239
+ }
240
+ );
203
241
  streamCompleteController.signal.addEventListener("abort", () => {
242
+ if (timeoutId) {
243
+ clearTimeout(timeoutId);
244
+ }
204
245
  emitter.clearListeners();
205
246
  });
206
247
  const play = (_0) => __async(this, [_0], function* ({ bufferDuration }) {
@@ -274,13 +315,9 @@ var audio_default = class extends Client {
274
315
  }
275
316
  }
276
317
  });
277
- return {
278
- play,
279
- on: emitter.on.bind(emitter),
280
- off: emitter.off.bind(emitter),
281
- once: emitter.once.bind(emitter),
282
- events: emitter.events.bind(emitter)
283
- };
318
+ return __spreadValues({
319
+ play
320
+ }, getEmitteryCallbacks(emitter));
284
321
  }
285
322
  /**
286
323
  * Generate a unique ID suitable for a streaming context.
@@ -305,46 +342,51 @@ var audio_default = class extends Client {
305
342
  connect() {
306
343
  const url = constructWebsocketUrl(this.baseUrl);
307
344
  url.searchParams.set("api_key", this.apiKey);
308
- this.socket = new WebSocket(url);
345
+ const emitter = new import_emittery.default();
346
+ this.socket = new import_partysocket.WebSocket(url.toString());
309
347
  this.socket.onopen = () => {
310
348
  this.isConnected = true;
349
+ emitter.emit("open");
311
350
  };
312
351
  this.socket.onclose = () => {
313
352
  this.isConnected = false;
353
+ emitter.emit("close");
314
354
  };
315
- return new Promise((resolve, reject) => {
316
- var _a, _b, _c;
317
- (_a = this.socket) == null ? void 0 : _a.addEventListener(
318
- "open",
319
- () => {
320
- resolve();
321
- },
322
- {
323
- once: true
324
- }
325
- );
326
- const aborter = new AbortController();
327
- (_b = this.socket) == null ? void 0 : _b.addEventListener(
328
- "error",
329
- () => {
330
- aborter.abort();
331
- reject(new Error("WebSocket failed to connect."));
332
- },
333
- {
334
- signal: aborter.signal
335
- }
336
- );
337
- (_c = this.socket) == null ? void 0 : _c.addEventListener(
338
- "close",
339
- () => {
340
- aborter.abort();
341
- reject(new Error("WebSocket closed before it could connect."));
342
- },
343
- {
344
- signal: aborter.signal
345
- }
346
- );
347
- });
355
+ return new Promise(
356
+ (resolve, reject) => {
357
+ var _a, _b, _c;
358
+ (_a = this.socket) == null ? void 0 : _a.addEventListener(
359
+ "open",
360
+ () => {
361
+ resolve(getEmitteryCallbacks(emitter));
362
+ },
363
+ {
364
+ once: true
365
+ }
366
+ );
367
+ const aborter = new AbortController();
368
+ (_b = this.socket) == null ? void 0 : _b.addEventListener(
369
+ "error",
370
+ () => {
371
+ aborter.abort();
372
+ reject(new Error("WebSocket failed to connect."));
373
+ },
374
+ {
375
+ signal: aborter.signal
376
+ }
377
+ );
378
+ (_c = this.socket) == null ? void 0 : _c.addEventListener(
379
+ "close",
380
+ () => {
381
+ aborter.abort();
382
+ reject(new Error("WebSocket closed before it could connect."));
383
+ },
384
+ {
385
+ signal: aborter.signal
386
+ }
387
+ );
388
+ }
389
+ );
348
390
  }
349
391
  /**
350
392
  * Disconnect from the Cartesia streaming WebSocket.
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  audio_default
3
- } from "../chunk-5RMUZJV7.mjs";
4
- import "../chunk-BTFHUVNH.mjs";
3
+ } from "../chunk-3CYTAFLF.mjs";
4
+ import "../chunk-FRIBQZPN.mjs";
5
5
  import {
6
6
  Client
7
- } from "../chunk-ERFCRIWU.mjs";
8
- import "../chunk-35HX6ML3.mjs";
7
+ } from "../chunk-XSFPHPPG.mjs";
8
+ import "../chunk-HNLIBHEN.mjs";
9
9
 
10
10
  // src/lib/index.ts
11
11
  var Cartesia = class extends Client {
@@ -1,16 +1,20 @@
1
- import { C as Chunk, S as StreamEventData } from '../index-Dt9A_pEb.mjs';
1
+ import { C as Chunk, S as StreamEventData } from '../index-DSBmfK9-.mjs';
2
2
  import 'emittery';
3
+ import 'partysocket';
3
4
  import '../lib/client.mjs';
4
5
  import '../types/index.mjs';
5
6
 
6
- interface UseAudioOptions {
7
- apiKey: string;
7
+ type UseAudioOptions = {
8
+ apiKey: string | null;
8
9
  baseUrl?: string;
9
- }
10
+ };
10
11
  interface UseAudioReturn {
11
12
  stream: (options: object) => void;
12
13
  play: (bufferDuration?: number) => Promise<void>;
14
+ download: () => Blob | null;
13
15
  isPlaying: boolean;
16
+ isConnected: boolean;
17
+ isStreamed: boolean;
14
18
  chunks: Chunk[];
15
19
  messages: StreamEventData["message"][];
16
20
  }
@@ -19,4 +23,4 @@ interface UseAudioReturn {
19
23
  */
20
24
  declare function useAudio({ apiKey, baseUrl }: UseAudioOptions): UseAudioReturn;
21
25
 
22
- export { useAudio };
26
+ export { type UseAudioOptions, useAudio };
@@ -1,16 +1,20 @@
1
- import { C as Chunk, S as StreamEventData } from '../index-Ds4LDkmk.js';
1
+ import { C as Chunk, S as StreamEventData } from '../index-qwAyxV5I.js';
2
2
  import 'emittery';
3
+ import 'partysocket';
3
4
  import '../lib/client.js';
4
5
  import '../types/index.js';
5
6
 
6
- interface UseAudioOptions {
7
- apiKey: string;
7
+ type UseAudioOptions = {
8
+ apiKey: string | null;
8
9
  baseUrl?: string;
9
- }
10
+ };
10
11
  interface UseAudioReturn {
11
12
  stream: (options: object) => void;
12
13
  play: (bufferDuration?: number) => Promise<void>;
14
+ download: () => Blob | null;
13
15
  isPlaying: boolean;
16
+ isConnected: boolean;
17
+ isStreamed: boolean;
14
18
  chunks: Chunk[];
15
19
  messages: StreamEventData["message"][];
16
20
  }
@@ -19,4 +23,4 @@ interface UseAudioReturn {
19
23
  */
20
24
  declare function useAudio({ apiKey, baseUrl }: UseAudioOptions): UseAudioReturn;
21
25
 
22
- export { useAudio };
26
+ export { type UseAudioOptions, useAudio };
@@ -3,11 +3,25 @@ var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
7
  var __getProtoOf = Object.getPrototypeOf;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
10
  var __knownSymbol = (name, symbol) => {
9
11
  return (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
10
12
  };
13
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
+ var __spreadValues = (a, b) => {
15
+ for (var prop in b || (b = {}))
16
+ if (__hasOwnProp.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
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
+ };
11
25
  var __export = (target, all) => {
12
26
  for (var name in all)
13
27
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -62,12 +76,13 @@ var import_react = require("react");
62
76
  // src/audio/index.ts
63
77
  var import_emittery = __toESM(require("emittery"));
64
78
  var import_human_id = require("human-id");
79
+ var import_partysocket = require("partysocket");
65
80
 
66
81
  // src/lib/constants.ts
67
82
  var BASE_URL = "https://api.cartesia.ai/v0";
68
83
  var SAMPLE_RATE = 44100;
69
84
  var constructWebsocketUrl = (baseUrl) => {
70
- return new URL(`${baseUrl.replace(/^http/, "ws")}/ws`);
85
+ return new URL(`${baseUrl.replace(/^http/, "ws")}/audio/websocket`);
71
86
  };
72
87
 
73
88
  // src/lib/client.ts
@@ -137,6 +152,46 @@ function filterSentinel(collection) {
137
152
  function isComplete(chunks) {
138
153
  return isSentinel(chunks[chunks.length - 1]);
139
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
+ }
140
195
 
141
196
  // src/audio/index.ts
142
197
  var audio_default = class extends Client {
@@ -185,6 +240,9 @@ var audio_default = class extends Client {
185
240
  });
186
241
  yield emitter.emit("message", message);
187
242
  if (isSentinel(chunk)) {
243
+ yield emitter.emit("streamed", {
244
+ chunks
245
+ });
188
246
  streamCompleteController.abort();
189
247
  } else if (timeoutId) {
190
248
  clearTimeout(timeoutId);
@@ -195,13 +253,28 @@ var audio_default = class extends Client {
195
253
  (_b = this.socket) == null ? void 0 : _b.addEventListener("message", handleMessage, {
196
254
  signal: streamCompleteController.signal
197
255
  });
198
- (_c = this.socket) == null ? void 0 : _c.addEventListener("close", streamCompleteController.abort, {
199
- once: true
200
- });
201
- (_d = this.socket) == null ? void 0 : _d.addEventListener("error", streamCompleteController.abort, {
202
- once: true
203
- });
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
+ );
204
274
  streamCompleteController.signal.addEventListener("abort", () => {
275
+ if (timeoutId) {
276
+ clearTimeout(timeoutId);
277
+ }
205
278
  emitter.clearListeners();
206
279
  });
207
280
  const play = (_0) => __async(this, [_0], function* ({ bufferDuration }) {
@@ -275,13 +348,9 @@ var audio_default = class extends Client {
275
348
  }
276
349
  }
277
350
  });
278
- return {
279
- play,
280
- on: emitter.on.bind(emitter),
281
- off: emitter.off.bind(emitter),
282
- once: emitter.once.bind(emitter),
283
- events: emitter.events.bind(emitter)
284
- };
351
+ return __spreadValues({
352
+ play
353
+ }, getEmitteryCallbacks(emitter));
285
354
  }
286
355
  /**
287
356
  * Generate a unique ID suitable for a streaming context.
@@ -306,46 +375,51 @@ var audio_default = class extends Client {
306
375
  connect() {
307
376
  const url = constructWebsocketUrl(this.baseUrl);
308
377
  url.searchParams.set("api_key", this.apiKey);
309
- this.socket = new WebSocket(url);
378
+ const emitter = new import_emittery.default();
379
+ this.socket = new import_partysocket.WebSocket(url.toString());
310
380
  this.socket.onopen = () => {
311
381
  this.isConnected = true;
382
+ emitter.emit("open");
312
383
  };
313
384
  this.socket.onclose = () => {
314
385
  this.isConnected = false;
386
+ emitter.emit("close");
315
387
  };
316
- return new Promise((resolve, reject) => {
317
- var _a, _b, _c;
318
- (_a = this.socket) == null ? void 0 : _a.addEventListener(
319
- "open",
320
- () => {
321
- resolve();
322
- },
323
- {
324
- once: true
325
- }
326
- );
327
- const aborter = new AbortController();
328
- (_b = this.socket) == null ? void 0 : _b.addEventListener(
329
- "error",
330
- () => {
331
- aborter.abort();
332
- reject(new Error("WebSocket failed to connect."));
333
- },
334
- {
335
- signal: aborter.signal
336
- }
337
- );
338
- (_c = this.socket) == null ? void 0 : _c.addEventListener(
339
- "close",
340
- () => {
341
- aborter.abort();
342
- reject(new Error("WebSocket closed before it could connect."));
343
- },
344
- {
345
- signal: aborter.signal
346
- }
347
- );
348
- });
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
+ );
349
423
  }
350
424
  /**
351
425
  * Disconnect from the Cartesia streaming WebSocket.
@@ -358,33 +432,45 @@ var audio_default = class extends Client {
358
432
 
359
433
  // src/react/index.ts
360
434
  function useAudio({ apiKey, baseUrl }) {
361
- if (typeof window === "undefined" || !apiKey) {
435
+ if (typeof window === "undefined") {
362
436
  return {
363
437
  stream: () => {
364
438
  },
365
439
  play: () => __async(this, null, function* () {
366
440
  }),
441
+ download: () => null,
442
+ isConnected: false,
367
443
  isPlaying: false,
444
+ isStreamed: false,
368
445
  chunks: [],
369
446
  messages: []
370
447
  };
371
448
  }
372
449
  const audio = (0, import_react.useMemo)(() => {
450
+ if (!apiKey) {
451
+ return null;
452
+ }
373
453
  const audio2 = new audio_default({ apiKey, baseUrl });
374
454
  return audio2;
375
455
  }, [apiKey, baseUrl]);
376
456
  const streamReturn = (0, import_react.useRef)(null);
457
+ const [isStreamed, setIsStreamed] = (0, import_react.useState)(false);
377
458
  const [isPlaying, setIsPlaying] = (0, import_react.useState)(false);
459
+ const [isConnected, setIsConnected] = (0, import_react.useState)(false);
378
460
  const [chunks, setChunks] = (0, import_react.useState)([]);
379
461
  const [messages, setMessages] = (0, import_react.useState)([]);
380
462
  const stream = (0, import_react.useCallback)(
381
- (options) => {
463
+ (options) => __async(this, null, function* () {
382
464
  var _a;
383
465
  streamReturn.current = (_a = audio == null ? void 0 : audio.stream(options)) != null ? _a : null;
466
+ if (!streamReturn.current) {
467
+ return;
468
+ }
469
+ setMessages([]);
384
470
  streamReturn.current.on(
385
471
  "chunk",
386
- ({ chunks: chunks2 }) => {
387
- setChunks(chunks2);
472
+ ({ chunks: chunks3 }) => {
473
+ setChunks(chunks3);
388
474
  }
389
475
  );
390
476
  streamReturn.current.on(
@@ -393,23 +479,46 @@ function useAudio({ apiKey, baseUrl }) {
393
479
  setMessages((messages2) => [...messages2, message]);
394
480
  }
395
481
  );
396
- },
482
+ const { chunks: chunks2 } = yield streamReturn.current.once("streamed");
483
+ setChunks(chunks2);
484
+ setIsStreamed(true);
485
+ }),
397
486
  [audio]
398
487
  );
488
+ const download = (0, import_react.useCallback)(() => {
489
+ if (!isStreamed) {
490
+ return null;
491
+ }
492
+ const audio2 = bufferToWav(SAMPLE_RATE, [base64ToArray(chunks)]);
493
+ return new Blob([audio2], { type: "audio/wav" });
494
+ }, [isStreamed, chunks]);
399
495
  (0, import_react.useEffect)(() => {
400
- function initialize() {
496
+ let cleanup = () => {
497
+ };
498
+ function setupConnection() {
401
499
  return __async(this, null, function* () {
402
500
  try {
403
- yield audio == null ? void 0 : audio.connect();
501
+ const connection = yield audio == null ? void 0 : audio.connect();
502
+ if (!connection) {
503
+ return;
504
+ }
505
+ setIsConnected(true);
506
+ const unsubscribe = connection.on("close", () => {
507
+ setIsConnected(false);
508
+ });
509
+ return () => {
510
+ unsubscribe();
511
+ audio == null ? void 0 : audio.disconnect();
512
+ };
404
513
  } catch (e) {
405
514
  console.error(e);
406
515
  }
407
- return () => {
408
- audio == null ? void 0 : audio.disconnect();
409
- };
410
516
  });
411
517
  }
412
- initialize();
518
+ setupConnection().then((cleanupConnection) => {
519
+ cleanup = cleanupConnection;
520
+ });
521
+ return () => cleanup == null ? void 0 : cleanup();
413
522
  }, [audio]);
414
523
  const play = (0, import_react.useCallback)(
415
524
  (bufferDuration = 0) => __async(this, null, function* () {
@@ -423,7 +532,16 @@ function useAudio({ apiKey, baseUrl }) {
423
532
  }),
424
533
  [isPlaying]
425
534
  );
426
- return { stream, play, isPlaying, chunks, messages };
535
+ return {
536
+ stream,
537
+ play,
538
+ download,
539
+ isPlaying,
540
+ isConnected,
541
+ isStreamed,
542
+ chunks,
543
+ messages
544
+ };
427
545
  }
428
546
  // Annotate the CommonJS export names for ESM import in node:
429
547
  0 && (module.exports = {