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.
- 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);
|