livekit-client 1.6.2 → 1.6.4

Sign up to get free protection for your applications and to get access to all the features.
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
  }