livekit-client 1.8.0 → 1.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. package/README.md +9 -7
  2. package/dist/livekit-client.esm.mjs +13550 -13342
  3. package/dist/livekit-client.esm.mjs.map +1 -1
  4. package/dist/livekit-client.umd.js +1 -1
  5. package/dist/livekit-client.umd.js.map +1 -1
  6. package/dist/src/api/SignalClient.d.ts +11 -10
  7. package/dist/src/api/SignalClient.d.ts.map +1 -1
  8. package/dist/src/connectionHelper/ConnectionCheck.d.ts +1 -1
  9. package/dist/src/connectionHelper/ConnectionCheck.d.ts.map +1 -1
  10. package/dist/src/connectionHelper/checks/Checker.d.ts +1 -1
  11. package/dist/src/connectionHelper/checks/Checker.d.ts.map +1 -1
  12. package/dist/src/index.d.ts +5 -7
  13. package/dist/src/index.d.ts.map +1 -1
  14. package/dist/src/proto/livekit_models.d.ts +5 -0
  15. package/dist/src/proto/livekit_models.d.ts.map +1 -1
  16. package/dist/src/proto/livekit_rtc.d.ts +32 -0
  17. package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
  18. package/dist/src/room/PCTransport.d.ts.map +1 -1
  19. package/dist/src/room/RTCEngine.d.ts +5 -3
  20. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  21. package/dist/src/room/Room.d.ts +20 -15
  22. package/dist/src/room/Room.d.ts.map +1 -1
  23. package/dist/src/room/events.d.ts +15 -0
  24. package/dist/src/room/events.d.ts.map +1 -1
  25. package/dist/src/room/participant/LocalParticipant.d.ts +14 -2
  26. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  27. package/dist/src/room/participant/Participant.d.ts +4 -2
  28. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  29. package/dist/src/room/participant/RemoteParticipant.d.ts +2 -2
  30. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  31. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  32. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  33. package/dist/src/room/track/LocalTrack.d.ts +1 -1
  34. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  35. package/dist/src/room/track/LocalTrackPublication.d.ts +1 -1
  36. package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -1
  37. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  38. package/dist/src/room/track/RemoteAudioTrack.d.ts +1 -1
  39. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
  40. package/dist/src/room/track/create.d.ts.map +1 -1
  41. package/dist/src/room/track/options.d.ts +7 -1
  42. package/dist/src/room/track/options.d.ts.map +1 -1
  43. package/dist/src/room/types.d.ts +1 -0
  44. package/dist/src/room/types.d.ts.map +1 -1
  45. package/dist/src/room/utils.d.ts +3 -0
  46. package/dist/src/room/utils.d.ts.map +1 -1
  47. package/dist/ts4.2/src/api/SignalClient.d.ts +14 -10
  48. package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +1 -1
  49. package/dist/ts4.2/src/connectionHelper/checks/Checker.d.ts +1 -1
  50. package/dist/ts4.2/src/index.d.ts +6 -7
  51. package/dist/ts4.2/src/proto/livekit_models.d.ts +5 -0
  52. package/dist/ts4.2/src/proto/livekit_rtc.d.ts +32 -0
  53. package/dist/ts4.2/src/room/RTCEngine.d.ts +5 -3
  54. package/dist/ts4.2/src/room/Room.d.ts +20 -15
  55. package/dist/ts4.2/src/room/events.d.ts +15 -0
  56. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +14 -2
  57. package/dist/ts4.2/src/room/participant/Participant.d.ts +4 -2
  58. package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +2 -2
  59. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +1 -1
  60. package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +1 -1
  61. package/dist/ts4.2/src/room/track/RemoteAudioTrack.d.ts +1 -1
  62. package/dist/ts4.2/src/room/track/options.d.ts +7 -0
  63. package/dist/ts4.2/src/room/types.d.ts +1 -0
  64. package/dist/ts4.2/src/room/utils.d.ts +3 -0
  65. package/package.json +4 -3
  66. package/src/api/SignalClient.ts +38 -26
  67. package/src/connectionHelper/ConnectionCheck.ts +1 -2
  68. package/src/connectionHelper/checks/Checker.ts +1 -1
  69. package/src/connectionHelper/checks/reconnect.ts +1 -1
  70. package/src/index.ts +8 -10
  71. package/src/proto/livekit_models.ts +15 -0
  72. package/src/room/PCTransport.ts +40 -1
  73. package/src/room/RTCEngine.ts +32 -11
  74. package/src/room/RegionUrlProvider.ts +1 -1
  75. package/src/room/Room.ts +114 -70
  76. package/src/room/events.ts +17 -0
  77. package/src/room/participant/LocalParticipant.ts +65 -11
  78. package/src/room/participant/Participant.ts +27 -3
  79. package/src/room/participant/RemoteParticipant.ts +6 -3
  80. package/src/room/participant/publishUtils.test.ts +1 -1
  81. package/src/room/participant/publishUtils.ts +14 -6
  82. package/src/room/track/LocalAudioTrack.ts +1 -1
  83. package/src/room/track/LocalTrack.ts +2 -2
  84. package/src/room/track/LocalTrackPublication.ts +1 -1
  85. package/src/room/track/LocalVideoTrack.ts +3 -3
  86. package/src/room/track/RemoteAudioTrack.ts +1 -1
  87. package/src/room/track/RemoteVideoTrack.test.ts +1 -1
  88. package/src/room/track/RemoteVideoTrack.ts +3 -3
  89. package/src/room/track/create.ts +2 -2
  90. package/src/room/track/options.ts +14 -1
  91. package/src/room/types.ts +11 -0
  92. package/src/room/utils.ts +18 -8
@@ -146,6 +146,13 @@ export declare enum RoomEvent {
146
146
  *
147
147
  */
148
148
  ParticipantMetadataChanged = "participantMetadataChanged",
149
+ /**
150
+ * Participant's display name changed
151
+ *
152
+ * args: (name: string, [[Participant]])
153
+ *
154
+ */
155
+ ParticipantNameChanged = "participantNameChanged",
149
156
  /**
150
157
  * Room metadata is a simple way for app-specific state to be pushed to
151
158
  * all users.
@@ -315,6 +322,13 @@ export declare enum ParticipantEvent {
315
322
  *
316
323
  */
317
324
  ParticipantMetadataChanged = "participantMetadataChanged",
325
+ /**
326
+ * Participant's display name changed
327
+ *
328
+ * args: (name: string, [[Participant]])
329
+ *
330
+ */
331
+ ParticipantNameChanged = "participantNameChanged",
318
332
  /**
319
333
  * Data received from this participant as sender.
320
334
  * Data packets provides the ability to use LiveKit to send/receive arbitrary payloads.
@@ -380,6 +394,7 @@ export declare enum EngineEvent {
380
394
  Restarting = "restarting",
381
395
  Restarted = "restarted",
382
396
  SignalResumed = "signalResumed",
397
+ SignalRestarted = "signalRestarted",
383
398
  Closing = "closing",
384
399
  MediaTrackAdded = "mediaTrackAdded",
385
400
  ActiveSpeakersUpdate = "activeSpeakersUpdate",
@@ -5,8 +5,8 @@ import { DataChannelInfo, TrackPublishedResponse } from '../../proto/livekit_rtc
5
5
  import type RTCEngine from '../RTCEngine';
6
6
  import LocalTrack from '../track/LocalTrack';
7
7
  import LocalTrackPublication from '../track/LocalTrackPublication';
8
- import { AudioCaptureOptions, BackupVideoCodec, CreateLocalTracksOptions, ScreenShareCaptureOptions, TrackPublishOptions, VideoCaptureOptions } from '../track/options';
9
8
  import { Track } from '../track/Track';
9
+ import { AudioCaptureOptions, BackupVideoCodec, CreateLocalTracksOptions, ScreenShareCaptureOptions, TrackPublishOptions, VideoCaptureOptions } from '../track/options';
10
10
  import type { DataPublishOptions } from '../types';
11
11
  import Participant from './Participant';
12
12
  import { ParticipantTrackPermission } from './ParticipantTrackPermission';
@@ -39,6 +39,18 @@ export default class LocalParticipant extends Participant {
39
39
  private handleReconnecting;
40
40
  private handleReconnected;
41
41
  private handleDisconnected;
42
+ /**
43
+ * Sets and updates the metadata of the local participant.
44
+ * Note: this requires `CanUpdateOwnMetadata` permission encoded in the token.
45
+ * @param metadata
46
+ */
47
+ setMetadata(metadata: string): void;
48
+ /**
49
+ * Sets and updates the name of the local participant.
50
+ * Note: this requires `CanUpdateOwnMetadata` permission encoded in the token.
51
+ * @param metadata
52
+ */
53
+ setName(name: string): void;
42
54
  /**
43
55
  * Enable or disable a participant's camera track.
44
56
  *
@@ -139,7 +151,7 @@ export default class LocalParticipant extends Participant {
139
151
  */
140
152
  setTrackSubscriptionPermissions(allParticipantsAllowed: boolean, participantTrackPermissions?: ParticipantTrackPermission[]): void;
141
153
  /** @internal */
142
- updateInfo(info: ParticipantInfo): void;
154
+ updateInfo(info: ParticipantInfo): boolean;
143
155
  private updateTrackSubscriptionPermissions;
144
156
  /** @internal */
145
157
  private onTrackUnmuted;
@@ -1,5 +1,5 @@
1
1
  import type TypedEmitter from 'typed-emitter';
2
- import { ConnectionQuality as ProtoQuality, DataPacket_Kind, ParticipantInfo, ParticipantPermission } from '../../proto/livekit_models';
2
+ import { DataPacket_Kind, ParticipantInfo, ParticipantPermission, ConnectionQuality as ProtoQuality } from '../../proto/livekit_models';
3
3
  import type LocalTrackPublication from '../track/LocalTrackPublication';
4
4
  import type RemoteTrack from '../track/RemoteTrack';
5
5
  import type RemoteTrackPublication from '../track/RemoteTrackPublication';
@@ -57,9 +57,10 @@ export default class Participant extends Participant_base {
57
57
  /** when participant joined the room */
58
58
  get joinedAt(): Date | undefined;
59
59
  /** @internal */
60
- updateInfo(info: ParticipantInfo): void;
60
+ updateInfo(info: ParticipantInfo): boolean;
61
61
  /** @internal */
62
62
  setMetadata(md: string): void;
63
+ protected setName(name: string): void;
63
64
  /** @internal */
64
65
  setPermissions(permissions: ParticipantPermission): boolean;
65
66
  /** @internal */
@@ -79,6 +80,7 @@ export type ParticipantEventCallbacks = {
79
80
  localTrackPublished: (publication: LocalTrackPublication) => void;
80
81
  localTrackUnpublished: (publication: LocalTrackPublication) => void;
81
82
  participantMetadataChanged: (prevMetadata: string | undefined, participant?: any) => void;
83
+ participantNameChanged: (name: string) => void;
82
84
  dataReceived: (payload: Uint8Array, kind: DataPacket_Kind) => void;
83
85
  isSpeakingChanged: (speaking: boolean) => void;
84
86
  connectionQualityChanged: (connectionQuality: ConnectionQuality) => void;
@@ -1,8 +1,8 @@
1
1
  import type { SignalClient } from '../../api/SignalClient';
2
2
  import type { ParticipantInfo } from '../../proto/livekit_models';
3
- import type { AudioOutputOptions } from '../track/options';
4
3
  import RemoteTrackPublication from '../track/RemoteTrackPublication';
5
4
  import { Track } from '../track/Track';
5
+ import type { AudioOutputOptions } from '../track/options';
6
6
  import type { AdaptiveStreamSettings } from '../track/types';
7
7
  import Participant, { ParticipantEventCallbacks } from './Participant';
8
8
  export default class RemoteParticipant extends Participant {
@@ -35,7 +35,7 @@ export default class RemoteParticipant extends Participant {
35
35
  get hasMetadata(): boolean;
36
36
  getTrackPublication(sid: Track.SID): RemoteTrackPublication | undefined;
37
37
  /** @internal */
38
- updateInfo(info: ParticipantInfo): void;
38
+ updateInfo(info: ParticipantInfo): boolean;
39
39
  /** @internal */
40
40
  unpublishTrack(sid: Track.SID, sendUnpublish?: boolean): void;
41
41
  /**
@@ -1,6 +1,6 @@
1
1
  import { Mutex } from '../utils';
2
- import type { VideoCodec } from './options';
3
2
  import { Track } from './Track';
3
+ import type { VideoCodec } from './options';
4
4
  export default abstract class LocalTrack extends Track {
5
5
  /** @internal */
6
6
  sender?: RTCRtpSender;
@@ -2,9 +2,9 @@ import type { TrackInfo } from '../../proto/livekit_models';
2
2
  import type LocalAudioTrack from './LocalAudioTrack';
3
3
  import type LocalTrack from './LocalTrack';
4
4
  import type LocalVideoTrack from './LocalVideoTrack';
5
- import type { TrackPublishOptions } from './options';
6
5
  import type { Track } from './Track';
7
6
  import { TrackPublication } from './TrackPublication';
7
+ import type { TrackPublishOptions } from './options';
8
8
  export default class LocalTrackPublication extends TrackPublication {
9
9
  track?: LocalTrack;
10
10
  options?: TrackPublishOptions;
@@ -1,6 +1,6 @@
1
1
  import { AudioReceiverStats } from '../stats';
2
- import type { AudioOutputOptions } from './options';
3
2
  import RemoteTrack from './RemoteTrack';
3
+ import type { AudioOutputOptions } from './options';
4
4
  export default class RemoteAudioTrack extends RemoteTrack {
5
5
  private prevStats?;
6
6
  private elementVolume;
@@ -122,6 +122,11 @@ export interface ScreenShareCaptureOptions {
122
122
  surfaceSwitching?: 'include' | 'exclude';
123
123
  /** specifies whether the browser should include the system audio among the possible audio sources offered to the user */
124
124
  systemAudio?: 'include' | 'exclude';
125
+ /**
126
+ * Experimental option to control whether the audio playing in a tab will continue to be played out of a user's
127
+ * local speakers when the tab is captured.
128
+ */
129
+ suppressLocalAudioPlayback?: boolean;
125
130
  }
126
131
  export interface AudioCaptureOptions {
127
132
  /**
@@ -189,6 +194,7 @@ export interface AudioPreset {
189
194
  declare const codecs: readonly [
190
195
  "vp8",
191
196
  "h264",
197
+ "vp9",
192
198
  "av1"
193
199
  ];
194
200
  declare const backupCodecs: readonly [
@@ -198,6 +204,7 @@ declare const backupCodecs: readonly [
198
204
  export type VideoCodec = (typeof codecs)[number];
199
205
  export type BackupVideoCodec = (typeof backupCodecs)[number];
200
206
  export declare function isBackupCodec(codec: string): codec is BackupVideoCodec;
207
+ export declare function isCodecEqual(c1: string | undefined, c2: string | undefined): boolean;
201
208
  /**
202
209
  * scalability modes for svc, only supprot l3t3 now.
203
210
  */
@@ -22,4 +22,5 @@ export type LiveKitReactNativeInfo = {
22
22
  platform: 'ios' | 'android' | 'windows' | 'macos' | 'web' | 'native';
23
23
  devicePixelRatio: number;
24
24
  };
25
+ export type SimulationScenario = 'signal-reconnect' | 'speaker' | 'node-failure' | 'server-leave' | 'migration' | 'resume-reconnect' | 'force-tcp' | 'force-tls' | 'full-reconnect';
25
26
  //# sourceMappingURL=types.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import { ClientInfo } from '../proto/livekit_models';
2
2
  import type LocalAudioTrack from './track/LocalAudioTrack';
3
3
  import type RemoteAudioTrack from './track/RemoteAudioTrack';
4
+ export declare const ddExtensionURI = "https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension";
4
5
  export declare function unpackStreamId(packed: string): string[];
5
6
  export declare function sleep(duration: number): Promise<void>;
6
7
  /** @internal */
@@ -10,6 +11,8 @@ export declare function supportsAddTrack(): boolean;
10
11
  export declare function supportsAdaptiveStream(): boolean;
11
12
  export declare function supportsDynacast(): boolean;
12
13
  export declare function supportsAV1(): boolean;
14
+ export declare function supportsVP9(): boolean;
15
+ export declare function isSVCCodec(codec?: string): boolean;
13
16
  export declare function supportsSetSinkId(elm?: HTMLMediaElement): boolean;
14
17
  export declare function supportsSetCodecPreferences(transceiver: RTCRtpTransceiver): boolean;
15
18
  export declare function isBrowserSupported(): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livekit-client",
3
- "version": "1.8.0",
3
+ "version": "1.9.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",
@@ -53,13 +53,14 @@
53
53
  "devDependencies": {
54
54
  "@babel/core": "7.21.4",
55
55
  "@babel/preset-env": "7.21.4",
56
- "@changesets/changelog-github": "0.4.8",
57
56
  "@changesets/cli": "2.26.1",
57
+ "@livekit/changesets-changelog-github": "^0.0.4",
58
58
  "@rollup/plugin-babel": "6.0.3",
59
59
  "@rollup/plugin-commonjs": "24.1.0",
60
60
  "@rollup/plugin-json": "6.0.0",
61
61
  "@rollup/plugin-node-resolve": "15.0.2",
62
62
  "@rollup/plugin-terser": "^0.4.0",
63
+ "@trivago/prettier-plugin-sort-imports": "^4.1.1",
63
64
  "@types/jest": "29.5.0",
64
65
  "@types/sdp-transform": "2.4.6",
65
66
  "@types/ua-parser-js": "0.7.36",
@@ -73,7 +74,7 @@
73
74
  "eslint-plugin-import": "2.27.5",
74
75
  "gh-pages": "5.0.0",
75
76
  "jest": "29.5.0",
76
- "prettier": "2.8.7",
77
+ "prettier": "^2.8.8",
77
78
  "rollup": "3.20.2",
78
79
  "rollup-plugin-delete": "^2.0.0",
79
80
  "rollup-plugin-filesize": "10.0.0",
@@ -33,7 +33,7 @@ import {
33
33
  } from '../proto/livekit_rtc';
34
34
  import { ConnectionError, ConnectionErrorReason } from '../room/errors';
35
35
  import CriticalTimers from '../room/timers';
36
- import { getClientInfo, isReactNative, Mutex, sleep } from '../room/utils';
36
+ import { Mutex, getClientInfo, isReactNative, sleep } from '../room/utils';
37
37
 
38
38
  // internal options
39
39
  interface ConnectOpts {
@@ -374,7 +374,7 @@ export class SignalClient {
374
374
  // answer a server-initiated offer
375
375
  sendAnswer(answer: RTCSessionDescriptionInit) {
376
376
  log.debug('sending answer');
377
- this.sendRequest({
377
+ return this.sendRequest({
378
378
  $case: 'answer',
379
379
  answer: toProtoSessionDescription(answer),
380
380
  });
@@ -382,7 +382,7 @@ export class SignalClient {
382
382
 
383
383
  sendIceCandidate(candidate: RTCIceCandidateInit, target: SignalTarget) {
384
384
  log.trace('sending ice candidate', candidate);
385
- this.sendRequest({
385
+ return this.sendRequest({
386
386
  $case: 'trickle',
387
387
  trickle: {
388
388
  candidateInit: JSON.stringify(candidate),
@@ -392,7 +392,7 @@ export class SignalClient {
392
392
  }
393
393
 
394
394
  sendMuteTrack(trackSid: string, muted: boolean) {
395
- this.sendRequest({
395
+ return this.sendRequest({
396
396
  $case: 'mute',
397
397
  mute: {
398
398
  sid: trackSid,
@@ -401,13 +401,23 @@ export class SignalClient {
401
401
  });
402
402
  }
403
403
 
404
- sendAddTrack(req: AddTrackRequest): void {
405
- this.sendRequest({
404
+ sendAddTrack(req: AddTrackRequest) {
405
+ return this.sendRequest({
406
406
  $case: 'addTrack',
407
407
  addTrack: AddTrackRequest.fromPartial(req),
408
408
  });
409
409
  }
410
410
 
411
+ sendUpdateLocalMetadata(metadata: string, name: string) {
412
+ return this.sendRequest({
413
+ $case: 'updateMetadata',
414
+ updateMetadata: {
415
+ metadata,
416
+ name,
417
+ },
418
+ });
419
+ }
420
+
411
421
  sendUpdateTrackSettings(settings: UpdateTrackSettings) {
412
422
  this.sendRequest({
413
423
  $case: 'trackSetting',
@@ -416,21 +426,21 @@ export class SignalClient {
416
426
  }
417
427
 
418
428
  sendUpdateSubscription(sub: UpdateSubscription) {
419
- this.sendRequest({
429
+ return this.sendRequest({
420
430
  $case: 'subscription',
421
431
  subscription: sub,
422
432
  });
423
433
  }
424
434
 
425
435
  sendSyncState(sync: SyncState) {
426
- this.sendRequest({
436
+ return this.sendRequest({
427
437
  $case: 'syncState',
428
438
  syncState: sync,
429
439
  });
430
440
  }
431
441
 
432
442
  sendUpdateVideoLayers(trackSid: string, layers: VideoLayer[]) {
433
- this.sendRequest({
443
+ return this.sendRequest({
434
444
  $case: 'updateLayers',
435
445
  updateLayers: {
436
446
  trackSid,
@@ -440,7 +450,7 @@ export class SignalClient {
440
450
  }
441
451
 
442
452
  sendUpdateSubscriptionPermissions(allParticipants: boolean, trackPermissions: TrackPermission[]) {
443
- this.sendRequest({
453
+ return this.sendRequest({
444
454
  $case: 'subscriptionPermission',
445
455
  subscriptionPermission: {
446
456
  allParticipants,
@@ -450,7 +460,7 @@ export class SignalClient {
450
460
  }
451
461
 
452
462
  sendSimulateScenario(scenario: SimulateScenario) {
453
- this.sendRequest({
463
+ return this.sendRequest({
454
464
  $case: 'simulate',
455
465
  simulate: scenario,
456
466
  });
@@ -458,21 +468,23 @@ export class SignalClient {
458
468
 
459
469
  sendPing() {
460
470
  /** send both of ping and pingReq for compatibility to old and new server */
461
- this.sendRequest({
462
- $case: 'ping',
463
- ping: Date.now(),
464
- });
465
- this.sendRequest({
466
- $case: 'pingReq',
467
- pingReq: {
468
- timestamp: Date.now(),
469
- rtt: this.rtt,
470
- },
471
- });
472
- }
473
-
474
- async sendLeave() {
475
- await this.sendRequest({
471
+ return Promise.all([
472
+ this.sendRequest({
473
+ $case: 'ping',
474
+ ping: Date.now(),
475
+ }),
476
+ this.sendRequest({
477
+ $case: 'pingReq',
478
+ pingReq: {
479
+ timestamp: Date.now(),
480
+ rtt: this.rtt,
481
+ },
482
+ }),
483
+ ]);
484
+ }
485
+
486
+ sendLeave() {
487
+ return this.sendRequest({
476
488
  $case: 'leave',
477
489
  leave: {
478
490
  canReconnect: false,
@@ -1,7 +1,6 @@
1
1
  import EventEmitter from 'events';
2
2
  import type TypedEmitter from 'typed-emitter';
3
-
4
- import { Checker, CheckInfo, CheckStatus, InstantiableCheck } from './checks/Checker';
3
+ import { CheckInfo, CheckStatus, Checker, InstantiableCheck } from './checks/Checker';
5
4
  import { PublishAudioCheck } from './checks/publishAudio';
6
5
  import { PublishVideoCheck } from './checks/publishVideo';
7
6
  import { ReconnectCheck } from './checks/reconnect';
@@ -1,8 +1,8 @@
1
1
  import { EventEmitter } from 'events';
2
2
  import type TypedEmitter from 'typed-emitter';
3
3
  import type { RoomConnectOptions, RoomOptions } from '../../options';
4
- import Room, { ConnectionState } from '../../room/Room';
5
4
  import type RTCEngine from '../../room/RTCEngine';
5
+ import Room, { ConnectionState } from '../../room/Room';
6
6
 
7
7
  type LogMessage = {
8
8
  level: 'info' | 'warning' | 'error';
@@ -1,5 +1,5 @@
1
- import { RoomEvent } from '../../room/events';
2
1
  import { ConnectionState } from '../../room/Room';
2
+ import { RoomEvent } from '../../room/events';
3
3
  import { Checker } from './Checker';
4
4
 
5
5
  export class ReconnectCheck extends Checker {
package/src/index.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { LogLevel, setLogExtension, setLogLevel } from './logger';
2
2
  import { DataPacket_Kind, DisconnectReason, VideoQuality } from './proto/livekit_models';
3
3
  import DefaultReconnectPolicy from './room/DefaultReconnectPolicy';
4
+ import Room, { ConnectionState, RoomState } from './room/Room';
4
5
  import LocalParticipant from './room/participant/LocalParticipant';
5
6
  import Participant, { ConnectionQuality } from './room/participant/Participant';
6
7
  import type { ParticipantTrackPermission } from './room/participant/ParticipantTrackPermission';
7
8
  import RemoteParticipant from './room/participant/RemoteParticipant';
8
- import Room, { ConnectionState, RoomState } from './room/Room';
9
+ import CriticalTimers from './room/timers';
9
10
  import LocalAudioTrack from './room/track/LocalAudioTrack';
10
11
  import LocalTrack from './room/track/LocalTrack';
11
12
  import LocalTrackPublication from './room/track/LocalTrackPublication';
@@ -13,27 +14,24 @@ import LocalVideoTrack from './room/track/LocalVideoTrack';
13
14
  import RemoteAudioTrack from './room/track/RemoteAudioTrack';
14
15
  import RemoteTrack from './room/track/RemoteTrack';
15
16
  import RemoteTrackPublication from './room/track/RemoteTrackPublication';
16
- import RemoteVideoTrack from './room/track/RemoteVideoTrack';
17
- import type { ElementInfo } from './room/track/RemoteVideoTrack';
17
+ import RemoteVideoTrack, { type ElementInfo } from './room/track/RemoteVideoTrack';
18
18
  import { TrackPublication } from './room/track/TrackPublication';
19
- import CriticalTimers from './room/timers';
19
+ import type { LiveKitReactNativeInfo } from './room/types';
20
20
  import {
21
+ type AudioAnalyserOptions,
22
+ createAudioAnalyser,
21
23
  getEmptyAudioStreamTrack,
22
24
  getEmptyVideoStreamTrack,
23
25
  isBrowserSupported,
24
- supportsAdaptiveStream,
25
26
  supportsAV1,
27
+ supportsAdaptiveStream,
26
28
  supportsDynacast,
27
- createAudioAnalyser,
28
29
  } from './room/utils';
29
30
 
30
- import type { AudioAnalyserOptions } from './room/utils';
31
- import type { LiveKitReactNativeInfo } from './room/types';
32
-
33
31
  export * from './options';
34
32
  export * from './room/errors';
35
33
  export * from './room/events';
36
- export type { DataPublishOptions } from './room/types';
34
+ export type { DataPublishOptions, SimulationScenario } from './room/types';
37
35
  export * from './room/track/create';
38
36
  export * from './room/track/options';
39
37
  export * from './room/track/Track';
@@ -438,6 +438,7 @@ export interface Room {
438
438
  enabledCodecs: Codec[];
439
439
  metadata: string;
440
440
  numParticipants: number;
441
+ numPublishers: number;
441
442
  activeRecording: boolean;
442
443
  }
443
444
 
@@ -904,6 +905,7 @@ function createBaseRoom(): Room {
904
905
  enabledCodecs: [],
905
906
  metadata: "",
906
907
  numParticipants: 0,
908
+ numPublishers: 0,
907
909
  activeRecording: false,
908
910
  };
909
911
  }
@@ -937,6 +939,9 @@ export const Room = {
937
939
  if (message.numParticipants !== 0) {
938
940
  writer.uint32(72).uint32(message.numParticipants);
939
941
  }
942
+ if (message.numPublishers !== 0) {
943
+ writer.uint32(88).uint32(message.numPublishers);
944
+ }
940
945
  if (message.activeRecording === true) {
941
946
  writer.uint32(80).bool(message.activeRecording);
942
947
  }
@@ -1013,6 +1018,13 @@ export const Room = {
1013
1018
 
1014
1019
  message.numParticipants = reader.uint32();
1015
1020
  continue;
1021
+ case 11:
1022
+ if (tag != 88) {
1023
+ break;
1024
+ }
1025
+
1026
+ message.numPublishers = reader.uint32();
1027
+ continue;
1016
1028
  case 10:
1017
1029
  if (tag != 80) {
1018
1030
  break;
@@ -1042,6 +1054,7 @@ export const Room = {
1042
1054
  : [],
1043
1055
  metadata: isSet(object.metadata) ? String(object.metadata) : "",
1044
1056
  numParticipants: isSet(object.numParticipants) ? Number(object.numParticipants) : 0,
1057
+ numPublishers: isSet(object.numPublishers) ? Number(object.numPublishers) : 0,
1045
1058
  activeRecording: isSet(object.activeRecording) ? Boolean(object.activeRecording) : false,
1046
1059
  };
1047
1060
  },
@@ -1061,6 +1074,7 @@ export const Room = {
1061
1074
  }
1062
1075
  message.metadata !== undefined && (obj.metadata = message.metadata);
1063
1076
  message.numParticipants !== undefined && (obj.numParticipants = Math.round(message.numParticipants));
1077
+ message.numPublishers !== undefined && (obj.numPublishers = Math.round(message.numPublishers));
1064
1078
  message.activeRecording !== undefined && (obj.activeRecording = message.activeRecording);
1065
1079
  return obj;
1066
1080
  },
@@ -1080,6 +1094,7 @@ export const Room = {
1080
1094
  message.enabledCodecs = object.enabledCodecs?.map((e) => Codec.fromPartial(e)) || [];
1081
1095
  message.metadata = object.metadata ?? "";
1082
1096
  message.numParticipants = object.numParticipants ?? 0;
1097
+ message.numPublishers = object.numPublishers ?? 0;
1083
1098
  message.activeRecording = object.activeRecording ?? false;
1084
1099
  return message;
1085
1100
  },
@@ -3,6 +3,7 @@ import { MediaDescription, parse, write } from 'sdp-transform';
3
3
  import { debounce } from 'ts-debounce';
4
4
  import log from '../logger';
5
5
  import { NegotiationError } from './errors';
6
+ import { ddExtensionURI, isSVCCodec } from './utils';
6
7
 
7
8
  /** @internal */
8
9
  interface TrackBitrateInfo {
@@ -122,6 +123,7 @@ export default class PCTransport extends EventEmitter {
122
123
  if (media.type === 'audio') {
123
124
  ensureAudioNackAndStereo(media, [], []);
124
125
  } else if (media.type === 'video') {
126
+ ensureVideoDDExtensionForSVC(media);
125
127
  // mung sdp for codec bitrate setting that can't apply by sendEncoding
126
128
  this.trackBitrates.some((trackbr): boolean => {
127
129
  if (!media.msid || !media.msid.includes(trackbr.sid)) {
@@ -142,6 +144,9 @@ export default class PCTransport extends EventEmitter {
142
144
  if (
143
145
  !media.fmtp.some((fmtp): boolean => {
144
146
  if (fmtp.payload === codecPayload) {
147
+ if (!fmtp.config.includes('x-google-start-bitrate')) {
148
+ fmtp.config += `;x-google-start-bitrate=${trackbr.maxbr * 0.7}`;
149
+ }
145
150
  if (!fmtp.config.includes('x-google-max-bitrate')) {
146
151
  fmtp.config += `;x-google-max-bitrate=${trackbr.maxbr}`;
147
152
  }
@@ -152,7 +157,9 @@ export default class PCTransport extends EventEmitter {
152
157
  ) {
153
158
  media.fmtp.push({
154
159
  payload: codecPayload,
155
- config: `x-google-max-bitrate=${trackbr.maxbr}`,
160
+ config: `x-google-start-bitrate=${trackbr.maxbr * 0.7};x-google-max-bitrate=${
161
+ trackbr.maxbr
162
+ }`,
156
163
  });
157
164
  }
158
165
  }
@@ -274,6 +281,38 @@ function ensureAudioNackAndStereo(
274
281
  }
275
282
  }
276
283
 
284
+ function ensureVideoDDExtensionForSVC(
285
+ media: {
286
+ type: string;
287
+ port: number;
288
+ protocol: string;
289
+ payloads?: string | undefined;
290
+ } & MediaDescription,
291
+ ) {
292
+ const codec = media.rtp.at(0)?.codec?.toLowerCase();
293
+ if (!isSVCCodec(codec)) {
294
+ return;
295
+ }
296
+
297
+ let maxID = 0;
298
+ const ddFound = media.ext?.some((ext): boolean => {
299
+ if (ext.uri === ddExtensionURI) {
300
+ return true;
301
+ }
302
+ if (ext.value > maxID) {
303
+ maxID = ext.value;
304
+ }
305
+ return false;
306
+ });
307
+
308
+ if (!ddFound) {
309
+ media.ext?.push({
310
+ value: maxID + 1,
311
+ uri: ddExtensionURI,
312
+ });
313
+ }
314
+ }
315
+
277
316
  function extractStereoAndNackAudioFromOffer(offer: RTCSessionDescriptionInit): {
278
317
  stereoMids: string[];
279
318
  nackMids: string[];