livekit-client 1.10.0 → 1.11.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.
Files changed (68) hide show
  1. package/dist/livekit-client.esm.mjs +504 -527
  2. package/dist/livekit-client.esm.mjs.map +1 -1
  3. package/dist/livekit-client.umd.js +1 -1
  4. package/dist/livekit-client.umd.js.map +1 -1
  5. package/dist/src/connectionHelper/ConnectionCheck.d.ts +2 -3
  6. package/dist/src/connectionHelper/ConnectionCheck.d.ts.map +1 -1
  7. package/dist/src/connectionHelper/checks/Checker.d.ts +2 -3
  8. package/dist/src/connectionHelper/checks/Checker.d.ts.map +1 -1
  9. package/dist/src/room/PCTransport.d.ts +1 -1
  10. package/dist/src/room/PCTransport.d.ts.map +1 -1
  11. package/dist/src/room/RTCEngine.d.ts +2 -4
  12. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  13. package/dist/src/room/Room.d.ts +3 -4
  14. package/dist/src/room/Room.d.ts.map +1 -1
  15. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  16. package/dist/src/room/participant/Participant.d.ts +2 -4
  17. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  18. package/dist/src/room/participant/RemoteParticipant.d.ts +2 -1
  19. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  20. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  21. package/dist/src/room/track/LocalTrack.d.ts +3 -2
  22. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  23. package/dist/src/room/track/LocalVideoTrack.d.ts +1 -1
  24. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  25. package/dist/src/room/track/RemoteVideoTrack.d.ts +1 -0
  26. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  27. package/dist/src/room/track/Track.d.ts +2 -4
  28. package/dist/src/room/track/Track.d.ts.map +1 -1
  29. package/dist/src/room/track/TrackPublication.d.ts +2 -4
  30. package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
  31. package/dist/src/room/track/options.d.ts +13 -4
  32. package/dist/src/room/track/options.d.ts.map +1 -1
  33. package/dist/src/room/track/types.d.ts +2 -1
  34. package/dist/src/room/track/types.d.ts.map +1 -1
  35. package/dist/src/room/utils.d.ts.map +1 -1
  36. package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +2 -3
  37. package/dist/ts4.2/src/connectionHelper/checks/Checker.d.ts +2 -3
  38. package/dist/ts4.2/src/room/PCTransport.d.ts +1 -1
  39. package/dist/ts4.2/src/room/RTCEngine.d.ts +2 -4
  40. package/dist/ts4.2/src/room/Room.d.ts +3 -4
  41. package/dist/ts4.2/src/room/participant/Participant.d.ts +2 -4
  42. package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +2 -1
  43. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -2
  44. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +1 -1
  45. package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +1 -0
  46. package/dist/ts4.2/src/room/track/Track.d.ts +2 -4
  47. package/dist/ts4.2/src/room/track/TrackPublication.d.ts +2 -4
  48. package/dist/ts4.2/src/room/track/options.d.ts +13 -4
  49. package/dist/ts4.2/src/room/track/types.d.ts +2 -1
  50. package/package.json +2 -3
  51. package/src/connectionHelper/ConnectionCheck.ts +2 -3
  52. package/src/connectionHelper/checks/Checker.ts +2 -3
  53. package/src/logger.ts +4 -4
  54. package/src/room/PCTransport.ts +1 -1
  55. package/src/room/RTCEngine.ts +4 -4
  56. package/src/room/Room.ts +41 -11
  57. package/src/room/participant/LocalParticipant.ts +11 -3
  58. package/src/room/participant/Participant.ts +2 -4
  59. package/src/room/participant/RemoteParticipant.ts +4 -3
  60. package/src/room/participant/publishUtils.ts +16 -18
  61. package/src/room/track/LocalTrack.ts +68 -46
  62. package/src/room/track/LocalVideoTrack.ts +9 -7
  63. package/src/room/track/RemoteVideoTrack.ts +23 -6
  64. package/src/room/track/Track.ts +2 -4
  65. package/src/room/track/TrackPublication.ts +2 -4
  66. package/src/room/track/options.ts +13 -4
  67. package/src/room/track/types.ts +2 -1
  68. package/src/room/utils.ts +6 -3
@@ -1,4 +1,4 @@
1
- import type TypedEmitter from 'typed-emitter';
1
+ import EventEmitter from 'eventemitter3';
2
2
  import { DataPacket_Kind, ParticipantInfo, ParticipantPermission, ConnectionQuality as ProtoQuality, SubscriptionError } from '../../proto/livekit_models';
3
3
  import type LocalTrackPublication from '../track/LocalTrackPublication';
4
4
  import type RemoteTrack from '../track/RemoteTrack';
@@ -11,8 +11,7 @@ export declare enum ConnectionQuality {
11
11
  Poor = "poor",
12
12
  Unknown = "unknown"
13
13
  }
14
- declare const Participant_base: new () => TypedEmitter<ParticipantEventCallbacks>;
15
- export default class Participant extends Participant_base {
14
+ export default class Participant extends EventEmitter<ParticipantEventCallbacks> {
16
15
  protected participantInfo?: ParticipantInfo;
17
16
  audioTracks: Map<string, TrackPublication>;
18
17
  videoTracks: Map<string, TrackPublication>;
@@ -90,5 +89,4 @@ export type ParticipantEventCallbacks = {
90
89
  participantPermissionsChanged: (prevPermissions?: ParticipantPermission) => void;
91
90
  trackSubscriptionStatusChanged: (publication: RemoteTrackPublication, status: TrackPublication.SubscriptionStatus) => void;
92
91
  };
93
- export {};
94
92
  //# sourceMappingURL=Participant.d.ts.map
@@ -1,3 +1,4 @@
1
+ import type EventEmitter from 'eventemitter3';
1
2
  import type { SignalClient } from '../../api/SignalClient';
2
3
  import type { ParticipantInfo } from '../../proto/livekit_models';
3
4
  import RemoteTrackPublication from '../track/RemoteTrackPublication';
@@ -48,6 +49,6 @@ export default class RemoteParticipant extends Participant {
48
49
  */
49
50
  setAudioOutput(output: AudioOutputOptions): Promise<void>;
50
51
  /** @internal */
51
- emit<E extends keyof ParticipantEventCallbacks>(event: E, ...args: Parameters<ParticipantEventCallbacks[E]>): boolean;
52
+ emit<T extends EventEmitter.EventNames<ParticipantEventCallbacks>>(event: T, ...args: EventEmitter.EventArgs<ParticipantEventCallbacks, T>): boolean;
52
53
  }
53
54
  //# sourceMappingURL=RemoteParticipant.d.ts.map
@@ -29,6 +29,7 @@ export default abstract class LocalTrack extends Track {
29
29
  get isUpstreamPaused(): boolean;
30
30
  get isUserProvided(): boolean;
31
31
  get mediaStreamTrack(): MediaStreamTrack;
32
+ private setMediaStreamTrack;
32
33
  waitForDimensions(timeout?: number): Promise<Track.Dimensions>;
33
34
  /**
34
35
  * @returns DeviceID of the device that is currently being used for this track
@@ -49,8 +50,8 @@ export default abstract class LocalTrack extends Track {
49
50
  * the server.
50
51
  * this API is unsupported on Safari < 12 due to a bug
51
52
  **/
52
- pauseUpstream(): Promise<void>;
53
- resumeUpstream(): Promise<void>;
53
+ pauseUpstream: () => Promise<void>;
54
+ resumeUpstream: () => Promise<void>;
54
55
  /**
55
56
  * Sets a processor on this track.
56
57
  * See https://github.com/livekit/track-processors-js for example usage
@@ -50,5 +50,5 @@ export default class LocalVideoTrack extends LocalTrack {
50
50
  protected handleAppVisibilityChanged(): Promise<void>;
51
51
  }
52
52
  export declare function videoQualityForRid(rid: string): VideoQuality;
53
- export declare function videoLayersFromEncodings(width: number, height: number, encodings?: RTCRtpEncodingParameters[]): VideoLayer[];
53
+ export declare function videoLayersFromEncodings(width: number, height: number, encodings?: RTCRtpEncodingParameters[], svc?: boolean): VideoLayer[];
54
54
  //# sourceMappingURL=LocalVideoTrack.d.ts.map
@@ -37,6 +37,7 @@ export default class RemoteVideoTrack extends RemoteTrack {
37
37
  private readonly debouncedHandleResize;
38
38
  private updateVisibility;
39
39
  private updateDimensions;
40
+ private getPixelDensity;
40
41
  }
41
42
  export interface ElementInfo {
42
43
  element: object;
@@ -1,9 +1,8 @@
1
- import type TypedEventEmitter from 'typed-emitter';
1
+ import EventEmitter from 'eventemitter3';
2
2
  import type { SignalClient } from '../../api/SignalClient';
3
3
  import { TrackSource, TrackType } from '../../proto/livekit_models';
4
4
  import { StreamState as ProtoStreamState } from '../../proto/livekit_rtc';
5
- declare const Track_base: new () => TypedEventEmitter<TrackEventCallbacks>;
6
- export declare abstract class Track extends Track_base {
5
+ export declare abstract class Track extends EventEmitter<TrackEventCallbacks> {
7
6
  kind: Track.Kind;
8
7
  attachedElements: HTMLMediaElement[];
9
8
  isMuted: boolean;
@@ -121,5 +120,4 @@ export type TrackEventCallbacks = {
121
120
  upstreamPaused: (track: any) => void;
122
121
  upstreamResumed: (track: any) => void;
123
122
  };
124
- export {};
125
123
  //# sourceMappingURL=Track.d.ts.map
@@ -1,4 +1,4 @@
1
- import type TypedEventEmitter from 'typed-emitter';
1
+ import EventEmitter from 'eventemitter3';
2
2
  import type { SubscriptionError, TrackInfo } from '../../proto/livekit_models';
3
3
  import type { UpdateSubscription, UpdateTrackSettings } from '../../proto/livekit_rtc';
4
4
  import LocalAudioTrack from './LocalAudioTrack';
@@ -7,8 +7,7 @@ import RemoteAudioTrack from './RemoteAudioTrack';
7
7
  import type RemoteTrack from './RemoteTrack';
8
8
  import RemoteVideoTrack from './RemoteVideoTrack';
9
9
  import { Track } from './Track';
10
- declare const TrackPublication_base: new () => TypedEventEmitter<PublicationEventCallbacks>;
11
- export declare class TrackPublication extends TrackPublication_base {
10
+ export declare class TrackPublication extends EventEmitter<PublicationEventCallbacks> {
12
11
  kind: Track.Kind;
13
12
  trackName: string;
14
13
  trackSid: Track.SID;
@@ -65,5 +64,4 @@ export type PublicationEventCallbacks = {
65
64
  subscriptionStatusChanged: (status: TrackPublication.SubscriptionStatus, prevStatus: TrackPublication.SubscriptionStatus) => void;
66
65
  subscriptionFailed: (error: SubscriptionError) => void;
67
66
  };
68
- export {};
69
67
  //# sourceMappingURL=TrackPublication.d.ts.map
@@ -54,10 +54,19 @@ export interface TrackPublishDefaults {
54
54
  */
55
55
  scalabilityMode?: ScalabilityMode;
56
56
  /**
57
- * custom video simulcast layers for camera tracks, defaults to h180, h360
58
- * You can specify up to two custom layers that will be used instead of
59
- * the LiveKit default layers.
60
- * Note: the layers need to be ordered from lowest to highest quality
57
+ * Up to two additional simulcast layers to publish in addition to the original
58
+ * Track.
59
+ * When left blank, it defaults to h180, h360.
60
+ * If a SVC codec is used (VP9 or AV1), this field has no effect.
61
+ *
62
+ * To publish three total layers, you would specify:
63
+ * {
64
+ * videoEncoding: {...}, // encoding of the primary layer
65
+ * videoSimulcastLayers: [
66
+ * VideoPresets.h540,
67
+ * VideoPresets.h216,
68
+ * ],
69
+ * }
61
70
  */
62
71
  videoSimulcastLayers?: Array<VideoPreset>;
63
72
  /**
@@ -6,7 +6,8 @@ export type AudioTrack = RemoteAudioTrack | LocalAudioTrack;
6
6
  export type VideoTrack = RemoteVideoTrack | LocalVideoTrack;
7
7
  export type AdaptiveStreamSettings = {
8
8
  /**
9
- * Set a custom pixel density, defaults to 1
9
+ * Set a custom pixel density. Defaults to 2 for high density screens (3+) or
10
+ * 1 otherwise.
10
11
  * When streaming videos on a ultra high definition screen this setting
11
12
  * let's you account for the devicePixelRatio of those screens.
12
13
  * Set it to `screen` to use the actual pixel density of the screen
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livekit-client",
3
- "version": "1.10.0",
3
+ "version": "1.11.1",
4
4
  "description": "JavaScript/TypeScript client SDK for LiveKit",
5
5
  "main": "./dist/livekit-client.umd.js",
6
6
  "unpkg": "./dist/livekit-client.umd.js",
@@ -42,12 +42,11 @@
42
42
  "size-limit": "size-limit"
43
43
  },
44
44
  "dependencies": {
45
- "events": "^3.3.0",
45
+ "eventemitter3": "^5.0.1",
46
46
  "loglevel": "^1.8.0",
47
47
  "protobufjs": "^7.0.0",
48
48
  "sdp-transform": "^2.14.1",
49
49
  "ts-debounce": "^4.0.0",
50
- "typed-emitter": "^2.1.0",
51
50
  "webrtc-adapter": "^8.1.1"
52
51
  },
53
52
  "devDependencies": {
@@ -1,5 +1,4 @@
1
- import { EventEmitter } from 'events';
2
- import type TypedEmitter from 'typed-emitter';
1
+ import EventEmitter from 'eventemitter3';
3
2
  import { CheckStatus, Checker } from './checks/Checker';
4
3
  import type { CheckInfo, InstantiableCheck } from './checks/Checker';
5
4
  import { PublishAudioCheck } from './checks/publishAudio';
@@ -11,7 +10,7 @@ import { WebSocketCheck } from './checks/websocket';
11
10
 
12
11
  export type { CheckInfo, CheckStatus };
13
12
 
14
- export class ConnectionCheck extends (EventEmitter as new () => TypedEmitter<ConnectionCheckCallbacks>) {
13
+ export class ConnectionCheck extends EventEmitter<ConnectionCheckCallbacks> {
15
14
  token: string;
16
15
 
17
16
  url: string;
@@ -1,5 +1,4 @@
1
- import { EventEmitter } from 'events';
2
- import type TypedEmitter from 'typed-emitter';
1
+ import EventEmitter from 'eventemitter3';
3
2
  import type { RoomConnectOptions, RoomOptions } from '../../options';
4
3
  import type RTCEngine from '../../room/RTCEngine';
5
4
  import Room, { ConnectionState } from '../../room/Room';
@@ -30,7 +29,7 @@ export interface CheckerOptions {
30
29
  connectOptions?: RoomConnectOptions;
31
30
  }
32
31
 
33
- export abstract class Checker extends (EventEmitter as new () => TypedEmitter<CheckerCallbacks>) {
32
+ export abstract class Checker extends EventEmitter<CheckerCallbacks> {
34
33
  protected url: string;
35
34
 
36
35
  protected token: string;
package/src/logger.ts CHANGED
@@ -21,7 +21,7 @@ type StructuredLogger = {
21
21
 
22
22
  const livekitLogger = log.getLogger('livekit');
23
23
 
24
- livekitLogger.setLevel(LogLevel.info);
24
+ livekitLogger.setDefaultLevel(LogLevel.info);
25
25
 
26
26
  export default livekitLogger as StructuredLogger;
27
27
 
@@ -38,10 +38,10 @@ export type LogExtension = (level: LogLevel, msg: string, context?: object) => v
38
38
  export function setLogExtension(extension: LogExtension) {
39
39
  const originalFactory = livekitLogger.methodFactory;
40
40
 
41
- livekitLogger.methodFactory = (methodName, logLevel, loggerName) => {
42
- const rawMethod = originalFactory(methodName, logLevel, loggerName);
41
+ livekitLogger.methodFactory = (methodName, configLevel, loggerName) => {
42
+ const rawMethod = originalFactory(methodName, configLevel, loggerName);
43
43
 
44
- const configLevel = livekitLogger.getLevel();
44
+ const logLevel = LogLevel[methodName as LogLevelString];
45
45
  const needLog = logLevel >= configLevel && logLevel < LogLevel.silent;
46
46
 
47
47
  return (msg, context?: [msg: string, context: object]) => {
@@ -1,4 +1,4 @@
1
- import { EventEmitter } from 'events';
1
+ import EventEmitter from 'eventemitter3';
2
2
  import { parse, write } from 'sdp-transform';
3
3
  import type { MediaDescription } from 'sdp-transform';
4
4
  import { debounce } from 'ts-debounce';
@@ -1,5 +1,4 @@
1
- import { EventEmitter } from 'events';
2
- import type TypedEventEmitter from 'typed-emitter';
1
+ import EventEmitter from 'eventemitter3';
3
2
  import { SignalClient } from '../api/SignalClient';
4
3
  import type { SignalOptions } from '../api/SignalClient';
5
4
  import log from '../logger';
@@ -65,7 +64,7 @@ enum PCState {
65
64
  }
66
65
 
67
66
  /** @internal */
68
- export default class RTCEngine extends (EventEmitter as new () => TypedEventEmitter<EngineEventCallbacks>) {
67
+ export default class RTCEngine extends EventEmitter<EngineEventCallbacks> {
69
68
  publisher?: PCTransport;
70
69
 
71
70
  subscriber?: PCTransport;
@@ -1046,6 +1045,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1046
1045
  };
1047
1046
  this.once(EngineEvent.Restarted, onRestarted);
1048
1047
  this.once(EngineEvent.Disconnected, onDisconnected);
1048
+ this.once(EngineEvent.Closing, onDisconnected);
1049
1049
  });
1050
1050
  };
1051
1051
 
@@ -1172,7 +1172,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1172
1172
  this.hasPublished = true;
1173
1173
 
1174
1174
  const handleClosed = () => {
1175
- log.debug('engine disconnected while negotiation was ongoing');
1175
+ log.warn('engine disconnected while negotiation was ongoing');
1176
1176
  cleanup();
1177
1177
  resolve();
1178
1178
  return;
package/src/room/Room.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { EventEmitter } from 'events';
2
- import type TypedEmitter from 'typed-emitter';
1
+ import EventEmitter from 'eventemitter3';
3
2
  import 'webrtc-adapter';
4
3
  import { toProtoSessionDescription } from '../api/SignalClient';
5
4
  import log from '../logger';
@@ -65,6 +64,7 @@ import {
65
64
  createDummyVideoStreamTrack,
66
65
  getEmptyAudioStreamTrack,
67
66
  isCloud,
67
+ isSafari,
68
68
  isWeb,
69
69
  supportsSetSinkId,
70
70
  unpackStreamId,
@@ -90,7 +90,7 @@ export const RoomState = ConnectionState;
90
90
  *
91
91
  * @noInheritDoc
92
92
  */
93
- class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>) {
93
+ class Room extends EventEmitter<RoomEventCallbacks> {
94
94
  state: ConnectionState = ConnectionState.Disconnected;
95
95
 
96
96
  /** map of sid: [[RemoteParticipant]] */
@@ -140,7 +140,6 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
140
140
  */
141
141
  constructor(options?: RoomOptions) {
142
142
  super();
143
- this.setMaxListeners(100);
144
143
  this.participants = new Map();
145
144
  this.cachedParticipantSids = [];
146
145
  this.identityToSid = new Map();
@@ -495,6 +494,9 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
495
494
  // capturing both 'pagehide' and 'beforeunload' to capture broadest set of browser behaviors
496
495
  window.addEventListener('pagehide', this.onPageLeave);
497
496
  window.addEventListener('beforeunload', this.onPageLeave);
497
+ }
498
+ if (isWeb()) {
499
+ document.addEventListener('freeze', this.onPageLeave);
498
500
  navigator.mediaDevices?.addEventListener('devicechange', this.handleDeviceChange);
499
501
  }
500
502
  this.setAndEmitConnectionState(ConnectionState.Connected);
@@ -657,8 +659,31 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
657
659
  */
658
660
  async startAudio() {
659
661
  await this.acquireAudioContext();
660
-
661
662
  const elements: Array<HTMLMediaElement> = [];
663
+
664
+ if (isSafari()) {
665
+ /**
666
+ * iOS Safari blocks audio element playback if
667
+ * - user is not publishing audio themselves and
668
+ * - no other audio source is playing
669
+ *
670
+ * as a workaround, we create an audio element with an empty track, so that
671
+ * silent audio is always playing
672
+ */
673
+ const audioId = 'livekit-dummy-audio-el';
674
+ let dummyAudioEl = document.getElementById(audioId) as HTMLAudioElement | null;
675
+ if (!dummyAudioEl) {
676
+ dummyAudioEl = document.createElement('audio');
677
+ dummyAudioEl.autoplay = true;
678
+ dummyAudioEl.hidden = true;
679
+ const track = getEmptyAudioStreamTrack();
680
+ track.enabled = true;
681
+ dummyAudioEl.srcObject = new MediaStream([track]);
682
+ document.body.append(dummyAudioEl);
683
+ }
684
+ elements.push(dummyAudioEl);
685
+ }
686
+
662
687
  this.participants.forEach((p) => {
663
688
  p.audioTracks.forEach((t) => {
664
689
  if (t.track) {
@@ -965,6 +990,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
965
990
  if (isWeb()) {
966
991
  window.removeEventListener('beforeunload', this.onPageLeave);
967
992
  window.removeEventListener('pagehide', this.onPageLeave);
993
+ window.removeEventListener('freeze', this.onPageLeave);
968
994
  navigator.mediaDevices?.removeEventListener('devicechange', this.handleDeviceChange);
969
995
  }
970
996
  } finally {
@@ -1420,9 +1446,9 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
1420
1446
  return true;
1421
1447
  }
1422
1448
 
1423
- private emitWhenConnected<E extends keyof RoomEventCallbacks>(
1424
- event: E,
1425
- ...args: Parameters<RoomEventCallbacks[E]>
1449
+ private emitWhenConnected<T extends EventEmitter.EventNames<RoomEventCallbacks>>(
1450
+ event: T,
1451
+ ...args: EventEmitter.EventArgs<RoomEventCallbacks, T>
1426
1452
  ): boolean {
1427
1453
  if (this.state === ConnectionState.Connected) {
1428
1454
  return this.emit(event, ...args);
@@ -1599,10 +1625,14 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
1599
1625
  }
1600
1626
 
1601
1627
  // /** @internal */
1602
- emit<E extends keyof RoomEventCallbacks>(
1603
- event: E,
1604
- ...args: Parameters<RoomEventCallbacks[E]>
1628
+ emit<T extends EventEmitter.EventNames<RoomEventCallbacks>>(
1629
+ event: T,
1630
+ ...args: EventEmitter.EventArgs<RoomEventCallbacks, T>
1605
1631
  ): boolean {
1632
+ // emit<E extends keyof RoomEventCallbacks>(
1633
+ // event: E,
1634
+ // ...args: Parameters<RoomEventCallbacks[E]>
1635
+ // ): boolean {
1606
1636
  // active speaker updates are too spammy
1607
1637
  if (event !== RoomEvent.ActiveSpeakersChanged) {
1608
1638
  log.debug(`room event ${event}`, { event, args });
@@ -143,8 +143,11 @@ export default class LocalParticipant extends Participant {
143
143
  };
144
144
 
145
145
  private handleDisconnected = () => {
146
- this.reconnectFuture?.reject?.('Got disconnected during publishing attempt');
147
- this.reconnectFuture = undefined;
146
+ if (this.reconnectFuture) {
147
+ this.reconnectFuture.promise.catch((e) => log.warn(e));
148
+ this.reconnectFuture?.reject?.('Got disconnected during reconnection attempt');
149
+ this.reconnectFuture = undefined;
150
+ }
148
151
  };
149
152
 
150
153
  /**
@@ -666,7 +669,12 @@ export default class LocalParticipant extends Participant {
666
669
  dims.height,
667
670
  opts,
668
671
  );
669
- req.layers = videoLayersFromEncodings(req.width, req.height, encodings);
672
+ req.layers = videoLayersFromEncodings(
673
+ req.width,
674
+ req.height,
675
+ encodings,
676
+ isSVCCodec(opts.videoCodec),
677
+ );
670
678
  } else if (track.kind === Track.Kind.Audio) {
671
679
  encodings = [
672
680
  {
@@ -1,5 +1,4 @@
1
- import { EventEmitter } from 'events';
2
- import type TypedEmitter from 'typed-emitter';
1
+ import EventEmitter from 'eventemitter3';
3
2
  import log from '../../logger';
4
3
  import {
5
4
  DataPacket_Kind,
@@ -35,7 +34,7 @@ function qualityFromProto(q: ProtoQuality): ConnectionQuality {
35
34
  }
36
35
  }
37
36
 
38
- export default class Participant extends (EventEmitter as new () => TypedEmitter<ParticipantEventCallbacks>) {
37
+ export default class Participant extends EventEmitter<ParticipantEventCallbacks> {
39
38
  protected participantInfo?: ParticipantInfo;
40
39
 
41
40
  audioTracks: Map<string, TrackPublication>;
@@ -72,7 +71,6 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
72
71
  /** @internal */
73
72
  constructor(sid: string, identity: string, name?: string, metadata?: string) {
74
73
  super();
75
- this.setMaxListeners(100);
76
74
  this.sid = sid;
77
75
  this.identity = identity;
78
76
  this.name = name;
@@ -1,3 +1,4 @@
1
+ import type EventEmitter from 'eventemitter3';
1
2
  import type { SignalClient } from '../../api/SignalClient';
2
3
  import log from '../../logger';
3
4
  import type { ParticipantInfo, SubscriptionError } from '../../proto/livekit_models';
@@ -345,9 +346,9 @@ export default class RemoteParticipant extends Participant {
345
346
  }
346
347
 
347
348
  /** @internal */
348
- emit<E extends keyof ParticipantEventCallbacks>(
349
- event: E,
350
- ...args: Parameters<ParticipantEventCallbacks[E]>
349
+ emit<T extends EventEmitter.EventNames<ParticipantEventCallbacks>>(
350
+ event: T,
351
+ ...args: EventEmitter.EventArgs<ParticipantEventCallbacks, T>
351
352
  ): boolean {
352
353
  log.trace('participant event', { participant: this.sid, event, args });
353
354
  return super.emit(event, ...args);
@@ -123,27 +123,25 @@ export function computeVideoEncodings(
123
123
  if (scalabilityMode && isSVCCodec(videoCodec)) {
124
124
  log.debug(`using svc with scalabilityMode ${scalabilityMode}`);
125
125
 
126
- const encodings: RTCRtpEncodingParameters[] = [];
126
+ const sm = new ScalabilityMode(scalabilityMode);
127
127
 
128
- // svc use first encoding as the original, so we sort encoding from high to low
129
- switch (scalabilityMode) {
130
- case 'L3T3':
131
- case 'L3T3_KEY':
132
- encodings.push({
133
- rid: videoRids[2],
134
- maxBitrate: videoEncoding.maxBitrate,
135
- /* @ts-ignore */
136
- maxFramerate: original.encoding.maxFramerate,
137
- /* @ts-ignore */
138
- scalabilityMode: scalabilityMode,
139
- });
140
- log.debug('encodings', encodings);
141
- return encodings;
128
+ const encodings: RTCRtpEncodingParameters[] = [];
142
129
 
143
- default:
144
- // TODO : support other scalability modes
145
- throw new Error(`unsupported scalabilityMode: ${scalabilityMode}`);
130
+ if (sm.spatial > 3) {
131
+ throw new Error(`unsupported scalabilityMode: ${scalabilityMode}`);
132
+ }
133
+ for (let i = 0; i < sm.spatial; i += 1) {
134
+ encodings.push({
135
+ rid: videoRids[2 - i],
136
+ maxBitrate: videoEncoding.maxBitrate / 3 ** i,
137
+ /* @ts-ignore */
138
+ maxFramerate: original.encoding.maxFramerate,
139
+ });
146
140
  }
141
+ /* @ts-ignore */
142
+ encodings[0].scalabilityMode = scalabilityMode;
143
+ log.debug('encodings', encodings);
144
+ return encodings;
147
145
  }
148
146
 
149
147
  if (!useSimulcast) {