livekit-client 1.6.2 → 1.6.4

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 (64) hide show
  1. package/dist/livekit-client.esm.mjs +468 -140
  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/api/SignalClient.d.ts +3 -3
  6. package/dist/src/api/SignalClient.d.ts.map +1 -1
  7. package/dist/src/connectionHelper/ConnectionCheck.d.ts +2 -2
  8. package/dist/src/connectionHelper/ConnectionCheck.d.ts.map +1 -1
  9. package/dist/src/index.d.ts +2 -1
  10. package/dist/src/index.d.ts.map +1 -1
  11. package/dist/src/proto/livekit_models.d.ts +53 -4
  12. package/dist/src/proto/livekit_models.d.ts.map +1 -1
  13. package/dist/src/proto/livekit_rtc.d.ts +650 -91
  14. package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
  15. package/dist/src/room/PCTransport.d.ts +1 -0
  16. package/dist/src/room/PCTransport.d.ts.map +1 -1
  17. package/dist/src/room/RTCEngine.d.ts +2 -0
  18. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  19. package/dist/src/room/Room.d.ts +1 -1
  20. package/dist/src/room/Room.d.ts.map +1 -1
  21. package/dist/src/room/errors.d.ts +3 -0
  22. package/dist/src/room/errors.d.ts.map +1 -1
  23. package/dist/src/room/participant/LocalParticipant.d.ts +1 -3
  24. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  25. package/dist/src/room/participant/Participant.d.ts +1 -1
  26. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  27. package/dist/src/room/timers.d.ts +13 -0
  28. package/dist/src/room/timers.d.ts.map +1 -0
  29. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  30. package/dist/src/room/track/create.d.ts.map +1 -1
  31. package/dist/src/room/track/options.d.ts +2 -2
  32. package/dist/src/room/track/options.d.ts.map +1 -1
  33. package/dist/src/test/mocks.d.ts +1 -1
  34. package/dist/ts4.2/src/api/SignalClient.d.ts +3 -3
  35. package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +2 -2
  36. package/dist/ts4.2/src/index.d.ts +2 -1
  37. package/dist/ts4.2/src/proto/livekit_models.d.ts +59 -4
  38. package/dist/ts4.2/src/proto/livekit_rtc.d.ts +739 -120
  39. package/dist/ts4.2/src/room/PCTransport.d.ts +1 -0
  40. package/dist/ts4.2/src/room/RTCEngine.d.ts +2 -0
  41. package/dist/ts4.2/src/room/Room.d.ts +1 -1
  42. package/dist/ts4.2/src/room/errors.d.ts +3 -0
  43. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +1 -3
  44. package/dist/ts4.2/src/room/participant/Participant.d.ts +1 -1
  45. package/dist/ts4.2/src/room/timers.d.ts +13 -0
  46. package/dist/ts4.2/src/room/track/options.d.ts +2 -2
  47. package/dist/ts4.2/src/test/mocks.d.ts +1 -1
  48. package/package.json +17 -17
  49. package/src/api/SignalClient.ts +33 -21
  50. package/src/connectionHelper/ConnectionCheck.ts +1 -1
  51. package/src/index.ts +2 -0
  52. package/src/proto/google/protobuf/timestamp.ts +2 -2
  53. package/src/proto/livekit_models.ts +158 -10
  54. package/src/proto/livekit_rtc.ts +205 -6
  55. package/src/room/PCTransport.ts +22 -6
  56. package/src/room/RTCEngine.ts +58 -45
  57. package/src/room/Room.ts +8 -10
  58. package/src/room/errors.ts +6 -0
  59. package/src/room/participant/LocalParticipant.ts +12 -17
  60. package/src/room/participant/Participant.ts +10 -2
  61. package/src/room/timers.ts +16 -0
  62. package/src/room/track/RemoteVideoTrack.ts +2 -1
  63. package/src/room/track/create.ts +6 -1
  64. package/src/room/track/options.ts +2 -2
@@ -18,6 +18,7 @@ export default class PCTransport extends EventEmitter {
18
18
  renegotiate: boolean;
19
19
  trackBitrates: TrackBitrateInfo[];
20
20
  remoteStereoMids: string[];
21
+ remoteNackMids: string[];
21
22
  onOffer?: (offer: RTCSessionDescriptionInit) => void;
22
23
  constructor(config?: RTCConfiguration);
23
24
  get isICEConnected(): boolean;
@@ -54,6 +54,7 @@ export default class RTCEngine extends RTCEngine_base {
54
54
  get dataSubscriberReadyState(): string | undefined;
55
55
  get connectedServerAddress(): string | undefined;
56
56
  private configure;
57
+ private makeRTCConfiguration;
57
58
  private createDataChannels;
58
59
  private handleDataChannel;
59
60
  private handleDataMessage;
@@ -79,6 +80,7 @@ export default class RTCEngine extends RTCEngine_base {
79
80
  /** @internal */
80
81
  negotiate(): Promise<void>;
81
82
  dataChannelForKind(kind: DataPacket_Kind, sub?: boolean): RTCDataChannel | undefined;
83
+ private clearReconnectTimeout;
82
84
  private clearPendingReconnect;
83
85
  private handleBrowserOnLine;
84
86
  private registerOnLineListener;
@@ -204,7 +204,7 @@ export type RoomEventCallbacks = {
204
204
  localTrackPublished: (publication: LocalTrackPublication, participant: LocalParticipant) => void;
205
205
  localTrackUnpublished: (publication: LocalTrackPublication, participant: LocalParticipant) => void;
206
206
  participantMetadataChanged: (metadata: string | undefined, participant: RemoteParticipant | LocalParticipant) => void;
207
- participantPermissionsChanged: (prevPermissions: ParticipantPermission, participant: RemoteParticipant | LocalParticipant) => void;
207
+ participantPermissionsChanged: (prevPermissions: ParticipantPermission | undefined, participant: RemoteParticipant | LocalParticipant) => void;
208
208
  activeSpeakersChanged: (speakers: Array<Participant>) => void;
209
209
  roomMetadataChanged: (metadata: string) => void;
210
210
  dataReceived: (payload: Uint8Array, participant?: RemoteParticipant, kind?: DataPacket_Kind) => void;
@@ -12,6 +12,9 @@ export declare class ConnectionError extends LivekitError {
12
12
  reason?: ConnectionErrorReason;
13
13
  constructor(message?: string, reason?: ConnectionErrorReason, status?: number);
14
14
  }
15
+ export declare class DeviceUnsupportedError extends LivekitError {
16
+ constructor(message?: string);
17
+ }
15
18
  export declare class TrackInvalidError extends LivekitError {
16
19
  constructor(message?: string);
17
20
  }
@@ -1,6 +1,6 @@
1
1
  import 'webrtc-adapter';
2
2
  import type { InternalRoomOptions } from '../../options';
3
- import { DataPacket_Kind, ParticipantInfo, ParticipantPermission } from '../../proto/livekit_models';
3
+ import { DataPacket_Kind, ParticipantInfo } from '../../proto/livekit_models';
4
4
  import { DataChannelInfo, TrackPublishedResponse } from '../../proto/livekit_rtc';
5
5
  import type RTCEngine from '../RTCEngine';
6
6
  import LocalTrack from '../track/LocalTrack';
@@ -52,8 +52,6 @@ export default class LocalParticipant extends Participant {
52
52
  * Resolves with a `LocalTrackPublication` instance if successful and `undefined` otherwise
53
53
  */
54
54
  setScreenShareEnabled(enabled: boolean, options?: ScreenShareCaptureOptions, publishOptions?: TrackPublishOptions): Promise<LocalTrackPublication | undefined>;
55
- /** @internal */
56
- setPermissions(permissions: ParticipantPermission): boolean;
57
55
  /**
58
56
  * Enable or disable publishing for a track by source. This serves as a simple
59
57
  * way to manage the common tracks (camera, mic, or screen share).
@@ -85,7 +85,7 @@ export type ParticipantEventCallbacks = {
85
85
  trackStreamStateChanged: (publication: RemoteTrackPublication, streamState: Track.StreamState) => void;
86
86
  trackSubscriptionPermissionChanged: (publication: RemoteTrackPublication, status: TrackPublication.PermissionStatus) => void;
87
87
  mediaDevicesError: (error: Error) => void;
88
- participantPermissionsChanged: (prevPermissions: ParticipantPermission) => void;
88
+ participantPermissionsChanged: (prevPermissions?: ParticipantPermission) => void;
89
89
  trackSubscriptionStatusChanged: (publication: RemoteTrackPublication, status: TrackPublication.SubscriptionStatus) => void;
90
90
  };
91
91
  export {};
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * Timers that can be overridden with platform specific implementations
4
+ * that ensure that they are fired. These should be used when it is critical
5
+ * that the timer fires on time.
6
+ */
7
+ export default class CriticalTimers {
8
+ static setTimeout: (callback: (args: void) => void, ms?: number | undefined) => NodeJS.Timeout;
9
+ static setInterval: (callback: (args: void) => void, ms?: number | undefined) => NodeJS.Timer;
10
+ static clearTimeout: (timeoutId: NodeJS.Timeout) => void;
11
+ static clearInterval: (intervalId: NodeJS.Timeout) => void;
12
+ }
13
+ //# sourceMappingURL=timers.d.ts.map
@@ -187,8 +187,8 @@ declare const backupCodecs: readonly [
187
187
  "vp8",
188
188
  "h264"
189
189
  ];
190
- export type VideoCodec = typeof codecs[number];
191
- export type BackupVideoCodec = typeof backupCodecs[number];
190
+ export type VideoCodec = (typeof codecs)[number];
191
+ export type BackupVideoCodec = (typeof backupCodecs)[number];
192
192
  export declare function isBackupCodec(codec: string): codec is BackupVideoCodec;
193
193
  /**
194
194
  * scalability modes for svc, only supprot l3t3 now.
@@ -4,7 +4,7 @@ declare const mocks: {
4
4
  SignalClient: jest.MockedClass<typeof SignalClient>;
5
5
  RTCEngine: jest.MockedClass<typeof RTCEngine>;
6
6
  MockLocalVideoTrack: {
7
- stop: jest.Mock<any, any>;
7
+ stop: jest.Mock<any, any, any>;
8
8
  };
9
9
  };
10
10
  export default mocks;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livekit-client",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
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",
@@ -51,40 +51,40 @@
51
51
  "webrtc-adapter": "^8.1.1"
52
52
  },
53
53
  "devDependencies": {
54
- "@babel/core": "7.20.7",
54
+ "@babel/core": "7.20.12",
55
55
  "@babel/preset-env": "7.20.2",
56
56
  "@changesets/changelog-github": "0.4.8",
57
57
  "@changesets/cli": "2.26.0",
58
58
  "@rollup/plugin-babel": "6.0.3",
59
- "@rollup/plugin-commonjs": "24.0.0",
59
+ "@rollup/plugin-commonjs": "24.0.1",
60
60
  "@rollup/plugin-json": "6.0.0",
61
61
  "@rollup/plugin-node-resolve": "15.0.1",
62
- "@types/jest": "29.2.5",
62
+ "@types/jest": "29.4.0",
63
63
  "@types/sdp-transform": "2.4.5",
64
64
  "@types/ua-parser-js": "0.7.36",
65
65
  "@types/ws": "8.5.4",
66
- "@typescript-eslint/eslint-plugin": "5.47.1",
67
- "@typescript-eslint/parser": "5.47.1",
66
+ "@typescript-eslint/eslint-plugin": "5.50.0",
67
+ "@typescript-eslint/parser": "5.50.0",
68
68
  "downlevel-dts": "^0.11.0",
69
- "eslint": "8.31.0",
69
+ "eslint": "8.33.0",
70
70
  "eslint-config-airbnb-typescript": "17.0.0",
71
- "eslint-config-prettier": "8.5.0",
72
- "eslint-plugin-import": "2.26.0",
71
+ "eslint-config-prettier": "8.6.0",
72
+ "eslint-plugin-import": "2.27.5",
73
73
  "gh-pages": "4.0.0",
74
- "jest": "29.3.1",
75
- "prettier": "2.8.1",
76
- "rollup": "3.9.1",
74
+ "jest": "29.4.1",
75
+ "prettier": "2.8.3",
76
+ "rollup": "3.12.1",
77
77
  "rollup-plugin-delete": "^2.0.0",
78
78
  "rollup-plugin-filesize": "9.1.2",
79
79
  "rollup-plugin-re": "1.0.7",
80
80
  "rollup-plugin-terser": "7.0.2",
81
81
  "rollup-plugin-typescript2": "0.34.1",
82
- "ts-jest": "29.0.3",
83
- "ts-proto": "1.137.0",
84
- "typedoc": "0.23.23",
82
+ "ts-jest": "29.0.5",
83
+ "ts-proto": "1.139.0",
84
+ "typedoc": "0.23.24",
85
85
  "typedoc-plugin-no-inherit": "1.4.0",
86
- "typescript": "4.9.4",
87
- "vite": "4.0.3"
86
+ "typescript": "4.9.5",
87
+ "vite": "4.0.4"
88
88
  },
89
89
  "browserslist": [
90
90
  "safari >= 11",
@@ -14,6 +14,7 @@ import {
14
14
  ConnectionQualityUpdate,
15
15
  JoinResponse,
16
16
  LeaveRequest,
17
+ ReconnectResponse,
17
18
  SessionDescription,
18
19
  SignalRequest,
19
20
  SignalResponse,
@@ -30,6 +31,7 @@ import {
30
31
  UpdateTrackSettings,
31
32
  } from '../proto/livekit_rtc';
32
33
  import { ConnectionError, ConnectionErrorReason } from '../room/errors';
34
+ import CriticalTimers from '../room/timers';
33
35
  import { getClientInfo, Mutex, sleep } from '../room/utils';
34
36
 
35
37
  // internal options
@@ -164,7 +166,7 @@ export class SignalClient {
164
166
  return res as JoinResponse;
165
167
  }
166
168
 
167
- async reconnect(url: string, token: string, sid?: string): Promise<void> {
169
+ async reconnect(url: string, token: string, sid?: string): Promise<ReconnectResponse | void> {
168
170
  if (!this.options) {
169
171
  log.warn('attempted to reconnect without signal options being set, ignoring');
170
172
  return;
@@ -173,7 +175,8 @@ export class SignalClient {
173
175
  // clear ping interval and restart it once reconnected
174
176
  this.clearPingInterval();
175
177
 
176
- await this.connect(url, token, { ...this.options, reconnect: true, sid });
178
+ const res = await this.connect(url, token, { ...this.options, reconnect: true, sid });
179
+ return res;
177
180
  }
178
181
 
179
182
  connect(
@@ -181,7 +184,7 @@ export class SignalClient {
181
184
  token: string,
182
185
  opts: ConnectOpts,
183
186
  abortSignal?: AbortSignal,
184
- ): Promise<JoinResponse | void> {
187
+ ): Promise<JoinResponse | ReconnectResponse | void> {
185
188
  this.connectOptions = opts;
186
189
  if (url.startsWith('http')) {
187
190
  url = url.replace('http', 'ws');
@@ -193,7 +196,7 @@ export class SignalClient {
193
196
  const clientInfo = getClientInfo();
194
197
  const params = createConnectionParams(token, clientInfo, opts);
195
198
 
196
- return new Promise<JoinResponse | void>(async (resolve, reject) => {
199
+ return new Promise<JoinResponse | ReconnectResponse | void>(async (resolve, reject) => {
197
200
  const abortHandler = async () => {
198
201
  await this.close();
199
202
  reject(new ConnectionError('room connection has been cancelled'));
@@ -240,16 +243,6 @@ export class SignalClient {
240
243
  this.handleWSError(ev);
241
244
  };
242
245
 
243
- this.ws.onopen = () => {
244
- if (opts.reconnect) {
245
- // upon reconnection, there will not be additional handshake
246
- this.isConnected = true;
247
- // restart ping interval as it's cleared for reconnection
248
- this.startPingInterval();
249
- resolve();
250
- }
251
- };
252
-
253
246
  this.ws.onmessage = async (ev: MessageEvent) => {
254
247
  // not considered connected until JoinResponse is received
255
248
  let resp: SignalResponse;
@@ -264,6 +257,7 @@ export class SignalClient {
264
257
  }
265
258
 
266
259
  if (!this.isConnected) {
260
+ let shouldProcessMessage = false;
267
261
  // handle join message only
268
262
  if (resp.message?.$case === 'join') {
269
263
  this.isConnected = true;
@@ -279,14 +273,28 @@ export class SignalClient {
279
273
  this.startPingInterval();
280
274
  }
281
275
  resolve(resp.message.join);
282
- } else {
276
+ } else if (opts.reconnect) {
277
+ // in reconnecting, any message received means signal reconnected
278
+ this.isConnected = true;
279
+ abortSignal?.removeEventListener('abort', abortHandler);
280
+ this.startPingInterval();
281
+ if (resp.message?.$case === 'reconnect') {
282
+ resolve(resp.message?.reconnect);
283
+ } else {
284
+ resolve();
285
+ shouldProcessMessage = true;
286
+ }
287
+ } else if (!opts.reconnect) {
288
+ // non-reconnect case, should receive join response first
283
289
  reject(
284
290
  new ConnectionError(
285
291
  `did not receive join response, got ${resp.message?.$case} instead`,
286
292
  ),
287
293
  );
288
294
  }
289
- return;
295
+ if (!shouldProcessMessage) {
296
+ return;
297
+ }
290
298
  }
291
299
 
292
300
  if (this.signalLatency) {
@@ -485,7 +493,11 @@ export class SignalClient {
485
493
  }
486
494
 
487
495
  private handleSignalResponse(res: SignalResponse) {
488
- const msg = res.message!;
496
+ const msg = res.message;
497
+ if (msg == undefined) {
498
+ log.debug('received unsupported message');
499
+ return;
500
+ }
489
501
  if (msg.$case === 'answer') {
490
502
  const sd = fromProtoSessionDescription(msg.answer);
491
503
  if (this.onAnswer) {
@@ -576,7 +588,7 @@ export class SignalClient {
576
588
  log.warn('ping timeout duration not set');
577
589
  return;
578
590
  }
579
- this.pingTimeout = setTimeout(() => {
591
+ this.pingTimeout = CriticalTimers.setTimeout(() => {
580
592
  log.warn(
581
593
  `ping timeout triggered. last pong received at: ${new Date(
582
594
  Date.now() - this.pingTimeoutDuration! * 1000,
@@ -590,7 +602,7 @@ export class SignalClient {
590
602
 
591
603
  private clearPingTimeout() {
592
604
  if (this.pingTimeout) {
593
- clearTimeout(this.pingTimeout);
605
+ CriticalTimers.clearTimeout(this.pingTimeout);
594
606
  }
595
607
  }
596
608
 
@@ -602,7 +614,7 @@ export class SignalClient {
602
614
  return;
603
615
  }
604
616
  log.debug('start ping interval');
605
- this.pingInterval = setInterval(() => {
617
+ this.pingInterval = CriticalTimers.setInterval(() => {
606
618
  this.sendPing();
607
619
  }, this.pingIntervalDuration * 1000);
608
620
  }
@@ -611,7 +623,7 @@ export class SignalClient {
611
623
  log.debug('clearing ping interval');
612
624
  this.clearPingTimeout();
613
625
  if (this.pingInterval) {
614
- clearInterval(this.pingInterval);
626
+ CriticalTimers.clearInterval(this.pingInterval);
615
627
  }
616
628
  }
617
629
  }
@@ -9,7 +9,7 @@ import { TURNCheck } from './checks/turn';
9
9
  import { WebRTCCheck } from './checks/webrtc';
10
10
  import { WebSocketCheck } from './checks/websocket';
11
11
 
12
- export type { CheckInfo };
12
+ export type { CheckInfo, CheckStatus };
13
13
 
14
14
  export class ConnectionCheck extends (EventEmitter as new () => TypedEmitter<ConnectionCheckCallbacks>) {
15
15
  token: string;
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@ import RemoteTrackPublication from './room/track/RemoteTrackPublication';
16
16
  import RemoteVideoTrack from './room/track/RemoteVideoTrack';
17
17
  import type { ElementInfo } from './room/track/RemoteVideoTrack';
18
18
  import { TrackPublication } from './room/track/TrackPublication';
19
+ import CriticalTimers from './room/timers';
19
20
  import {
20
21
  getEmptyAudioStreamTrack,
21
22
  getEmptyVideoStreamTrack,
@@ -71,4 +72,5 @@ export {
71
72
  ConnectionQuality,
72
73
  ElementInfo,
73
74
  DefaultReconnectPolicy,
75
+ CriticalTimers,
74
76
  };
@@ -172,7 +172,7 @@ export const Timestamp = {
172
172
  declare var self: any | undefined;
173
173
  declare var window: any | undefined;
174
174
  declare var global: any | undefined;
175
- var globalThis: any = (() => {
175
+ var tsProtoGlobalThis: any = (() => {
176
176
  if (typeof globalThis !== "undefined") {
177
177
  return globalThis;
178
178
  }
@@ -202,7 +202,7 @@ export type Exact<P, I extends P> = P extends Builtin ? P
202
202
 
203
203
  function longToNumber(long: Long): number {
204
204
  if (long.gt(Number.MAX_SAFE_INTEGER)) {
205
- throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
205
+ throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
206
206
  }
207
207
  return long.toNumber();
208
208
  }