@fluxerjs/voice 1.2.4 → 1.3.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/dist/index.d.mts +14 -6
- package/dist/index.d.ts +14 -6
- package/dist/index.js +74 -20
- package/dist/index.mjs +74 -20
- package/package.json +5 -4
package/dist/index.d.mts
CHANGED
|
@@ -42,12 +42,17 @@ declare class VoiceConnection extends EventEmitter {
|
|
|
42
42
|
private setupUDP;
|
|
43
43
|
/**
|
|
44
44
|
* Play a stream of raw Opus packets
|
|
45
|
-
* Uses the same queue and 20ms pacing as play(). Use this for
|
|
45
|
+
* Uses the same queue and 20ms pacing as play(). Use this for raw Opus packet streams (e.g. MP3 → PCM → Opus pipelines) when you are not using WebM/Opus.
|
|
46
46
|
*/
|
|
47
47
|
playOpus(stream: NodeJS.ReadableStream): void;
|
|
48
48
|
/**
|
|
49
|
-
* Play a direct WebM/Opus
|
|
50
|
-
*
|
|
49
|
+
* Play a direct WebM/Opus source. When `urlOrStream` is a string:
|
|
50
|
+
* - `http://` / `https://` — fetched over the network
|
|
51
|
+
* - `file://` — read from the local filesystem
|
|
52
|
+
* - any other string — treated as a filesystem path (e.g. `./music/track.webm`)
|
|
53
|
+
*
|
|
54
|
+
* You can also pass a Node.js Readable stream. Demuxes with prism-media WebmDemuxer; no FFmpeg;
|
|
55
|
+
* input must be WebM with Opus.
|
|
51
56
|
*/
|
|
52
57
|
play(urlOrStream: string | NodeJS.ReadableStream): Promise<void>;
|
|
53
58
|
private sendAudioFrame;
|
|
@@ -222,10 +227,13 @@ declare class LiveKitRtcConnection extends EventEmitter {
|
|
|
222
227
|
*/
|
|
223
228
|
private playVideoFFmpeg;
|
|
224
229
|
/**
|
|
225
|
-
* Play audio from a WebM/Opus
|
|
230
|
+
* Play audio from a WebM/Opus source. Publishes to the LiveKit room as an audio track.
|
|
231
|
+
*
|
|
232
|
+
* When `urlOrStream` is a string: `http(s)://` is fetched; `file://` or any other string is read
|
|
233
|
+
* from the local filesystem (path). Otherwise pass a Node.js ReadableStream.
|
|
226
234
|
*
|
|
227
|
-
* @param urlOrStream -
|
|
228
|
-
* @emits error - On fetch failure or decode errors
|
|
235
|
+
* @param urlOrStream - WebM/Opus HTTP(S) URL, `file://` URL, filesystem path, or ReadableStream
|
|
236
|
+
* @emits error - On fetch/read failure or decode errors
|
|
229
237
|
*/
|
|
230
238
|
play(urlOrStream: string | NodeJS.ReadableStream): Promise<void>;
|
|
231
239
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -42,12 +42,17 @@ declare class VoiceConnection extends EventEmitter {
|
|
|
42
42
|
private setupUDP;
|
|
43
43
|
/**
|
|
44
44
|
* Play a stream of raw Opus packets
|
|
45
|
-
* Uses the same queue and 20ms pacing as play(). Use this for
|
|
45
|
+
* Uses the same queue and 20ms pacing as play(). Use this for raw Opus packet streams (e.g. MP3 → PCM → Opus pipelines) when you are not using WebM/Opus.
|
|
46
46
|
*/
|
|
47
47
|
playOpus(stream: NodeJS.ReadableStream): void;
|
|
48
48
|
/**
|
|
49
|
-
* Play a direct WebM/Opus
|
|
50
|
-
*
|
|
49
|
+
* Play a direct WebM/Opus source. When `urlOrStream` is a string:
|
|
50
|
+
* - `http://` / `https://` — fetched over the network
|
|
51
|
+
* - `file://` — read from the local filesystem
|
|
52
|
+
* - any other string — treated as a filesystem path (e.g. `./music/track.webm`)
|
|
53
|
+
*
|
|
54
|
+
* You can also pass a Node.js Readable stream. Demuxes with prism-media WebmDemuxer; no FFmpeg;
|
|
55
|
+
* input must be WebM with Opus.
|
|
51
56
|
*/
|
|
52
57
|
play(urlOrStream: string | NodeJS.ReadableStream): Promise<void>;
|
|
53
58
|
private sendAudioFrame;
|
|
@@ -222,10 +227,13 @@ declare class LiveKitRtcConnection extends EventEmitter {
|
|
|
222
227
|
*/
|
|
223
228
|
private playVideoFFmpeg;
|
|
224
229
|
/**
|
|
225
|
-
* Play audio from a WebM/Opus
|
|
230
|
+
* Play audio from a WebM/Opus source. Publishes to the LiveKit room as an audio track.
|
|
231
|
+
*
|
|
232
|
+
* When `urlOrStream` is a string: `http(s)://` is fetched; `file://` or any other string is read
|
|
233
|
+
* from the local filesystem (path). Otherwise pass a Node.js ReadableStream.
|
|
226
234
|
*
|
|
227
|
-
* @param urlOrStream -
|
|
228
|
-
* @emits error - On fetch failure or decode errors
|
|
235
|
+
* @param urlOrStream - WebM/Opus HTTP(S) URL, `file://` URL, filesystem path, or ReadableStream
|
|
236
|
+
* @emits error - On fetch/read failure or decode errors
|
|
229
237
|
*/
|
|
230
238
|
play(urlOrStream: string | NodeJS.ReadableStream): Promise<void>;
|
|
231
239
|
/**
|
package/dist/index.js
CHANGED
|
@@ -49,10 +49,13 @@ var thumbnail = MINIMAL_PNG_BASE64;
|
|
|
49
49
|
|
|
50
50
|
// src/VoiceConnection.ts
|
|
51
51
|
var import_events = require("events");
|
|
52
|
+
var import_util = require("@fluxerjs/util");
|
|
52
53
|
var nacl = __toESM(require("tweetnacl"));
|
|
53
54
|
var dgram = __toESM(require("dgram"));
|
|
54
55
|
var ws = __toESM(require("ws"));
|
|
56
|
+
var import_node_fs = require("fs");
|
|
55
57
|
var import_node_stream = require("stream");
|
|
58
|
+
var import_node_url = require("url");
|
|
56
59
|
var import_prism_media = require("prism-media");
|
|
57
60
|
var VOICE_WS_OPCODES = {
|
|
58
61
|
Identify: 0,
|
|
@@ -210,8 +213,11 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
210
213
|
async getWebSocketConstructor() {
|
|
211
214
|
try {
|
|
212
215
|
return ws.default;
|
|
213
|
-
} catch {
|
|
214
|
-
throw new
|
|
216
|
+
} catch (err) {
|
|
217
|
+
throw new import_util.FluxerError('Install "ws" for voice support: pnpm add ws', {
|
|
218
|
+
code: import_util.ErrorCodes.VoiceWebSocketRequired,
|
|
219
|
+
cause: err instanceof Error ? err : void 0
|
|
220
|
+
});
|
|
215
221
|
}
|
|
216
222
|
}
|
|
217
223
|
sendVoiceOp(op, d) {
|
|
@@ -253,7 +259,7 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
253
259
|
}
|
|
254
260
|
/**
|
|
255
261
|
* Play a stream of raw Opus packets
|
|
256
|
-
* Uses the same queue and 20ms pacing as play(). Use this for
|
|
262
|
+
* Uses the same queue and 20ms pacing as play(). Use this for raw Opus packet streams (e.g. MP3 → PCM → Opus pipelines) when you are not using WebM/Opus.
|
|
257
263
|
*/
|
|
258
264
|
playOpus(stream) {
|
|
259
265
|
this.stop();
|
|
@@ -289,20 +295,40 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
289
295
|
});
|
|
290
296
|
}
|
|
291
297
|
/**
|
|
292
|
-
* Play a direct WebM/Opus
|
|
293
|
-
*
|
|
298
|
+
* Play a direct WebM/Opus source. When `urlOrStream` is a string:
|
|
299
|
+
* - `http://` / `https://` — fetched over the network
|
|
300
|
+
* - `file://` — read from the local filesystem
|
|
301
|
+
* - any other string — treated as a filesystem path (e.g. `./music/track.webm`)
|
|
302
|
+
*
|
|
303
|
+
* You can also pass a Node.js Readable stream. Demuxes with prism-media WebmDemuxer; no FFmpeg;
|
|
304
|
+
* input must be WebM with Opus.
|
|
294
305
|
*/
|
|
295
306
|
async play(urlOrStream) {
|
|
296
307
|
this.stop();
|
|
297
308
|
let inputStream;
|
|
298
309
|
if (typeof urlOrStream === "string") {
|
|
299
310
|
try {
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
if (
|
|
303
|
-
|
|
311
|
+
const spec = urlOrStream.trim();
|
|
312
|
+
const lower = spec.toLowerCase();
|
|
313
|
+
if (lower.startsWith("http://") || lower.startsWith("https://")) {
|
|
314
|
+
const response = await fetch(spec);
|
|
315
|
+
if (!response.ok) {
|
|
316
|
+
throw new import_util.FluxerError(`HTTP ${response.status}`, { code: import_util.ErrorCodes.VoiceHttpError });
|
|
317
|
+
}
|
|
318
|
+
if (!response.body) {
|
|
319
|
+
throw new import_util.FluxerError("No response body", { code: import_util.ErrorCodes.VoiceNoResponseBody });
|
|
320
|
+
}
|
|
321
|
+
inputStream = import_node_stream.Readable.fromWeb(response.body);
|
|
322
|
+
} else if (lower.startsWith("file:")) {
|
|
323
|
+
inputStream = (0, import_node_fs.createReadStream)((0, import_node_url.fileURLToPath)(new URL(spec)));
|
|
324
|
+
} else {
|
|
325
|
+
inputStream = (0, import_node_fs.createReadStream)(spec);
|
|
326
|
+
}
|
|
304
327
|
} catch (e) {
|
|
305
|
-
const err = e instanceof
|
|
328
|
+
const err = e instanceof import_util.FluxerError ? e : new import_util.FluxerError(e instanceof Error ? e.message : String(e), {
|
|
329
|
+
code: import_util.ErrorCodes.FileFetchFailed,
|
|
330
|
+
cause: e instanceof Error ? e : void 0
|
|
331
|
+
});
|
|
306
332
|
this.emit("error", err);
|
|
307
333
|
return;
|
|
308
334
|
}
|
|
@@ -404,6 +430,7 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
404
430
|
// src/LiveKitRtcConnection.ts
|
|
405
431
|
var import_node_child_process = require("child_process");
|
|
406
432
|
var import_events2 = require("events");
|
|
433
|
+
var import_util2 = require("@fluxerjs/util");
|
|
407
434
|
var import_rtc_node = require("@livekit/rtc-node");
|
|
408
435
|
|
|
409
436
|
// src/livekit.ts
|
|
@@ -492,7 +519,9 @@ function concatUint8Arrays(a, b) {
|
|
|
492
519
|
}
|
|
493
520
|
|
|
494
521
|
// src/LiveKitRtcConnection.ts
|
|
522
|
+
var import_node_fs2 = require("fs");
|
|
495
523
|
var import_node_stream2 = require("stream");
|
|
524
|
+
var import_node_url2 = require("url");
|
|
496
525
|
var import_opus_decoder = require("opus-decoder");
|
|
497
526
|
var import_prism_media2 = require("prism-media");
|
|
498
527
|
var import_node_util = require("util");
|
|
@@ -911,11 +940,17 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
911
940
|
if (typeof urlOrBuffer === "string") {
|
|
912
941
|
try {
|
|
913
942
|
const response = await fetch(urlOrBuffer);
|
|
914
|
-
if (!response.ok)
|
|
943
|
+
if (!response.ok) {
|
|
944
|
+
throw new import_util2.FluxerError(`HTTP ${response.status}`, { code: import_util2.ErrorCodes.VoiceHttpError });
|
|
945
|
+
}
|
|
915
946
|
const buf = await response.arrayBuffer();
|
|
916
947
|
arrayBuffer = buf;
|
|
917
948
|
} catch (e) {
|
|
918
|
-
|
|
949
|
+
const err = e instanceof import_util2.FluxerError ? e : new import_util2.FluxerError(e instanceof Error ? e.message : String(e), {
|
|
950
|
+
code: import_util2.ErrorCodes.FileFetchFailed,
|
|
951
|
+
cause: e instanceof Error ? e : void 0
|
|
952
|
+
});
|
|
953
|
+
this.emit("error", err);
|
|
919
954
|
return;
|
|
920
955
|
}
|
|
921
956
|
} else if (urlOrBuffer instanceof Uint8Array) {
|
|
@@ -1680,10 +1715,13 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
1680
1715
|
runFFmpeg().catch((e) => this.audioDebug("ffmpeg error", { error: String(e) }));
|
|
1681
1716
|
}
|
|
1682
1717
|
/**
|
|
1683
|
-
* Play audio from a WebM/Opus
|
|
1718
|
+
* Play audio from a WebM/Opus source. Publishes to the LiveKit room as an audio track.
|
|
1719
|
+
*
|
|
1720
|
+
* When `urlOrStream` is a string: `http(s)://` is fetched; `file://` or any other string is read
|
|
1721
|
+
* from the local filesystem (path). Otherwise pass a Node.js ReadableStream.
|
|
1684
1722
|
*
|
|
1685
|
-
* @param urlOrStream -
|
|
1686
|
-
* @emits error - On fetch failure or decode errors
|
|
1723
|
+
* @param urlOrStream - WebM/Opus HTTP(S) URL, `file://` URL, filesystem path, or ReadableStream
|
|
1724
|
+
* @emits error - On fetch/read failure or decode errors
|
|
1687
1725
|
*/
|
|
1688
1726
|
async play(urlOrStream) {
|
|
1689
1727
|
this.stop();
|
|
@@ -1694,12 +1732,28 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
1694
1732
|
let inputStream;
|
|
1695
1733
|
if (typeof urlOrStream === "string") {
|
|
1696
1734
|
try {
|
|
1697
|
-
const
|
|
1698
|
-
|
|
1699
|
-
if (
|
|
1700
|
-
|
|
1735
|
+
const spec = urlOrStream.trim();
|
|
1736
|
+
const lower = spec.toLowerCase();
|
|
1737
|
+
if (lower.startsWith("http://") || lower.startsWith("https://")) {
|
|
1738
|
+
const response = await fetch(spec);
|
|
1739
|
+
if (!response.ok) {
|
|
1740
|
+
throw new import_util2.FluxerError(`HTTP ${response.status}`, { code: import_util2.ErrorCodes.VoiceHttpError });
|
|
1741
|
+
}
|
|
1742
|
+
if (!response.body) {
|
|
1743
|
+
throw new import_util2.FluxerError("No response body", { code: import_util2.ErrorCodes.VoiceNoResponseBody });
|
|
1744
|
+
}
|
|
1745
|
+
inputStream = import_node_stream2.Readable.fromWeb(response.body);
|
|
1746
|
+
} else if (lower.startsWith("file:")) {
|
|
1747
|
+
inputStream = (0, import_node_fs2.createReadStream)((0, import_node_url2.fileURLToPath)(new URL(spec)));
|
|
1748
|
+
} else {
|
|
1749
|
+
inputStream = (0, import_node_fs2.createReadStream)(spec);
|
|
1750
|
+
}
|
|
1701
1751
|
} catch (e) {
|
|
1702
|
-
|
|
1752
|
+
const err = e instanceof import_util2.FluxerError ? e : new import_util2.FluxerError(e instanceof Error ? e.message : String(e), {
|
|
1753
|
+
code: import_util2.ErrorCodes.FileFetchFailed,
|
|
1754
|
+
cause: e instanceof Error ? e : void 0
|
|
1755
|
+
});
|
|
1756
|
+
this.emit("error", err);
|
|
1703
1757
|
return;
|
|
1704
1758
|
}
|
|
1705
1759
|
} else {
|
package/dist/index.mjs
CHANGED
|
@@ -9,10 +9,13 @@ var thumbnail = MINIMAL_PNG_BASE64;
|
|
|
9
9
|
|
|
10
10
|
// src/VoiceConnection.ts
|
|
11
11
|
import { EventEmitter } from "events";
|
|
12
|
+
import { ErrorCodes, FluxerError } from "@fluxerjs/util";
|
|
12
13
|
import * as nacl from "tweetnacl";
|
|
13
14
|
import * as dgram from "dgram";
|
|
14
15
|
import * as ws from "ws";
|
|
16
|
+
import { createReadStream } from "fs";
|
|
15
17
|
import { Readable } from "stream";
|
|
18
|
+
import { fileURLToPath } from "url";
|
|
16
19
|
import { opus } from "prism-media";
|
|
17
20
|
var VOICE_WS_OPCODES = {
|
|
18
21
|
Identify: 0,
|
|
@@ -170,8 +173,11 @@ var VoiceConnection = class extends EventEmitter {
|
|
|
170
173
|
async getWebSocketConstructor() {
|
|
171
174
|
try {
|
|
172
175
|
return ws.default;
|
|
173
|
-
} catch {
|
|
174
|
-
throw new
|
|
176
|
+
} catch (err) {
|
|
177
|
+
throw new FluxerError('Install "ws" for voice support: pnpm add ws', {
|
|
178
|
+
code: ErrorCodes.VoiceWebSocketRequired,
|
|
179
|
+
cause: err instanceof Error ? err : void 0
|
|
180
|
+
});
|
|
175
181
|
}
|
|
176
182
|
}
|
|
177
183
|
sendVoiceOp(op, d) {
|
|
@@ -213,7 +219,7 @@ var VoiceConnection = class extends EventEmitter {
|
|
|
213
219
|
}
|
|
214
220
|
/**
|
|
215
221
|
* Play a stream of raw Opus packets
|
|
216
|
-
* Uses the same queue and 20ms pacing as play(). Use this for
|
|
222
|
+
* Uses the same queue and 20ms pacing as play(). Use this for raw Opus packet streams (e.g. MP3 → PCM → Opus pipelines) when you are not using WebM/Opus.
|
|
217
223
|
*/
|
|
218
224
|
playOpus(stream) {
|
|
219
225
|
this.stop();
|
|
@@ -249,20 +255,40 @@ var VoiceConnection = class extends EventEmitter {
|
|
|
249
255
|
});
|
|
250
256
|
}
|
|
251
257
|
/**
|
|
252
|
-
* Play a direct WebM/Opus
|
|
253
|
-
*
|
|
258
|
+
* Play a direct WebM/Opus source. When `urlOrStream` is a string:
|
|
259
|
+
* - `http://` / `https://` — fetched over the network
|
|
260
|
+
* - `file://` — read from the local filesystem
|
|
261
|
+
* - any other string — treated as a filesystem path (e.g. `./music/track.webm`)
|
|
262
|
+
*
|
|
263
|
+
* You can also pass a Node.js Readable stream. Demuxes with prism-media WebmDemuxer; no FFmpeg;
|
|
264
|
+
* input must be WebM with Opus.
|
|
254
265
|
*/
|
|
255
266
|
async play(urlOrStream) {
|
|
256
267
|
this.stop();
|
|
257
268
|
let inputStream;
|
|
258
269
|
if (typeof urlOrStream === "string") {
|
|
259
270
|
try {
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
if (
|
|
263
|
-
|
|
271
|
+
const spec = urlOrStream.trim();
|
|
272
|
+
const lower = spec.toLowerCase();
|
|
273
|
+
if (lower.startsWith("http://") || lower.startsWith("https://")) {
|
|
274
|
+
const response = await fetch(spec);
|
|
275
|
+
if (!response.ok) {
|
|
276
|
+
throw new FluxerError(`HTTP ${response.status}`, { code: ErrorCodes.VoiceHttpError });
|
|
277
|
+
}
|
|
278
|
+
if (!response.body) {
|
|
279
|
+
throw new FluxerError("No response body", { code: ErrorCodes.VoiceNoResponseBody });
|
|
280
|
+
}
|
|
281
|
+
inputStream = Readable.fromWeb(response.body);
|
|
282
|
+
} else if (lower.startsWith("file:")) {
|
|
283
|
+
inputStream = createReadStream(fileURLToPath(new URL(spec)));
|
|
284
|
+
} else {
|
|
285
|
+
inputStream = createReadStream(spec);
|
|
286
|
+
}
|
|
264
287
|
} catch (e) {
|
|
265
|
-
const err = e instanceof
|
|
288
|
+
const err = e instanceof FluxerError ? e : new FluxerError(e instanceof Error ? e.message : String(e), {
|
|
289
|
+
code: ErrorCodes.FileFetchFailed,
|
|
290
|
+
cause: e instanceof Error ? e : void 0
|
|
291
|
+
});
|
|
266
292
|
this.emit("error", err);
|
|
267
293
|
return;
|
|
268
294
|
}
|
|
@@ -364,6 +390,7 @@ var VoiceConnection = class extends EventEmitter {
|
|
|
364
390
|
// src/LiveKitRtcConnection.ts
|
|
365
391
|
import { execFile, spawn } from "child_process";
|
|
366
392
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
393
|
+
import { ErrorCodes as ErrorCodes2, FluxerError as FluxerError2 } from "@fluxerjs/util";
|
|
367
394
|
import {
|
|
368
395
|
AudioStream,
|
|
369
396
|
Room,
|
|
@@ -466,7 +493,9 @@ function concatUint8Arrays(a, b) {
|
|
|
466
493
|
}
|
|
467
494
|
|
|
468
495
|
// src/LiveKitRtcConnection.ts
|
|
496
|
+
import { createReadStream as createReadStream2 } from "fs";
|
|
469
497
|
import { Readable as Readable2 } from "stream";
|
|
498
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
470
499
|
import { OpusDecoder } from "opus-decoder";
|
|
471
500
|
import { opus as opus2 } from "prism-media";
|
|
472
501
|
import { promisify } from "util";
|
|
@@ -885,11 +914,17 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
|
|
|
885
914
|
if (typeof urlOrBuffer === "string") {
|
|
886
915
|
try {
|
|
887
916
|
const response = await fetch(urlOrBuffer);
|
|
888
|
-
if (!response.ok)
|
|
917
|
+
if (!response.ok) {
|
|
918
|
+
throw new FluxerError2(`HTTP ${response.status}`, { code: ErrorCodes2.VoiceHttpError });
|
|
919
|
+
}
|
|
889
920
|
const buf = await response.arrayBuffer();
|
|
890
921
|
arrayBuffer = buf;
|
|
891
922
|
} catch (e) {
|
|
892
|
-
|
|
923
|
+
const err = e instanceof FluxerError2 ? e : new FluxerError2(e instanceof Error ? e.message : String(e), {
|
|
924
|
+
code: ErrorCodes2.FileFetchFailed,
|
|
925
|
+
cause: e instanceof Error ? e : void 0
|
|
926
|
+
});
|
|
927
|
+
this.emit("error", err);
|
|
893
928
|
return;
|
|
894
929
|
}
|
|
895
930
|
} else if (urlOrBuffer instanceof Uint8Array) {
|
|
@@ -1654,10 +1689,13 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
|
|
|
1654
1689
|
runFFmpeg().catch((e) => this.audioDebug("ffmpeg error", { error: String(e) }));
|
|
1655
1690
|
}
|
|
1656
1691
|
/**
|
|
1657
|
-
* Play audio from a WebM/Opus
|
|
1692
|
+
* Play audio from a WebM/Opus source. Publishes to the LiveKit room as an audio track.
|
|
1693
|
+
*
|
|
1694
|
+
* When `urlOrStream` is a string: `http(s)://` is fetched; `file://` or any other string is read
|
|
1695
|
+
* from the local filesystem (path). Otherwise pass a Node.js ReadableStream.
|
|
1658
1696
|
*
|
|
1659
|
-
* @param urlOrStream -
|
|
1660
|
-
* @emits error - On fetch failure or decode errors
|
|
1697
|
+
* @param urlOrStream - WebM/Opus HTTP(S) URL, `file://` URL, filesystem path, or ReadableStream
|
|
1698
|
+
* @emits error - On fetch/read failure or decode errors
|
|
1661
1699
|
*/
|
|
1662
1700
|
async play(urlOrStream) {
|
|
1663
1701
|
this.stop();
|
|
@@ -1668,12 +1706,28 @@ var LiveKitRtcConnection = class extends EventEmitter2 {
|
|
|
1668
1706
|
let inputStream;
|
|
1669
1707
|
if (typeof urlOrStream === "string") {
|
|
1670
1708
|
try {
|
|
1671
|
-
const
|
|
1672
|
-
|
|
1673
|
-
if (
|
|
1674
|
-
|
|
1709
|
+
const spec = urlOrStream.trim();
|
|
1710
|
+
const lower = spec.toLowerCase();
|
|
1711
|
+
if (lower.startsWith("http://") || lower.startsWith("https://")) {
|
|
1712
|
+
const response = await fetch(spec);
|
|
1713
|
+
if (!response.ok) {
|
|
1714
|
+
throw new FluxerError2(`HTTP ${response.status}`, { code: ErrorCodes2.VoiceHttpError });
|
|
1715
|
+
}
|
|
1716
|
+
if (!response.body) {
|
|
1717
|
+
throw new FluxerError2("No response body", { code: ErrorCodes2.VoiceNoResponseBody });
|
|
1718
|
+
}
|
|
1719
|
+
inputStream = Readable2.fromWeb(response.body);
|
|
1720
|
+
} else if (lower.startsWith("file:")) {
|
|
1721
|
+
inputStream = createReadStream2(fileURLToPath2(new URL(spec)));
|
|
1722
|
+
} else {
|
|
1723
|
+
inputStream = createReadStream2(spec);
|
|
1724
|
+
}
|
|
1675
1725
|
} catch (e) {
|
|
1676
|
-
|
|
1726
|
+
const err = e instanceof FluxerError2 ? e : new FluxerError2(e instanceof Error ? e.message : String(e), {
|
|
1727
|
+
code: ErrorCodes2.FileFetchFailed,
|
|
1728
|
+
cause: e instanceof Error ? e : void 0
|
|
1729
|
+
});
|
|
1730
|
+
this.emit("error", err);
|
|
1677
1731
|
return;
|
|
1678
1732
|
}
|
|
1679
1733
|
} else {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.3.1",
|
|
7
7
|
"description": "Voice support for Fluxer bots",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -39,9 +39,10 @@
|
|
|
39
39
|
"prism-media": "^1.3.5",
|
|
40
40
|
"tweetnacl": "^1.0.3",
|
|
41
41
|
"ws": "^8.18.0",
|
|
42
|
-
"@fluxerjs/collection": "1.
|
|
43
|
-
"@fluxerjs/core": "1.
|
|
44
|
-
"@fluxerjs/types": "1.
|
|
42
|
+
"@fluxerjs/collection": "1.3.1",
|
|
43
|
+
"@fluxerjs/core": "1.3.1",
|
|
44
|
+
"@fluxerjs/types": "1.3.1",
|
|
45
|
+
"@fluxerjs/util": "1.3.1"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
48
|
"@types/node": "^20.0.0",
|