@livekit/rtc-node 0.13.21 → 0.13.23
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/async_queue.cjs +80 -0
- package/dist/async_queue.cjs.map +1 -0
- package/dist/async_queue.d.cts +30 -0
- package/dist/async_queue.d.ts +30 -0
- package/dist/async_queue.d.ts.map +1 -0
- package/dist/async_queue.js +56 -0
- package/dist/async_queue.js.map +1 -0
- package/dist/audio_frame.cjs +5 -0
- package/dist/audio_frame.cjs.map +1 -1
- package/dist/audio_frame.d.cts +3 -0
- package/dist/audio_frame.d.ts +3 -0
- package/dist/audio_frame.d.ts.map +1 -1
- package/dist/audio_frame.js +5 -0
- package/dist/audio_frame.js.map +1 -1
- package/dist/audio_mixer.cjs +281 -0
- package/dist/audio_mixer.cjs.map +1 -0
- package/dist/audio_mixer.d.cts +121 -0
- package/dist/audio_mixer.d.ts +121 -0
- package/dist/audio_mixer.d.ts.map +1 -0
- package/dist/audio_mixer.js +256 -0
- package/dist/audio_mixer.js.map +1 -0
- package/dist/audio_stream.cjs +18 -5
- package/dist/audio_stream.cjs.map +1 -1
- package/dist/audio_stream.d.cts +4 -3
- package/dist/audio_stream.d.ts +4 -3
- package/dist/audio_stream.d.ts.map +1 -1
- package/dist/audio_stream.js +18 -5
- package/dist/audio_stream.js.map +1 -1
- package/dist/data_streams/stream_reader.cjs.map +1 -1
- package/dist/data_streams/stream_reader.js.map +1 -1
- package/dist/frame_processor.cjs +38 -0
- package/dist/frame_processor.cjs.map +1 -0
- package/dist/frame_processor.d.cts +29 -0
- package/dist/frame_processor.d.ts +29 -0
- package/dist/frame_processor.d.ts.map +1 -0
- package/dist/frame_processor.js +14 -0
- package/dist/frame_processor.js.map +1 -0
- package/dist/index.cjs +6 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/participant.cjs +4 -4
- package/dist/participant.cjs.map +1 -1
- package/dist/participant.d.cts +2 -2
- package/dist/participant.d.ts +2 -2
- package/dist/participant.d.ts.map +1 -1
- package/dist/participant.js +4 -4
- package/dist/participant.js.map +1 -1
- package/dist/proto/audio_frame_pb.cjs.map +1 -1
- package/dist/proto/audio_frame_pb.js.map +1 -1
- package/dist/proto/e2ee_pb.cjs.map +1 -1
- package/dist/proto/e2ee_pb.js.map +1 -1
- package/dist/proto/ffi_pb.cjs +4 -2
- package/dist/proto/ffi_pb.cjs.map +1 -1
- package/dist/proto/ffi_pb.d.cts +13 -1
- package/dist/proto/ffi_pb.d.ts +13 -1
- package/dist/proto/ffi_pb.d.ts.map +1 -1
- package/dist/proto/ffi_pb.js +5 -3
- package/dist/proto/ffi_pb.js.map +1 -1
- package/dist/proto/handle_pb.cjs.map +1 -1
- package/dist/proto/handle_pb.js.map +1 -1
- package/dist/proto/participant_pb.cjs +26 -4
- package/dist/proto/participant_pb.cjs.map +1 -1
- package/dist/proto/participant_pb.d.cts +31 -2
- package/dist/proto/participant_pb.d.ts +31 -2
- package/dist/proto/participant_pb.d.ts.map +1 -1
- package/dist/proto/participant_pb.js +24 -3
- package/dist/proto/participant_pb.js.map +1 -1
- package/dist/proto/room_pb.cjs +29 -2
- package/dist/proto/room_pb.cjs.map +1 -1
- package/dist/proto/room_pb.d.cts +30 -7
- package/dist/proto/room_pb.d.ts +30 -7
- package/dist/proto/room_pb.d.ts.map +1 -1
- package/dist/proto/room_pb.js +28 -2
- package/dist/proto/room_pb.js.map +1 -1
- package/dist/proto/rpc_pb.cjs.map +1 -1
- package/dist/proto/rpc_pb.js.map +1 -1
- package/dist/proto/stats_pb.cjs.map +1 -1
- package/dist/proto/stats_pb.js.map +1 -1
- package/dist/proto/track_pb.cjs.map +1 -1
- package/dist/proto/track_pb.js.map +1 -1
- package/dist/proto/track_publication_pb.cjs +66 -2
- package/dist/proto/track_publication_pb.cjs.map +1 -1
- package/dist/proto/track_publication_pb.d.cts +56 -1
- package/dist/proto/track_publication_pb.d.ts +56 -1
- package/dist/proto/track_publication_pb.d.ts.map +1 -1
- package/dist/proto/track_publication_pb.js +62 -1
- package/dist/proto/track_publication_pb.js.map +1 -1
- package/dist/proto/video_frame_pb.cjs +3 -1
- package/dist/proto/video_frame_pb.cjs.map +1 -1
- package/dist/proto/video_frame_pb.d.cts +5 -1
- package/dist/proto/video_frame_pb.d.ts +5 -1
- package/dist/proto/video_frame_pb.d.ts.map +1 -1
- package/dist/proto/video_frame_pb.js +3 -1
- package/dist/proto/video_frame_pb.js.map +1 -1
- package/dist/room.cjs +286 -288
- package/dist/room.cjs.map +1 -1
- package/dist/room.d.cts +11 -11
- package/dist/room.d.ts +11 -11
- package/dist/room.d.ts.map +1 -1
- package/dist/room.js +287 -289
- package/dist/room.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +9 -8
- package/src/async_queue.test.ts +250 -0
- package/src/async_queue.ts +80 -0
- package/src/audio_frame.ts +7 -0
- package/src/audio_mixer.test.ts +167 -0
- package/src/audio_mixer.ts +407 -0
- package/src/audio_stream.ts +22 -7
- package/src/data_streams/stream_reader.ts +4 -4
- package/src/frame_processor.ts +29 -0
- package/src/index.ts +6 -0
- package/src/participant.ts +5 -5
- package/src/proto/audio_frame_pb.ts +1 -1
- package/src/proto/e2ee_pb.ts +1 -1
- package/src/proto/ffi_pb.ts +16 -2
- package/src/proto/handle_pb.ts +1 -1
- package/src/proto/participant_pb.ts +45 -1
- package/src/proto/room_pb.ts +52 -8
- package/src/proto/rpc_pb.ts +1 -1
- package/src/proto/stats_pb.ts +1 -1
- package/src/proto/track_pb.ts +1 -1
- package/src/proto/track_publication_pb.ts +105 -1
- package/src/proto/video_frame_pb.ts +7 -1
- package/src/room.ts +297 -300
- package/src/version.ts +1 -1
package/dist/room.js
CHANGED
|
@@ -5,7 +5,7 @@ import { E2EEManager, defaultE2EEOptions } from "./e2ee.js";
|
|
|
5
5
|
import { FfiClient, FfiClientEvent, FfiHandle } from "./ffi_client.js";
|
|
6
6
|
import { log } from "./log.js";
|
|
7
7
|
import { LocalParticipant, RemoteParticipant } from "./participant.js";
|
|
8
|
-
import { EncryptionState
|
|
8
|
+
import { EncryptionState } from "./proto/e2ee_pb.js";
|
|
9
9
|
import {
|
|
10
10
|
ConnectRequest,
|
|
11
11
|
ConnectionState,
|
|
@@ -39,7 +39,7 @@ class Room extends EventEmitter {
|
|
|
39
39
|
* the local participant to acquire the lock while doing state updates related to FFI events
|
|
40
40
|
* before processing the next events
|
|
41
41
|
*/
|
|
42
|
-
this.
|
|
42
|
+
this.ffiEventLock = new Mutex();
|
|
43
43
|
this.byteStreamControllers = /* @__PURE__ */ new Map();
|
|
44
44
|
this.textStreamControllers = /* @__PURE__ */ new Map();
|
|
45
45
|
this.byteStreamHandlers = /* @__PURE__ */ new Map();
|
|
@@ -48,304 +48,302 @@ class Room extends EventEmitter {
|
|
|
48
48
|
this.connectionState = ConnectionState.CONN_DISCONNECTED;
|
|
49
49
|
this.remoteParticipants = /* @__PURE__ */ new Map();
|
|
50
50
|
this.onFfiEvent = async (ffiEvent) => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
const unlock = await this.ffiEventLock.lock();
|
|
52
|
+
try {
|
|
53
|
+
if (!this.localParticipant || !this.ffiHandle || !this.info) {
|
|
54
|
+
this.preConnectEvents.push(ffiEvent);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
for (const ev of this.preConnectEvents) {
|
|
58
|
+
await this.processFfiEvent(ev);
|
|
59
|
+
}
|
|
60
|
+
this.preConnectEvents = [];
|
|
61
|
+
await this.processFfiEvent(ffiEvent);
|
|
62
|
+
} finally {
|
|
63
|
+
unlock();
|
|
57
64
|
}
|
|
58
|
-
this.preConnectEvents = [];
|
|
59
|
-
await this.processFfiEvent(ffiEvent);
|
|
60
65
|
};
|
|
61
66
|
this.processFfiEvent = async (ffiEvent) => {
|
|
62
67
|
if (!this.localParticipant || !this.ffiHandle || !this.info) {
|
|
63
68
|
throw new Error("processFfiEvent called before connect");
|
|
64
69
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
ffiEvent.message.value.responseTimeoutMs
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
return;
|
|
79
|
-
} else if (ffiEvent.message.case != "roomEvent" || ffiEvent.message.value.roomHandle != this.ffiHandle.handle) {
|
|
80
|
-
return;
|
|
70
|
+
if (ffiEvent.message.case == "rpcMethodInvocation") {
|
|
71
|
+
if (ffiEvent.message.value.localParticipantHandle == this.localParticipant.ffi_handle.handle) {
|
|
72
|
+
this.localParticipant.handleRpcMethodInvocation(
|
|
73
|
+
ffiEvent.message.value.invocationId,
|
|
74
|
+
ffiEvent.message.value.method,
|
|
75
|
+
ffiEvent.message.value.requestId,
|
|
76
|
+
ffiEvent.message.value.callerIdentity,
|
|
77
|
+
ffiEvent.message.value.payload,
|
|
78
|
+
ffiEvent.message.value.responseTimeoutMs
|
|
79
|
+
);
|
|
81
80
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
return;
|
|
82
|
+
} else if (ffiEvent.message.case != "roomEvent" || ffiEvent.message.value.roomHandle != this.ffiHandle.handle) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const ev = ffiEvent.message.value.message;
|
|
86
|
+
if (process.env.LIVEKIT_DEBUG_LOG_ROOM_EVENTS) {
|
|
87
|
+
console.log("Room event:", ev);
|
|
88
|
+
}
|
|
89
|
+
if (ev.case == "participantConnected") {
|
|
90
|
+
const participant = this.createRemoteParticipant(ev.value.info);
|
|
91
|
+
this.remoteParticipants.set(participant.identity, participant);
|
|
92
|
+
this.emit("participantConnected" /* ParticipantConnected */, participant);
|
|
93
|
+
} else if (ev.case == "participantDisconnected") {
|
|
94
|
+
const participant = this.remoteParticipants.get(ev.value.participantIdentity);
|
|
95
|
+
if (participant) {
|
|
96
|
+
this.remoteParticipants.delete(participant.identity);
|
|
97
|
+
participant.info.disconnectReason = ev.value.disconnectReason;
|
|
98
|
+
this.emit("participantDisconnected" /* ParticipantDisconnected */, participant);
|
|
99
|
+
} else {
|
|
100
|
+
console.log(`RoomEvent.ParticipantDisconnected: Could not find participant`);
|
|
85
101
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
} else
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
102
|
+
} else if (ev.case == "localTrackPublished") {
|
|
103
|
+
const publication = this.localParticipant.trackPublications.get(ev.value.trackSid);
|
|
104
|
+
this.emit("localTrackPublished" /* LocalTrackPublished */, publication, this.localParticipant);
|
|
105
|
+
} else if (ev.case == "localTrackUnpublished") {
|
|
106
|
+
const publication = this.localParticipant.trackPublications.get(ev.value.publicationSid);
|
|
107
|
+
this.localParticipant.trackPublications.delete(ev.value.publicationSid);
|
|
108
|
+
this.emit("localTrackUnpublished" /* LocalTrackUnpublished */, publication, this.localParticipant);
|
|
109
|
+
} else if (ev.case == "localTrackSubscribed") {
|
|
110
|
+
const publication = this.localParticipant.trackPublications.get(ev.value.trackSid);
|
|
111
|
+
if (publication) {
|
|
112
|
+
publication.resolveFirstSubscription();
|
|
113
|
+
this.emit("localTrackSubscribed" /* LocalTrackSubscribed */, publication.track);
|
|
114
|
+
} else {
|
|
115
|
+
console.warn(`RoomEvent.LocalTrackSubscribed: Publication not found: ${ev.value.trackSid}`);
|
|
116
|
+
}
|
|
117
|
+
} else if (ev.case == "trackPublished") {
|
|
118
|
+
const participant = this.remoteParticipants.get(ev.value.participantIdentity);
|
|
119
|
+
const publication = new RemoteTrackPublication(ev.value.publication);
|
|
120
|
+
if (participant) {
|
|
121
|
+
participant.trackPublications.set(publication.sid, publication);
|
|
122
|
+
} else {
|
|
123
|
+
console.warn(
|
|
124
|
+
`RoomEvent.TrackPublished: Could not find participant: ${ev.value.participantIdentity}`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
this.emit("trackPublished" /* TrackPublished */, publication, participant);
|
|
128
|
+
} else if (ev.case == "trackUnpublished") {
|
|
129
|
+
const participant = this.requireRemoteParticipant(ev.value.participantIdentity);
|
|
130
|
+
const publication = participant.trackPublications.get(ev.value.publicationSid);
|
|
131
|
+
participant.trackPublications.delete(ev.value.publicationSid);
|
|
132
|
+
if (publication) {
|
|
133
|
+
this.emit("trackUnpublished" /* TrackUnpublished */, publication, participant);
|
|
134
|
+
} else {
|
|
135
|
+
console.warn(`RoomEvent.TrackUnpublished: Could not find publication`);
|
|
136
|
+
}
|
|
137
|
+
} else if (ev.case == "trackSubscribed") {
|
|
138
|
+
const ownedTrack = ev.value.track;
|
|
139
|
+
const trackInfo = ownedTrack.info;
|
|
140
|
+
try {
|
|
141
|
+
const { participant, publication } = this.requirePublicationOfRemoteParticipant(
|
|
142
|
+
ev.value.participantIdentity,
|
|
143
|
+
trackInfo.sid
|
|
144
|
+
);
|
|
145
|
+
publication.subscribed = true;
|
|
146
|
+
if (trackInfo.kind == TrackKind.KIND_VIDEO) {
|
|
147
|
+
publication.track = new RemoteVideoTrack(ownedTrack);
|
|
148
|
+
} else if (trackInfo.kind == TrackKind.KIND_AUDIO) {
|
|
149
|
+
publication.track = new RemoteAudioTrack(ownedTrack);
|
|
125
150
|
}
|
|
126
|
-
this.emit("
|
|
127
|
-
}
|
|
151
|
+
this.emit("trackSubscribed" /* TrackSubscribed */, publication.track, publication, participant);
|
|
152
|
+
} catch (e) {
|
|
153
|
+
console.warn(`RoomEvent.TrackSubscribed: ${e.message}`);
|
|
154
|
+
}
|
|
155
|
+
} else if (ev.case == "trackUnsubscribed") {
|
|
156
|
+
try {
|
|
157
|
+
const { participant, publication } = this.requirePublicationOfRemoteParticipant(
|
|
158
|
+
ev.value.participantIdentity,
|
|
159
|
+
ev.value.trackSid
|
|
160
|
+
);
|
|
161
|
+
const track = publication.track;
|
|
162
|
+
publication.track = void 0;
|
|
163
|
+
publication.subscribed = false;
|
|
164
|
+
this.emit("trackUnsubscribed" /* TrackUnsubscribed */, track, publication, participant);
|
|
165
|
+
} catch (e) {
|
|
166
|
+
console.warn(`RoomEvent.TrackUnsubscribed: ${e.message}`);
|
|
167
|
+
}
|
|
168
|
+
} else if (ev.case == "trackSubscriptionFailed") {
|
|
169
|
+
try {
|
|
128
170
|
const participant = this.requireRemoteParticipant(ev.value.participantIdentity);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
} else if (trackInfo.kind == TrackKind.KIND_AUDIO) {
|
|
148
|
-
publication.track = new RemoteAudioTrack(ownedTrack);
|
|
149
|
-
}
|
|
150
|
-
this.emit("trackSubscribed" /* TrackSubscribed */, publication.track, publication, participant);
|
|
151
|
-
} catch (e) {
|
|
152
|
-
console.warn(`RoomEvent.TrackSubscribed: ${e.message}`);
|
|
153
|
-
}
|
|
154
|
-
} else if (ev.case == "trackUnsubscribed") {
|
|
155
|
-
try {
|
|
156
|
-
const { participant, publication } = this.requirePublicationOfRemoteParticipant(
|
|
157
|
-
ev.value.participantIdentity,
|
|
158
|
-
ev.value.trackSid
|
|
159
|
-
);
|
|
160
|
-
const track = publication.track;
|
|
161
|
-
publication.track = void 0;
|
|
162
|
-
publication.subscribed = false;
|
|
163
|
-
this.emit("trackUnsubscribed" /* TrackUnsubscribed */, track, publication, participant);
|
|
164
|
-
} catch (e) {
|
|
165
|
-
console.warn(`RoomEvent.TrackUnsubscribed: ${e.message}`);
|
|
166
|
-
}
|
|
167
|
-
} else if (ev.case == "trackSubscriptionFailed") {
|
|
168
|
-
try {
|
|
169
|
-
const participant = this.requireRemoteParticipant(ev.value.participantIdentity);
|
|
170
|
-
this.emit(
|
|
171
|
-
"trackSubscriptionFailed" /* TrackSubscriptionFailed */,
|
|
172
|
-
ev.value.trackSid,
|
|
173
|
-
participant,
|
|
174
|
-
ev.value.error
|
|
175
|
-
);
|
|
176
|
-
} catch (e) {
|
|
177
|
-
console.warn(`RoomEvent.TrackSubscriptionFailed: ${e.message}`);
|
|
178
|
-
}
|
|
179
|
-
} else if (ev.case == "trackMuted") {
|
|
180
|
-
try {
|
|
181
|
-
const { participant, publication } = this.requirePublicationOfParticipant(
|
|
182
|
-
ev.value.participantIdentity,
|
|
183
|
-
ev.value.trackSid
|
|
184
|
-
);
|
|
185
|
-
publication.info.muted = true;
|
|
186
|
-
if (publication.track) {
|
|
187
|
-
publication.track.info.muted = true;
|
|
188
|
-
}
|
|
189
|
-
this.emit("trackMuted" /* TrackMuted */, publication, participant);
|
|
190
|
-
} catch (e) {
|
|
191
|
-
console.warn(`RoomEvent.TrackMuted: ${e.message}`);
|
|
192
|
-
}
|
|
193
|
-
} else if (ev.case == "trackUnmuted") {
|
|
194
|
-
try {
|
|
195
|
-
const { participant, publication } = this.requirePublicationOfParticipant(
|
|
196
|
-
ev.value.participantIdentity,
|
|
197
|
-
ev.value.trackSid
|
|
198
|
-
);
|
|
199
|
-
publication.info.muted = false;
|
|
200
|
-
if (publication.track) {
|
|
201
|
-
publication.track.info.muted = false;
|
|
202
|
-
}
|
|
203
|
-
this.emit("trackUnmuted" /* TrackUnmuted */, publication, participant);
|
|
204
|
-
} catch (e) {
|
|
205
|
-
console.warn(`RoomEvent.TrackUnmuted: ${e.message}`);
|
|
206
|
-
}
|
|
207
|
-
} else if (ev.case == "activeSpeakersChanged") {
|
|
208
|
-
try {
|
|
209
|
-
const activeSpeakers = ev.value.participantIdentities.map(
|
|
210
|
-
(identity) => this.requireParticipantByIdentity(identity)
|
|
211
|
-
);
|
|
212
|
-
this.emit("activeSpeakersChanged" /* ActiveSpeakersChanged */, activeSpeakers);
|
|
213
|
-
} catch (e) {
|
|
214
|
-
console.warn(`RoomEvent.ActiveSpeakersChanged: ${e.message}`);
|
|
215
|
-
}
|
|
216
|
-
} else if (ev.case == "roomMetadataChanged") {
|
|
217
|
-
this.info.metadata = ev.value.metadata ?? "";
|
|
218
|
-
this.emit("roomMetadataChanged" /* RoomMetadataChanged */, this.info.metadata);
|
|
219
|
-
} else if (ev.case == "participantMetadataChanged") {
|
|
220
|
-
try {
|
|
221
|
-
const participant = this.requireParticipantByIdentity(ev.value.participantIdentity);
|
|
222
|
-
participant.info.metadata = ev.value.metadata;
|
|
223
|
-
this.emit("participantMetadataChanged" /* ParticipantMetadataChanged */, participant.metadata, participant);
|
|
224
|
-
} catch (e) {
|
|
225
|
-
console.warn(`RoomEvent.ParticipantMetadataChanged: ${e.message}`);
|
|
171
|
+
this.emit(
|
|
172
|
+
"trackSubscriptionFailed" /* TrackSubscriptionFailed */,
|
|
173
|
+
ev.value.trackSid,
|
|
174
|
+
participant,
|
|
175
|
+
ev.value.error
|
|
176
|
+
);
|
|
177
|
+
} catch (e) {
|
|
178
|
+
console.warn(`RoomEvent.TrackSubscriptionFailed: ${e.message}`);
|
|
179
|
+
}
|
|
180
|
+
} else if (ev.case == "trackMuted") {
|
|
181
|
+
try {
|
|
182
|
+
const { participant, publication } = this.requirePublicationOfParticipant(
|
|
183
|
+
ev.value.participantIdentity,
|
|
184
|
+
ev.value.trackSid
|
|
185
|
+
);
|
|
186
|
+
publication.info.muted = true;
|
|
187
|
+
if (publication.track) {
|
|
188
|
+
publication.track.info.muted = true;
|
|
226
189
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
190
|
+
this.emit("trackMuted" /* TrackMuted */, publication, participant);
|
|
191
|
+
} catch (e) {
|
|
192
|
+
console.warn(`RoomEvent.TrackMuted: ${e.message}`);
|
|
193
|
+
}
|
|
194
|
+
} else if (ev.case == "trackUnmuted") {
|
|
195
|
+
try {
|
|
196
|
+
const { participant, publication } = this.requirePublicationOfParticipant(
|
|
197
|
+
ev.value.participantIdentity,
|
|
198
|
+
ev.value.trackSid
|
|
199
|
+
);
|
|
200
|
+
publication.info.muted = false;
|
|
201
|
+
if (publication.track) {
|
|
202
|
+
publication.track.info.muted = false;
|
|
234
203
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
204
|
+
this.emit("trackUnmuted" /* TrackUnmuted */, publication, participant);
|
|
205
|
+
} catch (e) {
|
|
206
|
+
console.warn(`RoomEvent.TrackUnmuted: ${e.message}`);
|
|
207
|
+
}
|
|
208
|
+
} else if (ev.case == "activeSpeakersChanged") {
|
|
209
|
+
try {
|
|
210
|
+
const activeSpeakers = ev.value.participantIdentities.map(
|
|
211
|
+
(identity) => this.requireParticipantByIdentity(identity)
|
|
212
|
+
);
|
|
213
|
+
this.emit("activeSpeakersChanged" /* ActiveSpeakersChanged */, activeSpeakers);
|
|
214
|
+
} catch (e) {
|
|
215
|
+
console.warn(`RoomEvent.ActiveSpeakersChanged: ${e.message}`);
|
|
216
|
+
}
|
|
217
|
+
} else if (ev.case == "roomMetadataChanged") {
|
|
218
|
+
this.info.metadata = ev.value.metadata ?? "";
|
|
219
|
+
this.emit("roomMetadataChanged" /* RoomMetadataChanged */, this.info.metadata);
|
|
220
|
+
} else if (ev.case == "participantMetadataChanged") {
|
|
221
|
+
try {
|
|
222
|
+
const participant = this.requireParticipantByIdentity(ev.value.participantIdentity);
|
|
223
|
+
participant.info.metadata = ev.value.metadata;
|
|
224
|
+
this.emit("participantMetadataChanged" /* ParticipantMetadataChanged */, participant.metadata, participant);
|
|
225
|
+
} catch (e) {
|
|
226
|
+
console.warn(`RoomEvent.ParticipantMetadataChanged: ${e.message}`);
|
|
227
|
+
}
|
|
228
|
+
} else if (ev.case == "participantNameChanged") {
|
|
229
|
+
try {
|
|
230
|
+
const participant = this.requireParticipantByIdentity(ev.value.participantIdentity);
|
|
231
|
+
participant.info.name = ev.value.name;
|
|
232
|
+
this.emit("participantNameChanged" /* ParticipantNameChanged */, participant.name, participant);
|
|
233
|
+
} catch (e) {
|
|
234
|
+
console.warn(`RoomEvent.ParticipantNameChanged: ${e.message}`);
|
|
235
|
+
}
|
|
236
|
+
} else if (ev.case == "participantAttributesChanged") {
|
|
237
|
+
try {
|
|
238
|
+
const participant = this.requireParticipantByIdentity(ev.value.participantIdentity);
|
|
239
|
+
participant.info.attributes = ev.value.attributes.reduce(
|
|
240
|
+
(acc, value) => {
|
|
241
|
+
acc[value.key] = value.value;
|
|
242
|
+
return acc;
|
|
243
|
+
},
|
|
244
|
+
{}
|
|
245
|
+
);
|
|
246
|
+
if (Object.keys(ev.value.changedAttributes).length > 0) {
|
|
247
|
+
const changedAttributes = ev.value.changedAttributes.reduce(
|
|
239
248
|
(acc, value) => {
|
|
240
249
|
acc[value.key] = value.value;
|
|
241
250
|
return acc;
|
|
242
251
|
},
|
|
243
252
|
{}
|
|
244
253
|
);
|
|
245
|
-
|
|
246
|
-
const changedAttributes = ev.value.changedAttributes.reduce(
|
|
247
|
-
(acc, value) => {
|
|
248
|
-
acc[value.key] = value.value;
|
|
249
|
-
return acc;
|
|
250
|
-
},
|
|
251
|
-
{}
|
|
252
|
-
);
|
|
253
|
-
this.emit("participantAttributesChanged" /* ParticipantAttributesChanged */, changedAttributes, participant);
|
|
254
|
-
}
|
|
255
|
-
} catch (e) {
|
|
256
|
-
console.warn(`RoomEvent.ParticipantAttributesChanged: ${e.message}`);
|
|
257
|
-
}
|
|
258
|
-
} else if (ev.case == "connectionQualityChanged") {
|
|
259
|
-
try {
|
|
260
|
-
const participant = this.requireParticipantByIdentity(ev.value.participantIdentity);
|
|
261
|
-
this.emit("connectionQualityChanged" /* ConnectionQualityChanged */, ev.value.quality, participant);
|
|
262
|
-
} catch (e) {
|
|
263
|
-
console.warn(`RoomEvent.ConnectionQualityChanged: ${e.message}`);
|
|
264
|
-
}
|
|
265
|
-
} else if (ev.case == "chatMessage") {
|
|
266
|
-
const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity);
|
|
267
|
-
const { id, message: messageText, timestamp, editTimestamp, generated } = ev.value.message;
|
|
268
|
-
const message = {
|
|
269
|
-
id,
|
|
270
|
-
message: messageText,
|
|
271
|
-
timestamp: Number(timestamp),
|
|
272
|
-
editTimestamp: Number(editTimestamp),
|
|
273
|
-
generated
|
|
274
|
-
};
|
|
275
|
-
this.emit("chatMessage" /* ChatMessage */, message, participant);
|
|
276
|
-
} else if (ev.case == "dataPacketReceived") {
|
|
277
|
-
const participant = this.remoteParticipants.get(ev.value.participantIdentity);
|
|
278
|
-
const dataPacket = ev.value.value;
|
|
279
|
-
switch (dataPacket.case) {
|
|
280
|
-
case "user":
|
|
281
|
-
const buffer = FfiClient.instance.copyBuffer(
|
|
282
|
-
dataPacket.value.data.data.dataPtr,
|
|
283
|
-
Number(dataPacket.value.data.data.dataLen)
|
|
284
|
-
);
|
|
285
|
-
new FfiHandle(dataPacket.value.data.handle.id).dispose();
|
|
286
|
-
this.emit(
|
|
287
|
-
"dataReceived" /* DataReceived */,
|
|
288
|
-
buffer,
|
|
289
|
-
participant,
|
|
290
|
-
ev.value.kind,
|
|
291
|
-
dataPacket.value.topic
|
|
292
|
-
);
|
|
293
|
-
break;
|
|
294
|
-
case "sipDtmf":
|
|
295
|
-
const { code, digit } = dataPacket.value;
|
|
296
|
-
this.emit("dtmfReceived" /* DtmfReceived */, code, digit, participant);
|
|
297
|
-
break;
|
|
298
|
-
default:
|
|
299
|
-
break;
|
|
300
|
-
}
|
|
301
|
-
} else if (ev.case == "e2eeStateChanged") {
|
|
302
|
-
if (ev.value.state == EncryptionState.INTERNAL_ERROR) {
|
|
303
|
-
this.emit("encryptionError" /* EncryptionError */, new Error("internal server error"));
|
|
254
|
+
this.emit("participantAttributesChanged" /* ParticipantAttributesChanged */, changedAttributes, participant);
|
|
304
255
|
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
this.emit("
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
try {
|
|
337
|
-
const participant = this.requireParticipantByIdentity(ev.value.participantIdentity);
|
|
256
|
+
} catch (e) {
|
|
257
|
+
console.warn(`RoomEvent.ParticipantAttributesChanged: ${e.message}`);
|
|
258
|
+
}
|
|
259
|
+
} else if (ev.case == "connectionQualityChanged") {
|
|
260
|
+
try {
|
|
261
|
+
const participant = this.requireParticipantByIdentity(ev.value.participantIdentity);
|
|
262
|
+
this.emit("connectionQualityChanged" /* ConnectionQualityChanged */, ev.value.quality, participant);
|
|
263
|
+
} catch (e) {
|
|
264
|
+
console.warn(`RoomEvent.ConnectionQualityChanged: ${e.message}`);
|
|
265
|
+
}
|
|
266
|
+
} else if (ev.case == "chatMessage") {
|
|
267
|
+
const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity);
|
|
268
|
+
const { id, message: messageText, timestamp, editTimestamp, generated } = ev.value.message;
|
|
269
|
+
const message = {
|
|
270
|
+
id,
|
|
271
|
+
message: messageText,
|
|
272
|
+
timestamp: Number(timestamp),
|
|
273
|
+
editTimestamp: Number(editTimestamp),
|
|
274
|
+
generated
|
|
275
|
+
};
|
|
276
|
+
this.emit("chatMessage" /* ChatMessage */, message, participant);
|
|
277
|
+
} else if (ev.case == "dataPacketReceived") {
|
|
278
|
+
const participant = this.remoteParticipants.get(ev.value.participantIdentity);
|
|
279
|
+
const dataPacket = ev.value.value;
|
|
280
|
+
switch (dataPacket.case) {
|
|
281
|
+
case "user":
|
|
282
|
+
const buffer = FfiClient.instance.copyBuffer(
|
|
283
|
+
dataPacket.value.data.data.dataPtr,
|
|
284
|
+
Number(dataPacket.value.data.data.dataLen)
|
|
285
|
+
);
|
|
286
|
+
new FfiHandle(dataPacket.value.data.handle.id).dispose();
|
|
338
287
|
this.emit(
|
|
339
|
-
"
|
|
340
|
-
|
|
341
|
-
participant
|
|
288
|
+
"dataReceived" /* DataReceived */,
|
|
289
|
+
buffer,
|
|
290
|
+
participant,
|
|
291
|
+
ev.value.kind,
|
|
292
|
+
dataPacket.value.topic
|
|
342
293
|
);
|
|
343
|
-
|
|
344
|
-
|
|
294
|
+
break;
|
|
295
|
+
case "sipDtmf":
|
|
296
|
+
const { code, digit } = dataPacket.value;
|
|
297
|
+
this.emit("dtmfReceived" /* DtmfReceived */, code, digit, participant);
|
|
298
|
+
break;
|
|
299
|
+
default:
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
} else if (ev.case == "e2eeStateChanged") {
|
|
303
|
+
if (ev.value.state == EncryptionState.INTERNAL_ERROR) {
|
|
304
|
+
this.emit("encryptionError" /* EncryptionError */, new Error("internal server error"));
|
|
305
|
+
}
|
|
306
|
+
} else if (ev.case == "connectionStateChanged") {
|
|
307
|
+
this.connectionState = ev.value.state;
|
|
308
|
+
this.emit("connectionStateChanged" /* ConnectionStateChanged */, this.connectionState);
|
|
309
|
+
} else if (ev.case == "disconnected") {
|
|
310
|
+
this.emit("disconnected" /* Disconnected */, ev.value.reason);
|
|
311
|
+
} else if (ev.case == "reconnecting") {
|
|
312
|
+
this.emit("reconnecting" /* Reconnecting */);
|
|
313
|
+
} else if (ev.case == "reconnected") {
|
|
314
|
+
this.emit("reconnected" /* Reconnected */);
|
|
315
|
+
} else if (ev.case == "roomSidChanged") {
|
|
316
|
+
this.emit("roomSidChanged" /* RoomSidChanged */, ev.value.sid);
|
|
317
|
+
} else if (ev.case === "streamHeaderReceived" && ev.value.header) {
|
|
318
|
+
this.handleStreamHeader(ev.value.header, ev.value.participantIdentity);
|
|
319
|
+
} else if (ev.case === "streamChunkReceived" && ev.value.chunk) {
|
|
320
|
+
this.handleStreamChunk(ev.value.chunk);
|
|
321
|
+
} else if (ev.case === "streamTrailerReceived" && ev.value.trailer) {
|
|
322
|
+
this.handleStreamTrailer(ev.value.trailer);
|
|
323
|
+
} else if (ev.case === "roomUpdated") {
|
|
324
|
+
this.info = ev.value;
|
|
325
|
+
this.emit("roomUpdated" /* RoomUpdated */);
|
|
326
|
+
} else if (ev.case === "moved") {
|
|
327
|
+
this.info = ev.value;
|
|
328
|
+
this.emit("moved" /* Moved */);
|
|
329
|
+
} else if (ev.case === "participantsUpdated") {
|
|
330
|
+
for (const info of ev.value.participants) {
|
|
331
|
+
const participant = this.retrieveParticipantByIdentity(info.identity);
|
|
332
|
+
if (participant) {
|
|
333
|
+
participant.info = info;
|
|
345
334
|
}
|
|
346
335
|
}
|
|
347
|
-
}
|
|
348
|
-
|
|
336
|
+
} else if (ev.case === "participantEncryptionStatusChanged") {
|
|
337
|
+
try {
|
|
338
|
+
const participant = this.requireParticipantByIdentity(ev.value.participantIdentity);
|
|
339
|
+
this.emit(
|
|
340
|
+
"participantEncryptionStatusChanged" /* ParticipantEncryptionStatusChanged */,
|
|
341
|
+
!!ev.value.isEncrypted,
|
|
342
|
+
participant
|
|
343
|
+
);
|
|
344
|
+
} catch (e) {
|
|
345
|
+
console.warn(`RoomEvent.ParticipantEncryptionStatusChanged: ${e.message}`);
|
|
346
|
+
}
|
|
349
347
|
}
|
|
350
348
|
};
|
|
351
349
|
}
|
|
@@ -421,10 +419,10 @@ class Room extends EventEmitter {
|
|
|
421
419
|
}
|
|
422
420
|
/**
|
|
423
421
|
* Connects to a LiveKit room using the provided URL and access token.
|
|
424
|
-
* @param url The WebSocket URL of the LiveKit server
|
|
425
|
-
* @param token A valid LiveKit access token for authentication
|
|
426
|
-
* @param opts Optional room configuration options
|
|
427
|
-
* @throws ConnectError if connection fails
|
|
422
|
+
* @param url - The WebSocket URL of the LiveKit server
|
|
423
|
+
* @param token - A valid LiveKit access token for authentication
|
|
424
|
+
* @param opts - Optional room configuration options
|
|
425
|
+
* @throws ConnectError - if connection fails
|
|
428
426
|
*/
|
|
429
427
|
async connect(url, token, opts) {
|
|
430
428
|
const options = { ...defaultRoomOptions, ...opts };
|
|
@@ -454,7 +452,7 @@ class Room extends EventEmitter {
|
|
|
454
452
|
this.connectionState = ConnectionState.CONN_CONNECTED;
|
|
455
453
|
this.localParticipant = new LocalParticipant(
|
|
456
454
|
cb.message.value.localParticipant,
|
|
457
|
-
this.
|
|
455
|
+
this.ffiEventLock
|
|
458
456
|
);
|
|
459
457
|
for (const pt of cb.message.value.participants) {
|
|
460
458
|
const rp = this.createRemoteParticipant(pt.participant);
|
|
@@ -487,7 +485,7 @@ class Room extends EventEmitter {
|
|
|
487
485
|
}
|
|
488
486
|
});
|
|
489
487
|
await FfiClient.instance.waitFor((ev) => {
|
|
490
|
-
return ev.message.case == "
|
|
488
|
+
return ev.message.case == "disconnect" && ev.message.value.asyncId == res.asyncId;
|
|
491
489
|
});
|
|
492
490
|
FfiClient.instance.removeListener(FfiClientEvent.FfiEvent, this.onFfiEvent);
|
|
493
491
|
this.removeAllListeners();
|
|
@@ -495,9 +493,9 @@ class Room extends EventEmitter {
|
|
|
495
493
|
/**
|
|
496
494
|
* Registers a handler for incoming text data streams on a specific topic.
|
|
497
495
|
* Text streams are used for receiving structured text data from other participants.
|
|
498
|
-
* @param topic The topic to listen for text streams on
|
|
499
|
-
* @param callback Function to handle incoming text stream data
|
|
500
|
-
* @throws Error if a handler for this topic is already registered
|
|
496
|
+
* @param topic - The topic to listen for text streams on
|
|
497
|
+
* @param callback - Function to handle incoming text stream data
|
|
498
|
+
* @throws Error - if a handler for this topic is already registered
|
|
501
499
|
*/
|
|
502
500
|
registerTextStreamHandler(topic, callback) {
|
|
503
501
|
if (this.textStreamHandlers.has(topic)) {
|
|
@@ -511,9 +509,9 @@ class Room extends EventEmitter {
|
|
|
511
509
|
/**
|
|
512
510
|
* Registers a handler for incoming byte data streams on a specific topic.
|
|
513
511
|
* Byte streams are used for receiving binary data like files from other participants.
|
|
514
|
-
* @param topic The topic to listen for byte streams on
|
|
515
|
-
* @param callback Function to handle incoming byte stream data
|
|
516
|
-
* @throws Error if a handler for this topic is already registered
|
|
512
|
+
* @param topic - The topic to listen for byte streams on
|
|
513
|
+
* @param callback - Function to handle incoming byte stream data
|
|
514
|
+
* @throws Error - if a handler for this topic is already registered
|
|
517
515
|
*/
|
|
518
516
|
registerByteStreamHandler(topic, callback) {
|
|
519
517
|
if (this.byteStreamHandlers.has(topic)) {
|