@livekit/rtc-node 0.13.22 → 0.13.24

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 (124) hide show
  1. package/dist/audio_frame.cjs +6 -1
  2. package/dist/audio_frame.cjs.map +1 -1
  3. package/dist/audio_frame.d.cts +4 -1
  4. package/dist/audio_frame.d.ts +4 -1
  5. package/dist/audio_frame.d.ts.map +1 -1
  6. package/dist/audio_frame.js +6 -1
  7. package/dist/audio_frame.js.map +1 -1
  8. package/dist/audio_mixer.cjs +11 -4
  9. package/dist/audio_mixer.cjs.map +1 -1
  10. package/dist/audio_mixer.d.ts.map +1 -1
  11. package/dist/audio_mixer.js +11 -4
  12. package/dist/audio_mixer.js.map +1 -1
  13. package/dist/audio_stream.cjs +20 -5
  14. package/dist/audio_stream.cjs.map +1 -1
  15. package/dist/audio_stream.d.cts +4 -3
  16. package/dist/audio_stream.d.ts +4 -3
  17. package/dist/audio_stream.d.ts.map +1 -1
  18. package/dist/audio_stream.js +20 -5
  19. package/dist/audio_stream.js.map +1 -1
  20. package/dist/data_streams/stream_reader.cjs.map +1 -1
  21. package/dist/data_streams/stream_reader.js.map +1 -1
  22. package/dist/frame_processor.cjs +38 -0
  23. package/dist/frame_processor.cjs.map +1 -0
  24. package/dist/frame_processor.d.cts +29 -0
  25. package/dist/frame_processor.d.ts +29 -0
  26. package/dist/frame_processor.d.ts.map +1 -0
  27. package/dist/frame_processor.js +14 -0
  28. package/dist/frame_processor.js.map +1 -0
  29. package/dist/index.cjs +3 -0
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +1 -0
  32. package/dist/index.d.ts +1 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +4 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/log.cjs +1 -10
  37. package/dist/log.cjs.map +1 -1
  38. package/dist/log.d.cts +4 -0
  39. package/dist/log.d.ts +4 -0
  40. package/dist/log.d.ts.map +1 -1
  41. package/dist/log.js +1 -10
  42. package/dist/log.js.map +1 -1
  43. package/dist/proto/audio_frame_pb.cjs.map +1 -1
  44. package/dist/proto/audio_frame_pb.js.map +1 -1
  45. package/dist/proto/e2ee_pb.cjs.map +1 -1
  46. package/dist/proto/e2ee_pb.js.map +1 -1
  47. package/dist/proto/ffi_pb.cjs +4 -2
  48. package/dist/proto/ffi_pb.cjs.map +1 -1
  49. package/dist/proto/ffi_pb.d.cts +13 -1
  50. package/dist/proto/ffi_pb.d.ts +13 -1
  51. package/dist/proto/ffi_pb.d.ts.map +1 -1
  52. package/dist/proto/ffi_pb.js +5 -3
  53. package/dist/proto/ffi_pb.js.map +1 -1
  54. package/dist/proto/handle_pb.cjs.map +1 -1
  55. package/dist/proto/handle_pb.js.map +1 -1
  56. package/dist/proto/participant_pb.cjs +26 -4
  57. package/dist/proto/participant_pb.cjs.map +1 -1
  58. package/dist/proto/participant_pb.d.cts +31 -2
  59. package/dist/proto/participant_pb.d.ts +31 -2
  60. package/dist/proto/participant_pb.d.ts.map +1 -1
  61. package/dist/proto/participant_pb.js +24 -3
  62. package/dist/proto/participant_pb.js.map +1 -1
  63. package/dist/proto/room_pb.cjs +29 -2
  64. package/dist/proto/room_pb.cjs.map +1 -1
  65. package/dist/proto/room_pb.d.cts +30 -7
  66. package/dist/proto/room_pb.d.ts +30 -7
  67. package/dist/proto/room_pb.d.ts.map +1 -1
  68. package/dist/proto/room_pb.js +28 -2
  69. package/dist/proto/room_pb.js.map +1 -1
  70. package/dist/proto/rpc_pb.cjs.map +1 -1
  71. package/dist/proto/rpc_pb.js.map +1 -1
  72. package/dist/proto/stats_pb.cjs.map +1 -1
  73. package/dist/proto/stats_pb.js.map +1 -1
  74. package/dist/proto/track_pb.cjs.map +1 -1
  75. package/dist/proto/track_pb.js.map +1 -1
  76. package/dist/proto/track_publication_pb.cjs +66 -2
  77. package/dist/proto/track_publication_pb.cjs.map +1 -1
  78. package/dist/proto/track_publication_pb.d.cts +56 -1
  79. package/dist/proto/track_publication_pb.d.ts +56 -1
  80. package/dist/proto/track_publication_pb.d.ts.map +1 -1
  81. package/dist/proto/track_publication_pb.js +62 -1
  82. package/dist/proto/track_publication_pb.js.map +1 -1
  83. package/dist/proto/video_frame_pb.cjs +3 -1
  84. package/dist/proto/video_frame_pb.cjs.map +1 -1
  85. package/dist/proto/video_frame_pb.d.cts +5 -1
  86. package/dist/proto/video_frame_pb.d.ts +5 -1
  87. package/dist/proto/video_frame_pb.d.ts.map +1 -1
  88. package/dist/proto/video_frame_pb.js +3 -1
  89. package/dist/proto/video_frame_pb.js.map +1 -1
  90. package/dist/room.cjs +44 -26
  91. package/dist/room.cjs.map +1 -1
  92. package/dist/room.d.cts +19 -11
  93. package/dist/room.d.ts +19 -11
  94. package/dist/room.d.ts.map +1 -1
  95. package/dist/room.js +45 -27
  96. package/dist/room.js.map +1 -1
  97. package/dist/version.cjs +1 -1
  98. package/dist/version.cjs.map +1 -1
  99. package/dist/version.d.cts +1 -1
  100. package/dist/version.d.ts +1 -1
  101. package/dist/version.js +1 -1
  102. package/dist/version.js.map +1 -1
  103. package/package.json +11 -7
  104. package/src/audio_frame.ts +15 -1
  105. package/src/audio_mixer.ts +15 -4
  106. package/src/audio_stream.ts +23 -7
  107. package/src/data_streams/stream_reader.ts +4 -4
  108. package/src/frame_processor.ts +29 -0
  109. package/src/index.ts +5 -0
  110. package/src/log.ts +14 -10
  111. package/src/proto/audio_frame_pb.ts +1 -1
  112. package/src/proto/e2ee_pb.ts +1 -1
  113. package/src/proto/ffi_pb.ts +16 -2
  114. package/src/proto/handle_pb.ts +1 -1
  115. package/src/proto/participant_pb.ts +45 -1
  116. package/src/proto/room_pb.ts +52 -8
  117. package/src/proto/rpc_pb.ts +1 -1
  118. package/src/proto/stats_pb.ts +1 -1
  119. package/src/proto/track_pb.ts +1 -1
  120. package/src/proto/track_publication_pb.ts +105 -1
  121. package/src/proto/video_frame_pb.ts +7 -1
  122. package/src/room.ts +65 -38
  123. package/src/tests/e2e.test.ts +514 -0
  124. package/src/version.ts +1 -1
package/src/room.ts CHANGED
@@ -18,7 +18,7 @@ import { FfiClient, FfiClientEvent, FfiHandle } from './ffi_client.js';
18
18
  import { log } from './log.js';
19
19
  import type { Participant } from './participant.js';
20
20
  import { LocalParticipant, RemoteParticipant } from './participant.js';
21
- import { EncryptionState, EncryptionType } from './proto/e2ee_pb.js';
21
+ import { EncryptionState, type EncryptionType } from './proto/e2ee_pb.js';
22
22
  import type { FfiEvent } from './proto/ffi_pb.js';
23
23
  import type { DisconnectReason, OwnedParticipant } from './proto/participant_pb.js';
24
24
  import type { DataStream_Trailer, DisconnectCallback } from './proto/room_pb.js';
@@ -96,6 +96,9 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
96
96
 
97
97
  private preConnectEvents: FfiEvent[] = [];
98
98
 
99
+ private _token?: string;
100
+ private _serverUrl?: string;
101
+
99
102
  e2eeManager?: E2EEManager;
100
103
  connectionState: ConnectionState = ConnectionState.CONN_DISCONNECTED;
101
104
 
@@ -118,6 +121,16 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
118
121
  return this.ffiHandle != undefined && this.connectionState != ConnectionState.CONN_DISCONNECTED;
119
122
  }
120
123
 
124
+ /** @internal */
125
+ get token(): string | undefined {
126
+ return this._token;
127
+ }
128
+
129
+ /** @internal */
130
+ get serverUrl(): string | undefined {
131
+ return this._serverUrl;
132
+ }
133
+
121
134
  /**
122
135
  * Gets the room's server ID. This ID is assigned by the LiveKit server
123
136
  * and is unique for each room session.
@@ -155,7 +168,14 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
155
168
  }
156
169
 
157
170
  get creationTime(): Date {
158
- return new Date(Number(this.info?.creationTime ?? 0));
171
+ // TODO: workaround for Rust SDK bug, remove after updating to:
172
+ // https://github.com/livekit/rust-sdks/pull/822
173
+ // check if creationTime looks like seconds (less than year 3000 in ms), convert to ms if needed
174
+ let creationTimeMs = Number(this.info?.creationTime ?? 0);
175
+ if (creationTimeMs > 0 && creationTimeMs < 1e12) {
176
+ creationTimeMs *= 1000;
177
+ }
178
+ return new Date(creationTimeMs);
159
179
  }
160
180
 
161
181
  get isRecording(): boolean {
@@ -179,10 +199,10 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
179
199
 
180
200
  /**
181
201
  * Connects to a LiveKit room using the provided URL and access token.
182
- * @param url The WebSocket URL of the LiveKit server
183
- * @param token A valid LiveKit access token for authentication
184
- * @param opts Optional room configuration options
185
- * @throws ConnectError if connection fails
202
+ * @param url - The WebSocket URL of the LiveKit server
203
+ * @param token - A valid LiveKit access token for authentication
204
+ * @param opts - Optional room configuration options
205
+ * @throws ConnectError - if connection fails
186
206
  */
187
207
  async connect(url: string, token: string, opts?: RoomOptions) {
188
208
  const options = { ...defaultRoomOptions, ...opts };
@@ -217,6 +237,8 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
217
237
  this.ffiHandle = new FfiHandle(cb.message.value.room!.handle!.id!);
218
238
  this.e2eeManager = e2eeEnabled && new E2EEManager(this.ffiHandle.handle, e2eeOptions);
219
239
 
240
+ this._token = token;
241
+ this._serverUrl = url;
220
242
  this.info = cb.message.value.room!.info;
221
243
  this.connectionState = ConnectionState.CONN_CONNECTED;
222
244
  this.localParticipant = new LocalParticipant(
@@ -268,9 +290,9 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
268
290
  /**
269
291
  * Registers a handler for incoming text data streams on a specific topic.
270
292
  * Text streams are used for receiving structured text data from other participants.
271
- * @param topic The topic to listen for text streams on
272
- * @param callback Function to handle incoming text stream data
273
- * @throws Error if a handler for this topic is already registered
293
+ * @param topic - The topic to listen for text streams on
294
+ * @param callback - Function to handle incoming text stream data
295
+ * @throws Error - if a handler for this topic is already registered
274
296
  */
275
297
  registerTextStreamHandler(topic: string, callback: TextStreamHandler) {
276
298
  if (this.textStreamHandlers.has(topic)) {
@@ -286,9 +308,9 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
286
308
  /**
287
309
  * Registers a handler for incoming byte data streams on a specific topic.
288
310
  * Byte streams are used for receiving binary data like files from other participants.
289
- * @param topic The topic to listen for byte streams on
290
- * @param callback Function to handle incoming byte stream data
291
- * @throws Error if a handler for this topic is already registered
311
+ * @param topic - The topic to listen for byte streams on
312
+ * @param callback - Function to handle incoming byte stream data
313
+ * @throws Error - if a handler for this topic is already registered
292
314
  */
293
315
  registerByteStreamHandler(topic: string, callback: ByteStreamHandler) {
294
316
  if (this.byteStreamHandlers.has(topic)) {
@@ -362,7 +384,7 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
362
384
  participant.info.disconnectReason = ev.value.disconnectReason;
363
385
  this.emit(RoomEvent.ParticipantDisconnected, participant);
364
386
  } else {
365
- console.log(`RoomEvent.ParticipantDisconnected: Could not find participant`);
387
+ log.warn(`RoomEvent.ParticipantDisconnected: Could not find participant`);
366
388
  }
367
389
  } else if (ev.case == 'localTrackPublished') {
368
390
  const publication = this.localParticipant.trackPublications.get(ev.value.trackSid!);
@@ -377,7 +399,7 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
377
399
  publication.resolveFirstSubscription();
378
400
  this.emit(RoomEvent.LocalTrackSubscribed, publication!.track!);
379
401
  } else {
380
- console.warn(`RoomEvent.LocalTrackSubscribed: Publication not found: ${ev.value.trackSid}`);
402
+ log.warn(`RoomEvent.LocalTrackSubscribed: Publication not found: ${ev.value.trackSid}`);
381
403
  }
382
404
  } else if (ev.case == 'trackPublished') {
383
405
  const participant = this.remoteParticipants.get(ev.value.participantIdentity!);
@@ -385,7 +407,7 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
385
407
  if (participant) {
386
408
  participant.trackPublications.set(publication.sid!, publication);
387
409
  } else {
388
- console.warn(
410
+ log.warn(
389
411
  `RoomEvent.TrackPublished: Could not find participant: ${ev.value.participantIdentity}`,
390
412
  );
391
413
  }
@@ -397,7 +419,7 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
397
419
  if (publication) {
398
420
  this.emit(RoomEvent.TrackUnpublished, publication, participant);
399
421
  } else {
400
- console.warn(`RoomEvent.TrackUnpublished: Could not find publication`);
422
+ log.warn(`RoomEvent.TrackUnpublished: Could not find publication`);
401
423
  }
402
424
  } else if (ev.case == 'trackSubscribed') {
403
425
  const ownedTrack = ev.value.track!;
@@ -415,8 +437,8 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
415
437
  }
416
438
 
417
439
  this.emit(RoomEvent.TrackSubscribed, publication.track!, publication, participant);
418
- } catch (e: any) {
419
- console.warn(`RoomEvent.TrackSubscribed: ${e.message}`);
440
+ } catch (e: unknown) {
441
+ log.warn(`RoomEvent.TrackSubscribed: ${(e as Error).message}`);
420
442
  }
421
443
  } else if (ev.case == 'trackUnsubscribed') {
422
444
  try {
@@ -428,8 +450,8 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
428
450
  publication.track = undefined;
429
451
  publication.subscribed = false;
430
452
  this.emit(RoomEvent.TrackUnsubscribed, track, publication, participant);
431
- } catch (e: any) {
432
- console.warn(`RoomEvent.TrackUnsubscribed: ${e.message}`);
453
+ } catch (e: unknown) {
454
+ log.warn(`RoomEvent.TrackUnsubscribed: ${(e as Error).message}`);
433
455
  }
434
456
  } else if (ev.case == 'trackSubscriptionFailed') {
435
457
  try {
@@ -440,8 +462,8 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
440
462
  participant,
441
463
  ev.value.error,
442
464
  );
443
- } catch (e: any) {
444
- console.warn(`RoomEvent.TrackSubscriptionFailed: ${e.message}`);
465
+ } catch (e: unknown) {
466
+ log.warn(`RoomEvent.TrackSubscriptionFailed: ${(e as Error).message}`);
445
467
  }
446
468
  } else if (ev.case == 'trackMuted') {
447
469
  try {
@@ -454,8 +476,8 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
454
476
  publication.track.info!.muted = true;
455
477
  }
456
478
  this.emit(RoomEvent.TrackMuted, publication, participant);
457
- } catch (e: any) {
458
- console.warn(`RoomEvent.TrackMuted: ${e.message}`);
479
+ } catch (e: unknown) {
480
+ log.warn(`RoomEvent.TrackMuted: ${(e as Error).message}`);
459
481
  }
460
482
  } else if (ev.case == 'trackUnmuted') {
461
483
  try {
@@ -468,8 +490,8 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
468
490
  publication.track.info!.muted = false;
469
491
  }
470
492
  this.emit(RoomEvent.TrackUnmuted, publication, participant);
471
- } catch (e: any) {
472
- console.warn(`RoomEvent.TrackUnmuted: ${e.message}`);
493
+ } catch (e: unknown) {
494
+ log.warn(`RoomEvent.TrackUnmuted: ${(e as Error).message}`);
473
495
  }
474
496
  } else if (ev.case == 'activeSpeakersChanged') {
475
497
  try {
@@ -477,8 +499,8 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
477
499
  this.requireParticipantByIdentity(identity),
478
500
  );
479
501
  this.emit(RoomEvent.ActiveSpeakersChanged, activeSpeakers);
480
- } catch (e: any) {
481
- console.warn(`RoomEvent.ActiveSpeakersChanged: ${e.message}`);
502
+ } catch (e: unknown) {
503
+ log.warn(`RoomEvent.ActiveSpeakersChanged: ${(e as Error).message}`);
482
504
  }
483
505
  } else if (ev.case == 'roomMetadataChanged') {
484
506
  this.info.metadata = ev.value.metadata ?? '';
@@ -488,16 +510,16 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
488
510
  const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);
489
511
  participant.info.metadata = ev.value.metadata;
490
512
  this.emit(RoomEvent.ParticipantMetadataChanged, participant.metadata, participant);
491
- } catch (e: any) {
492
- console.warn(`RoomEvent.ParticipantMetadataChanged: ${e.message}`);
513
+ } catch (e: unknown) {
514
+ log.warn(`RoomEvent.ParticipantMetadataChanged: ${(e as Error).message}`);
493
515
  }
494
516
  } else if (ev.case == 'participantNameChanged') {
495
517
  try {
496
518
  const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);
497
519
  participant.info.name = ev.value.name;
498
520
  this.emit(RoomEvent.ParticipantNameChanged, participant.name!, participant);
499
- } catch (e: any) {
500
- console.warn(`RoomEvent.ParticipantNameChanged: ${e.message}`);
521
+ } catch (e: unknown) {
522
+ log.warn(`RoomEvent.ParticipantNameChanged: ${(e as Error).message}`);
501
523
  }
502
524
  } else if (ev.case == 'participantAttributesChanged') {
503
525
  try {
@@ -519,15 +541,15 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
519
541
  );
520
542
  this.emit(RoomEvent.ParticipantAttributesChanged, changedAttributes, participant);
521
543
  }
522
- } catch (e: any) {
523
- console.warn(`RoomEvent.ParticipantAttributesChanged: ${e.message}`);
544
+ } catch (e: unknown) {
545
+ log.warn(`RoomEvent.ParticipantAttributesChanged: ${(e as Error).message}`);
524
546
  }
525
547
  } else if (ev.case == 'connectionQualityChanged') {
526
548
  try {
527
549
  const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);
528
550
  this.emit(RoomEvent.ConnectionQualityChanged, ev.value.quality!, participant);
529
- } catch (e: any) {
530
- console.warn(`RoomEvent.ConnectionQualityChanged: ${e.message}`);
551
+ } catch (e: unknown) {
552
+ log.warn(`RoomEvent.ConnectionQualityChanged: ${(e as Error).message}`);
531
553
  }
532
554
  } else if (ev.case == 'chatMessage') {
533
555
  const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity!);
@@ -611,9 +633,12 @@ export class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>
611
633
  !!ev.value.isEncrypted,
612
634
  participant,
613
635
  );
614
- } catch (e: any) {
615
- console.warn(`RoomEvent.ParticipantEncryptionStatusChanged: ${e.message}`);
636
+ } catch (e: unknown) {
637
+ log.warn(`RoomEvent.ParticipantEncryptionStatusChanged: ${(e as Error).message}`);
616
638
  }
639
+ } else if (ev.case === 'tokenRefreshed') {
640
+ this._token = ev.value.token;
641
+ this.emit('tokenRefreshed');
617
642
  }
618
643
  };
619
644
 
@@ -835,6 +860,7 @@ export type RoomCallbacks = {
835
860
  roomSidChanged: (sid: string) => void;
836
861
  roomUpdated: () => void;
837
862
  moved: () => void;
863
+ tokenRefreshed: () => void;
838
864
  };
839
865
 
840
866
  export enum RoomEvent {
@@ -869,4 +895,5 @@ export enum RoomEvent {
869
895
  Reconnected = 'reconnected',
870
896
  RoomUpdated = 'roomUpdated',
871
897
  Moved = 'moved',
898
+ TokenRefreshed = 'tokenRefreshed',
872
899
  }