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.
- package/dist/livekit-client.esm.mjs +468 -140
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts +3 -3
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/connectionHelper/ConnectionCheck.d.ts +2 -2
- package/dist/src/connectionHelper/ConnectionCheck.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/proto/livekit_models.d.ts +53 -4
- package/dist/src/proto/livekit_models.d.ts.map +1 -1
- package/dist/src/proto/livekit_rtc.d.ts +650 -91
- package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +1 -0
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +2 -0
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/errors.d.ts +3 -0
- package/dist/src/room/errors.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +1 -3
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/Participant.d.ts +1 -1
- package/dist/src/room/participant/Participant.d.ts.map +1 -1
- package/dist/src/room/timers.d.ts +13 -0
- package/dist/src/room/timers.d.ts.map +1 -0
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/create.d.ts.map +1 -1
- package/dist/src/room/track/options.d.ts +2 -2
- package/dist/src/room/track/options.d.ts.map +1 -1
- package/dist/src/test/mocks.d.ts +1 -1
- package/dist/ts4.2/src/api/SignalClient.d.ts +3 -3
- package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +2 -2
- package/dist/ts4.2/src/index.d.ts +2 -1
- package/dist/ts4.2/src/proto/livekit_models.d.ts +59 -4
- package/dist/ts4.2/src/proto/livekit_rtc.d.ts +739 -120
- package/dist/ts4.2/src/room/PCTransport.d.ts +1 -0
- package/dist/ts4.2/src/room/RTCEngine.d.ts +2 -0
- package/dist/ts4.2/src/room/Room.d.ts +1 -1
- package/dist/ts4.2/src/room/errors.d.ts +3 -0
- package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +1 -3
- package/dist/ts4.2/src/room/participant/Participant.d.ts +1 -1
- package/dist/ts4.2/src/room/timers.d.ts +13 -0
- package/dist/ts4.2/src/room/track/options.d.ts +2 -2
- package/dist/ts4.2/src/test/mocks.d.ts +1 -1
- package/package.json +17 -17
- package/src/api/SignalClient.ts +33 -21
- package/src/connectionHelper/ConnectionCheck.ts +1 -1
- package/src/index.ts +2 -0
- package/src/proto/google/protobuf/timestamp.ts +2 -2
- package/src/proto/livekit_models.ts +158 -10
- package/src/proto/livekit_rtc.ts +205 -6
- package/src/room/PCTransport.ts +22 -6
- package/src/room/RTCEngine.ts +58 -45
- package/src/room/Room.ts +8 -10
- package/src/room/errors.ts +6 -0
- package/src/room/participant/LocalParticipant.ts +12 -17
- package/src/room/participant/Participant.ts +10 -2
- package/src/room/timers.ts +16 -0
- package/src/room/track/RemoteVideoTrack.ts +2 -1
- package/src/room/track/create.ts +6 -1
- package/src/room/track/options.ts +2 -2
package/src/room/Room.ts
CHANGED
@@ -44,6 +44,7 @@ import type Participant from './participant/Participant';
|
|
44
44
|
import type { ConnectionQuality } from './participant/Participant';
|
45
45
|
import RemoteParticipant from './participant/RemoteParticipant';
|
46
46
|
import RTCEngine from './RTCEngine';
|
47
|
+
import CriticalTimers from './timers';
|
47
48
|
import LocalAudioTrack from './track/LocalAudioTrack';
|
48
49
|
import LocalTrackPublication from './track/LocalTrackPublication';
|
49
50
|
import LocalVideoTrack from './track/LocalVideoTrack';
|
@@ -364,7 +365,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
364
365
|
}
|
365
366
|
|
366
367
|
// don't return until ICE connected
|
367
|
-
const connectTimeout = setTimeout(() => {
|
368
|
+
const connectTimeout = CriticalTimers.setTimeout(() => {
|
368
369
|
// timeout
|
369
370
|
this.recreateEngine();
|
370
371
|
this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
|
@@ -372,7 +373,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
372
373
|
}, this.connOptions.peerConnectionTimeout);
|
373
374
|
const abortHandler = () => {
|
374
375
|
log.warn('closing engine');
|
375
|
-
clearTimeout(connectTimeout);
|
376
|
+
CriticalTimers.clearTimeout(connectTimeout);
|
376
377
|
this.recreateEngine();
|
377
378
|
this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
|
378
379
|
reject(new ConnectionError('room connection has been cancelled'));
|
@@ -383,7 +384,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
383
384
|
this.abortController?.signal.addEventListener('abort', abortHandler);
|
384
385
|
|
385
386
|
this.engine.once(EngineEvent.Connected, () => {
|
386
|
-
clearTimeout(connectTimeout);
|
387
|
+
CriticalTimers.clearTimeout(connectTimeout);
|
387
388
|
this.abortController?.signal.removeEventListener('abort', abortHandler);
|
388
389
|
// also hook unload event
|
389
390
|
if (isWeb()) {
|
@@ -842,10 +843,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
842
843
|
private handleParticipantUpdates = (participantInfos: ParticipantInfo[]) => {
|
843
844
|
// handle changes to participant state, and send events
|
844
845
|
participantInfos.forEach((info) => {
|
845
|
-
if (
|
846
|
-
info.sid === this.localParticipant.sid ||
|
847
|
-
info.identity === this.localParticipant.identity
|
848
|
-
) {
|
846
|
+
if (info.identity === this.localParticipant.identity) {
|
849
847
|
this.localParticipant.updateInfo(info);
|
850
848
|
return;
|
851
849
|
}
|
@@ -1137,7 +1135,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
1137
1135
|
})
|
1138
1136
|
.on(
|
1139
1137
|
ParticipantEvent.ParticipantPermissionsChanged,
|
1140
|
-
(prevPermissions
|
1138
|
+
(prevPermissions?: ParticipantPermission) => {
|
1141
1139
|
this.emitWhenConnected(
|
1142
1140
|
RoomEvent.ParticipantPermissionsChanged,
|
1143
1141
|
prevPermissions,
|
@@ -1272,7 +1270,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
1272
1270
|
this.emit(RoomEvent.MediaDevicesError, e);
|
1273
1271
|
};
|
1274
1272
|
|
1275
|
-
private onLocalParticipantPermissionsChanged = (prevPermissions
|
1273
|
+
private onLocalParticipantPermissionsChanged = (prevPermissions?: ParticipantPermission) => {
|
1276
1274
|
this.emit(RoomEvent.ParticipantPermissionsChanged, prevPermissions, this.localParticipant);
|
1277
1275
|
};
|
1278
1276
|
|
@@ -1441,7 +1439,7 @@ export type RoomEventCallbacks = {
|
|
1441
1439
|
participant: RemoteParticipant | LocalParticipant,
|
1442
1440
|
) => void;
|
1443
1441
|
participantPermissionsChanged: (
|
1444
|
-
prevPermissions: ParticipantPermission,
|
1442
|
+
prevPermissions: ParticipantPermission | undefined,
|
1445
1443
|
participant: RemoteParticipant | LocalParticipant,
|
1446
1444
|
) => void;
|
1447
1445
|
activeSpeakersChanged: (speakers: Array<Participant>) => void;
|
package/src/room/errors.ts
CHANGED
@@ -25,6 +25,12 @@ export class ConnectionError extends LivekitError {
|
|
25
25
|
}
|
26
26
|
}
|
27
27
|
|
28
|
+
export class DeviceUnsupportedError extends LivekitError {
|
29
|
+
constructor(message?: string) {
|
30
|
+
super(21, message ?? 'device is unsupported');
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
28
34
|
export class TrackInvalidError extends LivekitError {
|
29
35
|
constructor(message?: string) {
|
30
36
|
super(20, message ?? 'track is invalid');
|
@@ -1,12 +1,7 @@
|
|
1
1
|
import 'webrtc-adapter';
|
2
2
|
import log from '../../logger';
|
3
3
|
import type { InternalRoomOptions } from '../../options';
|
4
|
-
import {
|
5
|
-
DataPacket,
|
6
|
-
DataPacket_Kind,
|
7
|
-
ParticipantInfo,
|
8
|
-
ParticipantPermission,
|
9
|
-
} from '../../proto/livekit_models';
|
4
|
+
import { DataPacket, DataPacket_Kind, ParticipantInfo } from '../../proto/livekit_models';
|
10
5
|
import {
|
11
6
|
AddTrackRequest,
|
12
7
|
DataChannelInfo,
|
@@ -15,7 +10,7 @@ import {
|
|
15
10
|
TrackPublishedResponse,
|
16
11
|
TrackUnpublishedResponse,
|
17
12
|
} from '../../proto/livekit_rtc';
|
18
|
-
import { TrackInvalidError, UnexpectedConnectionState } from '../errors';
|
13
|
+
import { DeviceUnsupportedError, TrackInvalidError, UnexpectedConnectionState } from '../errors';
|
19
14
|
import { EngineEvent, ParticipantEvent, TrackEvent } from '../events';
|
20
15
|
import type RTCEngine from '../RTCEngine';
|
21
16
|
import LocalAudioTrack from '../track/LocalAudioTrack';
|
@@ -168,16 +163,6 @@ export default class LocalParticipant extends Participant {
|
|
168
163
|
return this.setTrackEnabled(Track.Source.ScreenShare, enabled, options, publishOptions);
|
169
164
|
}
|
170
165
|
|
171
|
-
/** @internal */
|
172
|
-
setPermissions(permissions: ParticipantPermission): boolean {
|
173
|
-
const prevPermissions = this.permissions;
|
174
|
-
const changed = super.setPermissions(permissions);
|
175
|
-
if (changed && prevPermissions) {
|
176
|
-
this.emit(ParticipantEvent.ParticipantPermissionsChanged, prevPermissions);
|
177
|
-
}
|
178
|
-
return changed;
|
179
|
-
}
|
180
|
-
|
181
166
|
/**
|
182
167
|
* Enable or disable publishing for a track by source. This serves as a simple
|
183
168
|
* way to manage the common tracks (camera, mic, or screen share).
|
@@ -389,6 +374,11 @@ export default class LocalParticipant extends Participant {
|
|
389
374
|
};
|
390
375
|
}
|
391
376
|
}
|
377
|
+
|
378
|
+
if (navigator.mediaDevices.getDisplayMedia === undefined) {
|
379
|
+
throw new DeviceUnsupportedError('getDisplayMedia not supported');
|
380
|
+
}
|
381
|
+
|
392
382
|
const stream: MediaStream = await navigator.mediaDevices.getDisplayMedia({
|
393
383
|
audio: options.audio ?? false,
|
394
384
|
video: videoConstraints,
|
@@ -876,6 +866,11 @@ export default class LocalParticipant extends Participant {
|
|
876
866
|
|
877
867
|
/** @internal */
|
878
868
|
updateInfo(info: ParticipantInfo) {
|
869
|
+
if (info.sid !== this.sid) {
|
870
|
+
// drop updates that specify a wrong sid.
|
871
|
+
// the sid for local participant is only explicitly set on join and full reconnect
|
872
|
+
return;
|
873
|
+
}
|
879
874
|
super.updateInfo(info);
|
880
875
|
|
881
876
|
// reconcile track mute status.
|
@@ -173,14 +173,22 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
|
|
173
173
|
|
174
174
|
/** @internal */
|
175
175
|
setPermissions(permissions: ParticipantPermission): boolean {
|
176
|
+
const prevPermissions = this.permissions;
|
176
177
|
const changed =
|
177
178
|
permissions.canPublish !== this.permissions?.canPublish ||
|
178
179
|
permissions.canSubscribe !== this.permissions?.canSubscribe ||
|
179
180
|
permissions.canPublishData !== this.permissions?.canPublishData ||
|
180
181
|
permissions.hidden !== this.permissions?.hidden ||
|
181
|
-
permissions.recorder !== this.permissions?.recorder
|
182
|
+
permissions.recorder !== this.permissions?.recorder ||
|
183
|
+
permissions.canPublishSources.length !== this.permissions.canPublishSources.length ||
|
184
|
+
permissions.canPublishSources.some(
|
185
|
+
(value, index) => value !== this.permissions?.canPublishSources[index],
|
186
|
+
);
|
182
187
|
this.permissions = permissions;
|
183
188
|
|
189
|
+
if (changed) {
|
190
|
+
this.emit(ParticipantEvent.ParticipantPermissionsChanged, prevPermissions);
|
191
|
+
}
|
184
192
|
return changed;
|
185
193
|
}
|
186
194
|
|
@@ -257,7 +265,7 @@ export type ParticipantEventCallbacks = {
|
|
257
265
|
status: TrackPublication.PermissionStatus,
|
258
266
|
) => void;
|
259
267
|
mediaDevicesError: (error: Error) => void;
|
260
|
-
participantPermissionsChanged: (prevPermissions
|
268
|
+
participantPermissionsChanged: (prevPermissions?: ParticipantPermission) => void;
|
261
269
|
trackSubscriptionStatusChanged: (
|
262
270
|
publication: RemoteTrackPublication,
|
263
271
|
status: TrackPublication.SubscriptionStatus,
|
@@ -0,0 +1,16 @@
|
|
1
|
+
/**
|
2
|
+
* Timers that can be overridden with platform specific implementations
|
3
|
+
* that ensure that they are fired. These should be used when it is critical
|
4
|
+
* that the timer fires on time.
|
5
|
+
*/
|
6
|
+
export default class CriticalTimers {
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
8
|
+
static setTimeout = (...args: Parameters<typeof setTimeout>) => setTimeout(...args);
|
9
|
+
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
11
|
+
static setInterval = (...args: Parameters<typeof setInterval>) => setInterval(...args);
|
12
|
+
|
13
|
+
static clearTimeout = (...args: Parameters<typeof clearTimeout>) => clearTimeout(...args);
|
14
|
+
|
15
|
+
static clearInterval = (...args: Parameters<typeof clearInterval>) => clearInterval(...args);
|
16
|
+
}
|
@@ -2,6 +2,7 @@ import { debounce } from 'ts-debounce';
|
|
2
2
|
import log from '../../logger';
|
3
3
|
import { TrackEvent } from '../events';
|
4
4
|
import { computeBitrate, VideoReceiverStats } from '../stats';
|
5
|
+
import CriticalTimers from '../timers';
|
5
6
|
import { getIntersectionObserver, getResizeObserver, ObservableMediaElement } from '../utils';
|
6
7
|
import RemoteTrack from './RemoteTrack';
|
7
8
|
import { attachToElement, detachTrack, Track } from './Track';
|
@@ -233,7 +234,7 @@ export default class RemoteVideoTrack extends RemoteTrack {
|
|
233
234
|
|
234
235
|
if (!isVisible && Date.now() - lastVisibilityChange < REACTION_DELAY) {
|
235
236
|
// delay hidden events
|
236
|
-
setTimeout(() => {
|
237
|
+
CriticalTimers.setTimeout(() => {
|
237
238
|
this.updateVisibility();
|
238
239
|
}, REACTION_DELAY);
|
239
240
|
return;
|
package/src/room/track/create.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import DeviceManager from '../DeviceManager';
|
2
|
-
import { TrackInvalidError } from '../errors';
|
2
|
+
import { DeviceUnsupportedError, TrackInvalidError } from '../errors';
|
3
3
|
import { mediaTrackToLocalTrack } from '../participant/publishUtils';
|
4
4
|
import { audioDefaults, videoDefaults } from '../defaults';
|
5
5
|
import LocalAudioTrack from './LocalAudioTrack';
|
@@ -114,6 +114,11 @@ export async function createLocalScreenTracks(
|
|
114
114
|
height: options.resolution.height,
|
115
115
|
};
|
116
116
|
}
|
117
|
+
|
118
|
+
if (navigator.mediaDevices.getDisplayMedia === undefined) {
|
119
|
+
throw new DeviceUnsupportedError('getDisplayMedia not supported');
|
120
|
+
}
|
121
|
+
|
117
122
|
// typescript definition is missing getDisplayMedia: https://github.com/microsoft/TypeScript/issues/33232
|
118
123
|
// @ts-ignore
|
119
124
|
const stream: MediaStream = await navigator.mediaDevices.getDisplayMedia({
|
@@ -232,9 +232,9 @@ export interface AudioPreset {
|
|
232
232
|
const codecs = ['vp8', 'h264', 'av1'] as const;
|
233
233
|
const backupCodecs = ['vp8', 'h264'] as const;
|
234
234
|
|
235
|
-
export type VideoCodec = typeof codecs[number];
|
235
|
+
export type VideoCodec = (typeof codecs)[number];
|
236
236
|
|
237
|
-
export type BackupVideoCodec = typeof backupCodecs[number];
|
237
|
+
export type BackupVideoCodec = (typeof backupCodecs)[number];
|
238
238
|
|
239
239
|
export function isBackupCodec(codec: string): codec is BackupVideoCodec {
|
240
240
|
return !!backupCodecs.find((backup) => backup === codec);
|