@fluxerjs/voice 1.1.9 → 1.2.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.js +37 -42
- package/dist/index.mjs +2606 -33
- package/package.json +5 -5
- package/dist/chunk-EBO3CZXG.mjs +0 -15
- package/dist/dist-N4IEBIZ4.mjs +0 -2552
package/dist/index.js
CHANGED
|
@@ -800,7 +800,7 @@ var require_EncodedVideoChunk = __commonJS({
|
|
|
800
800
|
"use strict";
|
|
801
801
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
802
802
|
exports2.EncodedVideoChunk = void 0;
|
|
803
|
-
var
|
|
803
|
+
var EncodedVideoChunk2 = class {
|
|
804
804
|
constructor(init) {
|
|
805
805
|
if (!init.type) {
|
|
806
806
|
throw new TypeError("type is required");
|
|
@@ -842,7 +842,7 @@ var require_EncodedVideoChunk = __commonJS({
|
|
|
842
842
|
dest.set(this._data);
|
|
843
843
|
}
|
|
844
844
|
};
|
|
845
|
-
exports2.EncodedVideoChunk =
|
|
845
|
+
exports2.EncodedVideoChunk = EncodedVideoChunk2;
|
|
846
846
|
}
|
|
847
847
|
});
|
|
848
848
|
|
|
@@ -1830,7 +1830,7 @@ var require_VideoDecoder = __commonJS({
|
|
|
1830
1830
|
var codec_registry_1 = require_codec_registry();
|
|
1831
1831
|
var types_1 = require_types();
|
|
1832
1832
|
var native_1 = require_native();
|
|
1833
|
-
var
|
|
1833
|
+
var VideoDecoder2 = class {
|
|
1834
1834
|
static async isConfigSupported(config) {
|
|
1835
1835
|
if (!config.codec) {
|
|
1836
1836
|
return { supported: false, config };
|
|
@@ -2061,7 +2061,7 @@ var require_VideoDecoder = __commonJS({
|
|
|
2061
2061
|
}
|
|
2062
2062
|
}
|
|
2063
2063
|
};
|
|
2064
|
-
exports2.VideoDecoder =
|
|
2064
|
+
exports2.VideoDecoder = VideoDecoder2;
|
|
2065
2065
|
}
|
|
2066
2066
|
});
|
|
2067
2067
|
|
|
@@ -2602,6 +2602,9 @@ var thumbnail = MINIMAL_PNG_BASE64;
|
|
|
2602
2602
|
var import_events = require("events");
|
|
2603
2603
|
var nacl = __toESM(require("tweetnacl"));
|
|
2604
2604
|
var dgram = __toESM(require("dgram"));
|
|
2605
|
+
var ws = __toESM(require("ws"));
|
|
2606
|
+
var import_node_stream = require("stream");
|
|
2607
|
+
var import_prism_media = require("prism-media");
|
|
2605
2608
|
var VOICE_WS_OPCODES = {
|
|
2606
2609
|
Identify: 0,
|
|
2607
2610
|
SelectProtocol: 1,
|
|
@@ -2745,11 +2748,11 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
2745
2748
|
this.voiceWs.removeAllListeners();
|
|
2746
2749
|
}
|
|
2747
2750
|
};
|
|
2748
|
-
const
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2751
|
+
const ws2 = this.voiceWs;
|
|
2752
|
+
ws2.on("open", onOpen);
|
|
2753
|
+
ws2.on("error", onError);
|
|
2754
|
+
ws2.on("message", (data) => onMessage(data));
|
|
2755
|
+
ws2.once("close", () => {
|
|
2753
2756
|
cleanup();
|
|
2754
2757
|
if (!this._destroyed) reject(new Error("Voice WebSocket closed"));
|
|
2755
2758
|
});
|
|
@@ -2757,7 +2760,6 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
2757
2760
|
}
|
|
2758
2761
|
async getWebSocketConstructor() {
|
|
2759
2762
|
try {
|
|
2760
|
-
const ws = await import("ws");
|
|
2761
2763
|
return ws.default;
|
|
2762
2764
|
} catch {
|
|
2763
2765
|
throw new Error('Install "ws" for voice support: pnpm add ws');
|
|
@@ -2843,15 +2845,13 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
2843
2845
|
*/
|
|
2844
2846
|
async play(urlOrStream) {
|
|
2845
2847
|
this.stop();
|
|
2846
|
-
const { opus: prismOpus } = await import("prism-media");
|
|
2847
|
-
const { Readable } = await import("stream");
|
|
2848
2848
|
let inputStream;
|
|
2849
2849
|
if (typeof urlOrStream === "string") {
|
|
2850
2850
|
try {
|
|
2851
2851
|
const response = await fetch(urlOrStream);
|
|
2852
2852
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
2853
2853
|
if (!response.body) throw new Error("No response body");
|
|
2854
|
-
inputStream = Readable.fromWeb(response.body);
|
|
2854
|
+
inputStream = import_node_stream.Readable.fromWeb(response.body);
|
|
2855
2855
|
} catch (e) {
|
|
2856
2856
|
const err = e instanceof Error ? e : new Error(String(e));
|
|
2857
2857
|
this.emit("error", err);
|
|
@@ -2860,7 +2860,7 @@ var VoiceConnection = class extends import_events.EventEmitter {
|
|
|
2860
2860
|
} else {
|
|
2861
2861
|
inputStream = urlOrStream;
|
|
2862
2862
|
}
|
|
2863
|
-
const demuxer = new
|
|
2863
|
+
const demuxer = new import_prism_media.opus.WebmDemuxer();
|
|
2864
2864
|
inputStream.pipe(demuxer);
|
|
2865
2865
|
this._playing = true;
|
|
2866
2866
|
this.currentStream = demuxer;
|
|
@@ -3043,6 +3043,12 @@ function concatUint8Arrays(a, b) {
|
|
|
3043
3043
|
}
|
|
3044
3044
|
|
|
3045
3045
|
// src/LiveKitRtcConnection.ts
|
|
3046
|
+
var import_node_stream2 = require("stream");
|
|
3047
|
+
var import_opus_decoder = require("opus-decoder");
|
|
3048
|
+
var import_prism_media2 = require("prism-media");
|
|
3049
|
+
var import_node_util = require("util");
|
|
3050
|
+
var import_mp4box = require("mp4box");
|
|
3051
|
+
var WebCodecs = __toESM(require_dist());
|
|
3046
3052
|
var SAMPLE_RATE = 48e3;
|
|
3047
3053
|
var CHANNELS2 = 1;
|
|
3048
3054
|
function getNaluByteLength(nalu) {
|
|
@@ -3287,13 +3293,11 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3287
3293
|
this.emit("error", new Error("useFFmpeg requires a URL; buffer/ArrayBuffer not supported"));
|
|
3288
3294
|
return;
|
|
3289
3295
|
}
|
|
3290
|
-
|
|
3291
|
-
let
|
|
3292
|
-
let EncodedVideoChunk;
|
|
3296
|
+
let VideoDecoder2;
|
|
3297
|
+
let EncodedVideoChunk2;
|
|
3293
3298
|
try {
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
EncodedVideoChunk = webcodecs.EncodedVideoChunk;
|
|
3299
|
+
VideoDecoder2 = WebCodecs.VideoDecoder;
|
|
3300
|
+
EncodedVideoChunk2 = WebCodecs.EncodedVideoChunk;
|
|
3297
3301
|
} catch {
|
|
3298
3302
|
this.emit(
|
|
3299
3303
|
"error",
|
|
@@ -3323,7 +3327,7 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3323
3327
|
} else {
|
|
3324
3328
|
arrayBuffer = urlOrBuffer;
|
|
3325
3329
|
}
|
|
3326
|
-
const file = createFile();
|
|
3330
|
+
const file = (0, import_mp4box.createFile)();
|
|
3327
3331
|
const sourceOption = options?.source ?? "camera";
|
|
3328
3332
|
const loop = options?.loop ?? true;
|
|
3329
3333
|
file.onError = (e) => {
|
|
@@ -3377,7 +3381,7 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3377
3381
|
const FRAME_INTERVAL_MS = Math.round(1e3 / maxFps);
|
|
3378
3382
|
const MAX_QUEUED_FRAMES = 30;
|
|
3379
3383
|
let pacingInterval = null;
|
|
3380
|
-
const decoder = new
|
|
3384
|
+
const decoder = new VideoDecoder2({
|
|
3381
3385
|
output: async (frame) => {
|
|
3382
3386
|
if (!this._playingVideo || !source) return;
|
|
3383
3387
|
const { codedWidth, codedHeight } = frame;
|
|
@@ -3503,7 +3507,7 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3503
3507
|
playbackStartMs = null;
|
|
3504
3508
|
frameQueue.length = 0;
|
|
3505
3509
|
samplesReceived = 0;
|
|
3506
|
-
const loopFile = createFile();
|
|
3510
|
+
const loopFile = (0, import_mp4box.createFile)();
|
|
3507
3511
|
loopFile.onError = (e) => {
|
|
3508
3512
|
this._playingVideo = false;
|
|
3509
3513
|
this.emit("error", e);
|
|
@@ -3521,7 +3525,7 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3521
3525
|
try {
|
|
3522
3526
|
for (const sample of samp) {
|
|
3523
3527
|
const isKeyFrame = sample.is_sync ?? sample.is_rap ?? sample.dts === 0;
|
|
3524
|
-
const chunk = new
|
|
3528
|
+
const chunk = new EncodedVideoChunk2({
|
|
3525
3529
|
type: isKeyFrame ? "key" : "delta",
|
|
3526
3530
|
timestamp: Math.round(sample.dts / sample.timescale * 1e6),
|
|
3527
3531
|
duration: Math.round(sample.duration / sample.timescale * 1e6),
|
|
@@ -3560,7 +3564,7 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3560
3564
|
try {
|
|
3561
3565
|
for (const sample of samples) {
|
|
3562
3566
|
const isKeyFrame = sample.is_sync ?? sample.is_rap ?? sample.dts === 0;
|
|
3563
|
-
const chunk = new
|
|
3567
|
+
const chunk = new EncodedVideoChunk2({
|
|
3564
3568
|
type: isKeyFrame ? "key" : "delta",
|
|
3565
3569
|
timestamp: Math.round(sample.dts / sample.timescale * 1e6),
|
|
3566
3570
|
duration: Math.round(sample.duration / sample.timescale * 1e6),
|
|
@@ -3633,8 +3637,6 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3633
3637
|
file.start();
|
|
3634
3638
|
});
|
|
3635
3639
|
if (videoUrl && audioSource && audioTrack) {
|
|
3636
|
-
const { opus: prismOpus } = await import("prism-media");
|
|
3637
|
-
const { OpusDecoder } = await import("opus-decoder");
|
|
3638
3640
|
const runAudioFfmpeg = async () => {
|
|
3639
3641
|
if (!this._playingVideo || cleanupCalled || !audioSource) return;
|
|
3640
3642
|
const audioProc = (0, import_node_child_process.spawn)(
|
|
@@ -3656,9 +3658,9 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3656
3658
|
{ stdio: ["ignore", "pipe", "pipe"] }
|
|
3657
3659
|
);
|
|
3658
3660
|
audioFfmpegProc = audioProc;
|
|
3659
|
-
const demuxer = new
|
|
3661
|
+
const demuxer = new import_prism_media2.opus.WebmDemuxer();
|
|
3660
3662
|
if (audioProc.stdout) audioProc.stdout.pipe(demuxer);
|
|
3661
|
-
const decoder2 = new OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
3663
|
+
const decoder2 = new import_opus_decoder.OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
3662
3664
|
await decoder2.ready;
|
|
3663
3665
|
let sampleBuffer = new Int16Array(0);
|
|
3664
3666
|
let opusBuffer = new Uint8Array(0);
|
|
@@ -3746,9 +3748,7 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
3746
3748
|
let height = 480;
|
|
3747
3749
|
let hasAudio = false;
|
|
3748
3750
|
try {
|
|
3749
|
-
const
|
|
3750
|
-
const { promisify } = await import("util");
|
|
3751
|
-
const exec = promisify(execFile);
|
|
3751
|
+
const exec = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
3752
3752
|
const { stdout } = await exec(
|
|
3753
3753
|
"ffprobe",
|
|
3754
3754
|
[
|
|
@@ -4010,11 +4010,9 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
4010
4010
|
}
|
|
4011
4011
|
if (hasAudio && audioReady && audioSource && proc.stdio[3]) {
|
|
4012
4012
|
const audioPipe = proc.stdio[3];
|
|
4013
|
-
const
|
|
4014
|
-
const { OpusDecoder } = await import("opus-decoder");
|
|
4015
|
-
const demuxer = new prismOpus.WebmDemuxer();
|
|
4013
|
+
const demuxer = new import_prism_media2.opus.WebmDemuxer();
|
|
4016
4014
|
audioPipe.pipe(demuxer);
|
|
4017
|
-
const decoder = new OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
4015
|
+
const decoder = new import_opus_decoder.OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
4018
4016
|
await decoder.ready;
|
|
4019
4017
|
let sampleBuffer = new Int16Array(0);
|
|
4020
4018
|
let opusBuffer = new Uint8Array(0);
|
|
@@ -4094,16 +4092,13 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
4094
4092
|
this.emit("error", new Error("LiveKit: not connected"));
|
|
4095
4093
|
return;
|
|
4096
4094
|
}
|
|
4097
|
-
const { opus: prismOpus } = await import("prism-media");
|
|
4098
|
-
const { Readable } = await import("stream");
|
|
4099
|
-
const { OpusDecoder } = await import("opus-decoder");
|
|
4100
4095
|
let inputStream;
|
|
4101
4096
|
if (typeof urlOrStream === "string") {
|
|
4102
4097
|
try {
|
|
4103
4098
|
const response = await fetch(urlOrStream);
|
|
4104
4099
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
4105
4100
|
if (!response.body) throw new Error("No response body");
|
|
4106
|
-
inputStream = Readable.fromWeb(response.body);
|
|
4101
|
+
inputStream = import_node_stream2.Readable.fromWeb(response.body);
|
|
4107
4102
|
} catch (e) {
|
|
4108
4103
|
this.emit("error", e instanceof Error ? e : new Error(String(e)));
|
|
4109
4104
|
return;
|
|
@@ -4118,10 +4113,10 @@ var LiveKitRtcConnection = class extends import_events2.EventEmitter {
|
|
|
4118
4113
|
const options = new import_rtc_node.TrackPublishOptions();
|
|
4119
4114
|
options.source = import_rtc_node.TrackSource.SOURCE_MICROPHONE;
|
|
4120
4115
|
await this.room.localParticipant.publishTrack(track, options);
|
|
4121
|
-
const demuxer = new
|
|
4116
|
+
const demuxer = new import_prism_media2.opus.WebmDemuxer();
|
|
4122
4117
|
inputStream.pipe(demuxer);
|
|
4123
4118
|
this.currentStream = demuxer;
|
|
4124
|
-
const decoder = new OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
4119
|
+
const decoder = new import_opus_decoder.OpusDecoder({ sampleRate: SAMPLE_RATE, channels: CHANNELS2 });
|
|
4125
4120
|
await decoder.ready;
|
|
4126
4121
|
this._playing = true;
|
|
4127
4122
|
let sampleBuffer = new Int16Array(0);
|