livekit-client 1.6.3 → 1.6.5
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/livekit-client.esm.mjs +418 -70
- 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 +13 -2
- 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/proto/livekit_models.d.ts +20 -3
- package/dist/src/proto/livekit_models.d.ts.map +1 -1
- package/dist/src/proto/livekit_rtc.d.ts +2565 -464
- package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
- 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/track/LocalAudioTrack.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 +13 -2
- package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +2 -2
- package/dist/ts4.2/src/proto/livekit_models.d.ts +24 -3
- package/dist/ts4.2/src/proto/livekit_rtc.d.ts +2775 -540
- 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/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 +46 -3
- package/src/connectionHelper/ConnectionCheck.ts +1 -1
- package/src/proto/google/protobuf/timestamp.ts +2 -2
- package/src/proto/livekit_models.ts +93 -9
- package/src/proto/livekit_rtc.ts +308 -6
- package/src/room/RTCEngine.ts +37 -16
- package/src/room/Room.ts +12 -11
- package/src/room/errors.ts +6 -0
- package/src/room/participant/LocalParticipant.ts +19 -20
- package/src/room/participant/Participant.ts +10 -2
- package/src/room/track/LocalAudioTrack.ts +5 -1
- package/src/room/track/create.ts +6 -1
- package/src/room/track/options.ts +2 -2
package/src/room/Room.ts
CHANGED
@@ -355,12 +355,16 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
355
355
|
} catch (err) {
|
356
356
|
this.recreateEngine();
|
357
357
|
this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
|
358
|
-
|
358
|
+
const resultingError = new ConnectionError(`could not establish signal connection`);
|
359
359
|
if (err instanceof Error) {
|
360
|
-
|
361
|
-
log.debug(`error trying to establish signal connection`, { error: err });
|
360
|
+
resultingError.message = `${resultingError.message}: ${err.message}`;
|
362
361
|
}
|
363
|
-
|
362
|
+
if (err instanceof ConnectionError) {
|
363
|
+
resultingError.reason = err.reason;
|
364
|
+
resultingError.status = err.status;
|
365
|
+
}
|
366
|
+
log.debug(`error trying to establish signal connection`, { error: err });
|
367
|
+
reject(resultingError);
|
364
368
|
return;
|
365
369
|
}
|
366
370
|
|
@@ -843,10 +847,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
843
847
|
private handleParticipantUpdates = (participantInfos: ParticipantInfo[]) => {
|
844
848
|
// handle changes to participant state, and send events
|
845
849
|
participantInfos.forEach((info) => {
|
846
|
-
if (
|
847
|
-
info.sid === this.localParticipant.sid ||
|
848
|
-
info.identity === this.localParticipant.identity
|
849
|
-
) {
|
850
|
+
if (info.identity === this.localParticipant.identity) {
|
850
851
|
this.localParticipant.updateInfo(info);
|
851
852
|
return;
|
852
853
|
}
|
@@ -1138,7 +1139,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
1138
1139
|
})
|
1139
1140
|
.on(
|
1140
1141
|
ParticipantEvent.ParticipantPermissionsChanged,
|
1141
|
-
(prevPermissions
|
1142
|
+
(prevPermissions?: ParticipantPermission) => {
|
1142
1143
|
this.emitWhenConnected(
|
1143
1144
|
RoomEvent.ParticipantPermissionsChanged,
|
1144
1145
|
prevPermissions,
|
@@ -1273,7 +1274,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
1273
1274
|
this.emit(RoomEvent.MediaDevicesError, e);
|
1274
1275
|
};
|
1275
1276
|
|
1276
|
-
private onLocalParticipantPermissionsChanged = (prevPermissions
|
1277
|
+
private onLocalParticipantPermissionsChanged = (prevPermissions?: ParticipantPermission) => {
|
1277
1278
|
this.emit(RoomEvent.ParticipantPermissionsChanged, prevPermissions, this.localParticipant);
|
1278
1279
|
};
|
1279
1280
|
|
@@ -1442,7 +1443,7 @@ export type RoomEventCallbacks = {
|
|
1442
1443
|
participant: RemoteParticipant | LocalParticipant,
|
1443
1444
|
) => void;
|
1444
1445
|
participantPermissionsChanged: (
|
1445
|
-
prevPermissions: ParticipantPermission,
|
1446
|
+
prevPermissions: ParticipantPermission | undefined,
|
1446
1447
|
participant: RemoteParticipant | LocalParticipant,
|
1447
1448
|
) => void;
|
1448
1449
|
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.
|
@@ -1004,7 +999,9 @@ export default class LocalParticipant extends Participant {
|
|
1004
999
|
// detect granted change after permissions were denied to try and resume then
|
1005
1000
|
currentPermissions.onchange = () => {
|
1006
1001
|
if (currentPermissions.state !== 'denied') {
|
1007
|
-
track.
|
1002
|
+
if (!track.isMuted) {
|
1003
|
+
track.restartTrack();
|
1004
|
+
}
|
1008
1005
|
currentPermissions.onchange = null;
|
1009
1006
|
}
|
1010
1007
|
};
|
@@ -1014,8 +1011,10 @@ export default class LocalParticipant extends Participant {
|
|
1014
1011
|
// permissions query fails for firefox, we continue and try to restart the track
|
1015
1012
|
}
|
1016
1013
|
}
|
1017
|
-
|
1018
|
-
|
1014
|
+
if (!track.isMuted) {
|
1015
|
+
log.debug('track ended, attempting to use a different device');
|
1016
|
+
await track.restartTrack();
|
1017
|
+
}
|
1019
1018
|
} catch (e) {
|
1020
1019
|
log.warn(`could not restart track, muting instead`);
|
1021
1020
|
await track.mute();
|
@@ -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,
|
@@ -53,7 +53,11 @@ export default class LocalAudioTrack extends LocalTrack {
|
|
53
53
|
|
54
54
|
async unmute(): Promise<LocalAudioTrack> {
|
55
55
|
await this.muteQueue.run(async () => {
|
56
|
-
if (
|
56
|
+
if (
|
57
|
+
this.source === Track.Source.Microphone &&
|
58
|
+
(this.stopOnMute || this._mediaStreamTrack.readyState === 'ended') &&
|
59
|
+
!this.isUserProvided
|
60
|
+
) {
|
57
61
|
log.debug('reacquiring mic track');
|
58
62
|
await this.restartTrack();
|
59
63
|
}
|
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);
|