@livekit/rtc-node 0.5.1 → 0.6.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.
Files changed (54) hide show
  1. package/README.md +5 -2
  2. package/dist/audio_frame.d.ts.map +1 -1
  3. package/dist/audio_frame.js +5 -0
  4. package/dist/audio_frame.js.map +1 -1
  5. package/dist/audio_source.d.ts +1 -1
  6. package/dist/audio_source.d.ts.map +1 -1
  7. package/dist/audio_source.js +2 -1
  8. package/dist/audio_source.js.map +1 -1
  9. package/dist/audio_stream.d.ts.map +1 -1
  10. package/dist/ffi_client.d.ts.map +1 -1
  11. package/dist/participant.d.ts +5 -2
  12. package/dist/participant.d.ts.map +1 -1
  13. package/dist/participant.js +39 -16
  14. package/dist/participant.js.map +1 -1
  15. package/dist/proto/audio_frame_pb.d.ts +4 -0
  16. package/dist/proto/audio_frame_pb.d.ts.map +1 -1
  17. package/dist/proto/audio_frame_pb.js +1 -0
  18. package/dist/proto/audio_frame_pb.js.map +1 -1
  19. package/dist/proto/ffi_pb.d.ts +105 -51
  20. package/dist/proto/ffi_pb.d.ts.map +1 -1
  21. package/dist/proto/ffi_pb.js +48 -39
  22. package/dist/proto/ffi_pb.js.map +1 -1
  23. package/dist/proto/participant_pb.d.ts +6 -0
  24. package/dist/proto/participant_pb.d.ts.map +1 -1
  25. package/dist/proto/participant_pb.js +5 -0
  26. package/dist/proto/participant_pb.js.map +1 -1
  27. package/dist/proto/room_pb.d.ts +471 -111
  28. package/dist/proto/room_pb.d.ts.map +1 -1
  29. package/dist/proto/room_pb.js +639 -128
  30. package/dist/proto/room_pb.js.map +1 -1
  31. package/dist/room.d.ts +5 -2
  32. package/dist/room.d.ts.map +1 -1
  33. package/dist/room.js +40 -24
  34. package/dist/room.js.map +1 -1
  35. package/dist/utils.d.ts +2 -0
  36. package/dist/utils.d.ts.map +1 -0
  37. package/dist/utils.js +20 -0
  38. package/dist/utils.js.map +1 -0
  39. package/dist/video_stream.d.ts.map +1 -1
  40. package/package.json +6 -6
  41. package/src/audio_frame.ts +5 -0
  42. package/src/audio_source.ts +2 -1
  43. package/src/participant.ts +64 -28
  44. package/src/proto/audio_frame_pb.ts +7 -1
  45. package/src/proto/e2ee_pb.ts +1 -1
  46. package/src/proto/ffi_pb.ts +153 -90
  47. package/src/proto/handle_pb.ts +1 -1
  48. package/src/proto/participant_pb.ts +7 -1
  49. package/src/proto/room_pb.ts +845 -169
  50. package/src/proto/stats_pb.ts +1 -1
  51. package/src/proto/track_pb.ts +1 -1
  52. package/src/proto/video_frame_pb.ts +1 -1
  53. package/src/room.ts +55 -26
  54. package/src/utils.ts +25 -0
@@ -12,7 +12,7 @@
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
 
15
- // @generated by protoc-gen-es v1.7.2 with parameter "target=ts"
15
+ // @generated by protoc-gen-es v1.10.0 with parameter "target=ts"
16
16
  // @generated from file stats.proto (package livekit.proto, syntax proto3)
17
17
  /* eslint-disable */
18
18
  // @ts-nocheck
@@ -12,7 +12,7 @@
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
 
15
- // @generated by protoc-gen-es v1.7.2 with parameter "target=ts"
15
+ // @generated by protoc-gen-es v1.10.0 with parameter "target=ts"
16
16
  // @generated from file track.proto (package livekit.proto, syntax proto3)
17
17
  /* eslint-disable */
18
18
  // @ts-nocheck
@@ -12,7 +12,7 @@
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
 
15
- // @generated by protoc-gen-es v1.7.2 with parameter "target=ts"
15
+ // @generated by protoc-gen-es v1.10.0 with parameter "target=ts"
16
16
  // @generated from file video_frame.proto (package livekit.proto, syntax proto3)
17
17
  /* eslint-disable */
18
18
  // @ts-nocheck
package/src/room.ts CHANGED
@@ -31,6 +31,7 @@ import type { RemoteTrack } from './track.js';
31
31
  import { RemoteAudioTrack, RemoteVideoTrack } from './track.js';
32
32
  import type { LocalTrackPublication, TrackPublication } from './track_publication.js';
33
33
  import { RemoteTrackPublication } from './track_publication.js';
34
+ import { diffAttributes } from './utils.js';
34
35
 
35
36
  export interface RtcConfiguration {
36
37
  iceTransportType: IceTransportType;
@@ -175,7 +176,7 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
175
176
  this.remoteParticipants.set(participant.identity, participant);
176
177
  this.emit(RoomEvent.ParticipantConnected, participant);
177
178
  } else if (ev.case == 'participantDisconnected') {
178
- const participant = this.getRemoteParticipantBySid(ev.value.participantSid);
179
+ const participant = this.remoteParticipants.get(ev.value.participantIdentity);
179
180
  this.remoteParticipants.delete(participant.identity);
180
181
  this.emit(RoomEvent.ParticipantDisconnected, participant);
181
182
  } else if (ev.case == 'localTrackPublished') {
@@ -186,18 +187,18 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
186
187
  this.localParticipant.trackPublications.delete(ev.value.publicationSid);
187
188
  this.emit(RoomEvent.LocalTrackUnpublished, publication, this.localParticipant);
188
189
  } else if (ev.case == 'trackPublished') {
189
- const participant = this.getRemoteParticipantBySid(ev.value.participantSid);
190
+ const participant = this.remoteParticipants.get(ev.value.participantIdentity);
190
191
  const publication = new RemoteTrackPublication(ev.value.publication);
191
192
  participant.trackPublications.set(publication.sid, publication);
192
193
  this.emit(RoomEvent.TrackPublished, publication, participant);
193
194
  } else if (ev.case == 'trackUnpublished') {
194
- const participant = this.getRemoteParticipantBySid(ev.value.participantSid);
195
+ const participant = this.remoteParticipants.get(ev.value.participantIdentity);
195
196
  const publication = participant.trackPublications.get(ev.value.publicationSid);
196
197
  participant.trackPublications.delete(ev.value.publicationSid);
197
198
  this.emit(RoomEvent.TrackUnpublished, publication, participant);
198
199
  } else if (ev.case == 'trackSubscribed') {
199
200
  const ownedTrack = ev.value.track;
200
- const participant = this.getRemoteParticipantBySid(ev.value.participantSid);
201
+ const participant = this.remoteParticipants.get(ev.value.participantIdentity);
201
202
  const publication = participant.trackPublications.get(ownedTrack.info.sid);
202
203
  publication.subscribed = true;
203
204
  if (ownedTrack.info.kind == TrackKind.KIND_VIDEO) {
@@ -208,16 +209,16 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
208
209
 
209
210
  this.emit(RoomEvent.TrackSubscribed, publication.track, publication, participant);
210
211
  } else if (ev.case == 'trackUnsubscribed') {
211
- const participant = this.getRemoteParticipantBySid(ev.value.participantSid);
212
+ const participant = this.remoteParticipants.get(ev.value.participantIdentity);
212
213
  const publication = participant.trackPublications.get(ev.value.trackSid);
213
214
  publication.track = undefined;
214
215
  publication.subscribed = false;
215
216
  this.emit(RoomEvent.TrackUnsubscribed, publication.track, publication, participant);
216
217
  } else if (ev.case == 'trackSubscriptionFailed') {
217
- const participant = this.getRemoteParticipantBySid(ev.value.participantSid);
218
+ const participant = this.remoteParticipants.get(ev.value.participantIdentity);
218
219
  this.emit(RoomEvent.TrackSubscriptionFailed, ev.value.trackSid, participant, ev.value.error);
219
220
  } else if (ev.case == 'trackMuted') {
220
- const participant = this.retrieveParticipant(ev.value.participantSid);
221
+ const participant = this.remoteParticipants.get(ev.value.participantIdentity);
221
222
  const publication = participant.trackPublications.get(ev.value.trackSid);
222
223
  publication.info.muted = true;
223
224
  if (publication.track) {
@@ -225,7 +226,7 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
225
226
  }
226
227
  this.emit(RoomEvent.TrackMuted, publication, participant);
227
228
  } else if (ev.case == 'trackUnmuted') {
228
- const participant = this.retrieveParticipant(ev.value.participantSid);
229
+ const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity);
229
230
  const publication = participant.trackPublications.get(ev.value.trackSid);
230
231
  publication.info.muted = false;
231
232
  if (publication.track) {
@@ -233,31 +234,56 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
233
234
  }
234
235
  this.emit(RoomEvent.TrackUnmuted, publication, participant);
235
236
  } else if (ev.case == 'activeSpeakersChanged') {
236
- const activeSpeakers = ev.value.participantSids.map((sid) =>
237
- this.getRemoteParticipantBySid(sid),
237
+ const activeSpeakers = ev.value.participantIdentities.map((identity) =>
238
+ this.retrieveParticipantByIdentity(identity),
238
239
  );
239
240
  this.emit(RoomEvent.ActiveSpeakersChanged, activeSpeakers);
240
241
  } else if (ev.case == 'roomMetadataChanged') {
241
242
  this.info.metadata = ev.value.metadata;
242
243
  this.emit(RoomEvent.RoomMetadataChanged, this.info.metadata);
243
244
  } else if (ev.case == 'participantMetadataChanged') {
244
- const participant = this.retrieveParticipant(ev.value.participantSid);
245
+ const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity);
245
246
  participant.info.metadata = ev.value.metadata;
246
247
  this.emit(RoomEvent.ParticipantMetadataChanged, participant.metadata, participant);
247
248
  } else if (ev.case == 'participantNameChanged') {
248
- const participant = this.retrieveParticipant(ev.value.participantSid);
249
+ const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity);
249
250
  participant.info.name = ev.value.name;
250
251
  this.emit(RoomEvent.ParticipantNameChanged, participant.name, participant);
252
+ } else if (ev.case == 'participantAttributesChanged') {
253
+ const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity);
254
+ const changedAttributes = diffAttributes(participant.info.attributes, ev.value.attributes);
255
+ participant.info.attributes = ev.value.attributes;
256
+ this.emit(RoomEvent.ParticipantAttributesChanged, changedAttributes, participant);
251
257
  } else if (ev.case == 'connectionQualityChanged') {
252
- const participant = this.retrieveParticipant(ev.value.participantSid);
258
+ const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity);
253
259
  this.emit(RoomEvent.ConnectionQualityChanged, ev.value.quality, participant);
254
- } else if (ev.case == 'dataReceived') {
260
+ } else if (ev.case == 'dataPacketReceived') {
255
261
  // Can be undefined if the data is sent from a Server SDK
256
- const participant = this.getRemoteParticipantBySid(ev.value.participantSid);
257
- const info = ev.value.data;
258
- const buffer = FfiClient.instance.copyBuffer(info.data.dataPtr, Number(info.data.dataLen));
259
- new FfiHandle(info.handle.id).dispose();
260
- this.emit(RoomEvent.DataReceived, buffer, participant, ev.value.kind, ev.value.topic);
262
+ const participant = this.remoteParticipants.get(ev.value.participantIdentity);
263
+ const dataPacket = ev.value.value;
264
+ switch (dataPacket.case) {
265
+ case 'user':
266
+ const buffer = FfiClient.instance.copyBuffer(
267
+ dataPacket.value.data.data.dataPtr,
268
+ Number(dataPacket.value.data.data.dataLen),
269
+ );
270
+ new FfiHandle(dataPacket.value.data.handle.id).dispose();
271
+ this.emit(
272
+ RoomEvent.DataReceived,
273
+ buffer,
274
+ participant,
275
+ ev.value.kind,
276
+ dataPacket.value.topic,
277
+ );
278
+ break;
279
+ case 'sipDtmf':
280
+ const { code, digit } = dataPacket.value;
281
+ this.emit(RoomEvent.DtmfReceived, code, digit, participant);
282
+ break;
283
+
284
+ default:
285
+ break;
286
+ }
261
287
  } else if (ev.case == 'e2eeStateChanged') {
262
288
  if (ev.value.state == EncryptionState.INTERNAL_ERROR) {
263
289
  // throw generic error until Rust SDK is updated to supply the error alongside INTERNAL_ERROR
@@ -277,15 +303,11 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
277
303
  }
278
304
  };
279
305
 
280
- getRemoteParticipantBySid(sid: string) {
281
- return Array.from(this.remoteParticipants.values()).find((p) => p.sid === sid);
282
- }
283
-
284
- private retrieveParticipant(sid: string): Participant {
285
- if (this.localParticipant.sid === sid) {
306
+ private retrieveParticipantByIdentity(identity: string): Participant {
307
+ if (this.localParticipant.identity === identity) {
286
308
  return this.localParticipant;
287
309
  } else {
288
- return this.getRemoteParticipantBySid(sid);
310
+ return this.remoteParticipants.get(identity);
289
311
  }
290
312
  }
291
313
 
@@ -337,6 +359,10 @@ export type RoomCallbacks = {
337
359
  roomMetadataChanged: (metadata: string) => void;
338
360
  participantMetadataChanged: (metadata: string | undefined, participant: Participant) => void;
339
361
  participantNameChanged: (name: string, participant: Participant) => void;
362
+ participantAttributesChanged: (
363
+ changedAttributes: Record<string, string>,
364
+ participant: Participant,
365
+ ) => void;
340
366
  connectionQualityChanged: (quality: ConnectionQuality, participant: Participant) => void;
341
367
  dataReceived: (
342
368
  payload: Uint8Array,
@@ -344,6 +370,7 @@ export type RoomCallbacks = {
344
370
  kind?: DataPacketKind,
345
371
  topic?: string,
346
372
  ) => void;
373
+ dtmfReceived: (code: number, digit: string, participant: RemoteParticipant) => void;
347
374
  encryptionError: (error: Error) => void;
348
375
  connectionStateChanged: (state: ConnectionState) => void;
349
376
  connected: () => void;
@@ -368,8 +395,10 @@ export enum RoomEvent {
368
395
  RoomMetadataChanged = 'roomMetadataChanged',
369
396
  ParticipantMetadataChanged = 'participantMetadataChanged',
370
397
  ParticipantNameChanged = 'participantNameChanged',
398
+ ParticipantAttributesChanged = 'participantAttributesChanged',
371
399
  ConnectionQualityChanged = 'connectionQualityChanged',
372
400
  DataReceived = 'dataReceived',
401
+ DtmfReceived = 'dtmfReceived',
373
402
  EncryptionError = 'encryptionError',
374
403
  ConnectionStateChanged = 'connectionStateChanged',
375
404
  Connected = 'connected',
package/src/utils.ts ADDED
@@ -0,0 +1,25 @@
1
+ // SPDX-FileCopyrightText: 2024 LiveKit, Inc.
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ export function diffAttributes(
6
+ oldValues: Record<string, string> | undefined,
7
+ newValues: Record<string, string> | undefined,
8
+ ) {
9
+ if (oldValues === undefined) {
10
+ oldValues = {};
11
+ }
12
+ if (newValues === undefined) {
13
+ newValues = {};
14
+ }
15
+ const allKeys = [...Object.keys(newValues), ...Object.keys(oldValues)];
16
+ const diff: Record<string, string> = {};
17
+
18
+ for (const key of allKeys) {
19
+ if (oldValues[key] !== newValues[key]) {
20
+ diff[key] = newValues[key] ?? '';
21
+ }
22
+ }
23
+
24
+ return diff;
25
+ }