livekit-client 1.15.3 → 1.15.5
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/livekit-client.esm.mjs +91 -50
- 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/proto/livekit_models_pb.d.ts +11 -1
- package/dist/src/proto/livekit_models_pb.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +4 -1
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +4 -1
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/Participant.d.ts +6 -0
- package/dist/src/room/participant/Participant.d.ts.map +1 -1
- package/dist/src/room/stats.d.ts +1 -0
- package/dist/src/room/stats.d.ts.map +1 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +0 -3
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/ts4.2/src/proto/livekit_models_pb.d.ts +11 -1
- package/dist/ts4.2/src/room/RTCEngine.d.ts +4 -0
- package/dist/ts4.2/src/room/events.d.ts +4 -1
- package/dist/ts4.2/src/room/participant/Participant.d.ts +6 -0
- package/dist/ts4.2/src/room/stats.d.ts +1 -0
- package/dist/ts4.2/src/room/track/Track.d.ts +0 -3
- package/dist/ts4.2/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/src/proto/livekit_models_pb.ts +15 -1
- package/src/proto/livekit_rtc_pb.ts +1 -1
- package/src/room/RTCEngine.ts +13 -0
- package/src/room/Room.ts +26 -8
- package/src/room/events.ts +3 -0
- package/src/room/participant/LocalParticipant.ts +4 -6
- package/src/room/participant/Participant.ts +11 -0
- package/src/room/stats.ts +2 -0
- package/src/room/track/RemoteVideoTrack.ts +8 -0
- package/src/room/track/Track.ts +34 -48
- package/src/version.ts +1 -1
@@ -3761,6 +3761,10 @@ var ConnectionQuality$1;
|
|
3761
3761
|
* @generated from enum value: EXCELLENT = 2;
|
3762
3762
|
*/
|
3763
3763
|
ConnectionQuality[ConnectionQuality["EXCELLENT"] = 2] = "EXCELLENT";
|
3764
|
+
/**
|
3765
|
+
* @generated from enum value: LOST = 3;
|
3766
|
+
*/
|
3767
|
+
ConnectionQuality[ConnectionQuality["LOST"] = 3] = "LOST";
|
3764
3768
|
})(ConnectionQuality$1 || (ConnectionQuality$1 = {}));
|
3765
3769
|
// Retrieve enum metadata with: proto3.getEnumType(ConnectionQuality)
|
3766
3770
|
proto3.util.setEnumType(ConnectionQuality$1, "livekit.ConnectionQuality", [{
|
@@ -3772,6 +3776,9 @@ proto3.util.setEnumType(ConnectionQuality$1, "livekit.ConnectionQuality", [{
|
|
3772
3776
|
}, {
|
3773
3777
|
no: 2,
|
3774
3778
|
name: "EXCELLENT"
|
3779
|
+
}, {
|
3780
|
+
no: 3,
|
3781
|
+
name: "LOST"
|
3775
3782
|
}]);
|
3776
3783
|
/**
|
3777
3784
|
* @generated from enum livekit.ClientConfigSetting
|
@@ -4203,6 +4210,12 @@ class ParticipantPermission extends Message {
|
|
4203
4210
|
* @generated from field: bool can_update_metadata = 10;
|
4204
4211
|
*/
|
4205
4212
|
this.canUpdateMetadata = false;
|
4213
|
+
/**
|
4214
|
+
* indicates that participant is an agent
|
4215
|
+
*
|
4216
|
+
* @generated from field: bool agent = 11;
|
4217
|
+
*/
|
4218
|
+
this.agent = false;
|
4206
4219
|
proto3.util.initPartial(data, this);
|
4207
4220
|
}
|
4208
4221
|
static fromBinary(bytes, options) {
|
@@ -4256,6 +4269,11 @@ ParticipantPermission.fields = proto3.util.newFieldList(() => [{
|
|
4256
4269
|
name: "can_update_metadata",
|
4257
4270
|
kind: "scalar",
|
4258
4271
|
T: 8 /* ScalarType.BOOL */
|
4272
|
+
}, {
|
4273
|
+
no: 11,
|
4274
|
+
name: "agent",
|
4275
|
+
kind: "scalar",
|
4276
|
+
T: 8 /* ScalarType.BOOL */
|
4259
4277
|
}]);
|
4260
4278
|
/**
|
4261
4279
|
* @generated from message livekit.ParticipantInfo
|
@@ -10396,6 +10414,9 @@ var EngineEvent;
|
|
10396
10414
|
EngineEvent["ConnectionQualityUpdate"] = "connectionQualityUpdate";
|
10397
10415
|
EngineEvent["SubscriptionError"] = "subscriptionError";
|
10398
10416
|
EngineEvent["SubscriptionPermissionUpdate"] = "subscriptionPermissionUpdate";
|
10417
|
+
EngineEvent["RemoteMute"] = "remoteMute";
|
10418
|
+
EngineEvent["SubscribedQualityUpdate"] = "subscribedQualityUpdate";
|
10419
|
+
EngineEvent["LocalTrackUnpublished"] = "localTrackUnpublished";
|
10399
10420
|
})(EngineEvent || (EngineEvent = {}));
|
10400
10421
|
var TrackEvent;
|
10401
10422
|
(function (TrackEvent) {
|
@@ -10565,10 +10586,10 @@ function getMatch(exp, ua) {
|
|
10565
10586
|
return match && match.length >= id && match[id] || '';
|
10566
10587
|
}
|
10567
10588
|
|
10568
|
-
var version$1 = "1.15.
|
10589
|
+
var version$1 = "1.15.5";
|
10569
10590
|
|
10570
10591
|
const version = version$1;
|
10571
|
-
const protocolVersion =
|
10592
|
+
const protocolVersion = 11;
|
10572
10593
|
|
10573
10594
|
/**
|
10574
10595
|
* Timers that can be overridden with platform specific implementations
|
@@ -12957,21 +12978,6 @@ class Track extends eventsExports.EventEmitter {
|
|
12957
12978
|
this.handleAppVisibilityChanged();
|
12958
12979
|
}
|
12959
12980
|
};
|
12960
|
-
this.handleElementSuspended = () => {
|
12961
|
-
this.debouncedPlaybackStateChange(false);
|
12962
|
-
};
|
12963
|
-
this.handleElementPlay = () => {
|
12964
|
-
this.debouncedPlaybackStateChange(true);
|
12965
|
-
};
|
12966
|
-
this.debouncedPlaybackStateChange = r(allowed => {
|
12967
|
-
// we debounce this as Safari triggers both `playing` and `suspend` shortly after one another
|
12968
|
-
// in order not to raise the wrong event, we debounce the call to make sure we only emit the correct status
|
12969
|
-
if (this.kind === Track.Kind.Audio) {
|
12970
|
-
this.emit(allowed ? TrackEvent.AudioPlaybackStarted : TrackEvent.AudioPlaybackFailed);
|
12971
|
-
} else if (this.kind === Track.Kind.Video) {
|
12972
|
-
this.emit(allowed ? TrackEvent.VideoPlaybackStarted : TrackEvent.VideoPlaybackFailed);
|
12973
|
-
}
|
12974
|
-
}, 300);
|
12975
12981
|
this.setMaxListeners(100);
|
12976
12982
|
this.kind = kind;
|
12977
12983
|
this._mediaStreamTrack = mediaTrack;
|
@@ -13019,9 +13025,6 @@ class Track extends eventsExports.EventEmitter {
|
|
13019
13025
|
}
|
13020
13026
|
if (!this.attachedElements.includes(element)) {
|
13021
13027
|
this.attachedElements.push(element);
|
13022
|
-
// listen to suspend events in order to detect auto playback issues
|
13023
|
-
element.addEventListener('suspend', this.handleElementSuspended);
|
13024
|
-
element.addEventListener('playing', this.handleElementPlay);
|
13025
13028
|
}
|
13026
13029
|
// even if we believe it's already attached to the element, it's possible
|
13027
13030
|
// the element's srcObject was set to something else out of band.
|
@@ -13029,20 +13032,27 @@ class Track extends eventsExports.EventEmitter {
|
|
13029
13032
|
attachToElement(this.mediaStreamTrack, element);
|
13030
13033
|
// handle auto playback failures
|
13031
13034
|
const allMediaStreamTracks = element.srcObject.getTracks();
|
13032
|
-
|
13033
|
-
|
13034
|
-
|
13035
|
-
|
13036
|
-
|
13037
|
-
|
13038
|
-
|
13039
|
-
|
13040
|
-
|
13041
|
-
|
13042
|
-
|
13043
|
-
|
13044
|
-
}
|
13045
|
-
|
13035
|
+
const hasAudio = allMediaStreamTracks.some(tr => tr.kind === 'audio');
|
13036
|
+
// manually play media to detect auto playback status
|
13037
|
+
element.play().then(() => {
|
13038
|
+
this.emit(hasAudio ? TrackEvent.AudioPlaybackStarted : TrackEvent.VideoPlaybackStarted);
|
13039
|
+
}).catch(e => {
|
13040
|
+
if (e.name === 'NotAllowedError') {
|
13041
|
+
this.emit(hasAudio ? TrackEvent.AudioPlaybackFailed : TrackEvent.VideoPlaybackFailed, e);
|
13042
|
+
} else if (e.name === 'AbortError') {
|
13043
|
+
// commonly triggered by another `play` request, only log for debugging purposes
|
13044
|
+
livekitLogger.debug("".concat(hasAudio ? 'audio' : 'video', " playback aborted, likely due to new play request"));
|
13045
|
+
} else {
|
13046
|
+
livekitLogger.warn("could not playback ".concat(hasAudio ? 'audio' : 'video'), e);
|
13047
|
+
}
|
13048
|
+
// If audio playback isn't allowed make sure we still play back the video
|
13049
|
+
if (hasAudio && element && allMediaStreamTracks.some(tr => tr.kind === 'video') && e.name === 'NotAllowedError') {
|
13050
|
+
element.muted = true;
|
13051
|
+
element.play().catch(() => {
|
13052
|
+
// catch for Safari, exceeded options at this point to automatically play the media element
|
13053
|
+
});
|
13054
|
+
}
|
13055
|
+
});
|
13046
13056
|
this.emit(TrackEvent.ElementAttached, element);
|
13047
13057
|
return element;
|
13048
13058
|
}
|
@@ -13055,8 +13065,6 @@ class Track extends eventsExports.EventEmitter {
|
|
13055
13065
|
if (idx >= 0) {
|
13056
13066
|
this.attachedElements.splice(idx, 1);
|
13057
13067
|
this.recycleElement(element);
|
13058
|
-
element.removeEventListener('suspend', this.handleElementSuspended);
|
13059
|
-
element.removeEventListener('playing', this.handleElementPlay);
|
13060
13068
|
this.emit(TrackEvent.ElementDetached, element);
|
13061
13069
|
}
|
13062
13070
|
return element;
|
@@ -13066,8 +13074,6 @@ class Track extends eventsExports.EventEmitter {
|
|
13066
13074
|
detachTrack(this.mediaStreamTrack, elm);
|
13067
13075
|
detached.push(elm);
|
13068
13076
|
this.recycleElement(elm);
|
13069
|
-
elm.removeEventListener('suspend', this.handleElementSuspended);
|
13070
|
-
elm.removeEventListener('playing', this.handleElementPlay);
|
13071
13077
|
this.emit(TrackEvent.ElementDetached, elm);
|
13072
13078
|
});
|
13073
13079
|
// remove all tracks
|
@@ -13176,7 +13182,7 @@ function attachToElement(track, element) {
|
|
13176
13182
|
// when the window is backgrounded before the first frame is drawn
|
13177
13183
|
// manually calling play here seems to fix that
|
13178
13184
|
element.play().catch(() => {
|
13179
|
-
/** do nothing
|
13185
|
+
/** do nothing */
|
13180
13186
|
});
|
13181
13187
|
}, 0);
|
13182
13188
|
}
|
@@ -17242,6 +17248,12 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17242
17248
|
this.client.onTokenRefresh = token => {
|
17243
17249
|
this.token = token;
|
17244
17250
|
};
|
17251
|
+
this.client.onRemoteMuteChanged = (trackSid, muted) => {
|
17252
|
+
this.emit(EngineEvent.RemoteMute, trackSid, muted);
|
17253
|
+
};
|
17254
|
+
this.client.onSubscribedQualityUpdate = update => {
|
17255
|
+
this.emit(EngineEvent.SubscribedQualityUpdate, update);
|
17256
|
+
};
|
17245
17257
|
this.client.onClose = () => {
|
17246
17258
|
this.handleDisconnect('signal', ReconnectReason.RR_SIGNAL_DISCONNECTED);
|
17247
17259
|
};
|
@@ -19369,8 +19381,11 @@ class RemoteVideoTrack extends RemoteTrack {
|
|
19369
19381
|
}
|
19370
19382
|
const stats = yield this.receiver.getStats();
|
19371
19383
|
let receiverStats;
|
19384
|
+
let codecID = '';
|
19385
|
+
let codecs = new Map();
|
19372
19386
|
stats.forEach(v => {
|
19373
19387
|
if (v.type === 'inbound-rtp') {
|
19388
|
+
codecID = v.codecId;
|
19374
19389
|
receiverStats = {
|
19375
19390
|
type: 'video',
|
19376
19391
|
framesDecoded: v.framesDecoded,
|
@@ -19388,8 +19403,13 @@ class RemoteVideoTrack extends RemoteTrack {
|
|
19388
19403
|
bytesReceived: v.bytesReceived,
|
19389
19404
|
decoderImplementation: v.decoderImplementation
|
19390
19405
|
};
|
19406
|
+
} else if (v.type === 'codec') {
|
19407
|
+
codecs.set(v.id, v);
|
19391
19408
|
}
|
19392
19409
|
});
|
19410
|
+
if (receiverStats && codecID !== '' && codecs.get(codecID)) {
|
19411
|
+
receiverStats.mimeType = codecs.get(codecID).mimeType;
|
19412
|
+
}
|
19393
19413
|
return receiverStats;
|
19394
19414
|
});
|
19395
19415
|
}
|
@@ -19727,6 +19747,11 @@ var ConnectionQuality;
|
|
19727
19747
|
ConnectionQuality["Excellent"] = "excellent";
|
19728
19748
|
ConnectionQuality["Good"] = "good";
|
19729
19749
|
ConnectionQuality["Poor"] = "poor";
|
19750
|
+
/**
|
19751
|
+
* Indicates that a participant has temporarily (or permanently) lost connection to LiveKit.
|
19752
|
+
* For permanent disconnection a `ParticipantDisconnected` event will be emitted after a timeout
|
19753
|
+
*/
|
19754
|
+
ConnectionQuality["Lost"] = "lost";
|
19730
19755
|
ConnectionQuality["Unknown"] = "unknown";
|
19731
19756
|
})(ConnectionQuality || (ConnectionQuality = {}));
|
19732
19757
|
function qualityFromProto(q) {
|
@@ -19737,6 +19762,8 @@ function qualityFromProto(q) {
|
|
19737
19762
|
return ConnectionQuality.Good;
|
19738
19763
|
case ConnectionQuality$1.POOR:
|
19739
19764
|
return ConnectionQuality.Poor;
|
19765
|
+
case ConnectionQuality$1.LOST:
|
19766
|
+
return ConnectionQuality.Lost;
|
19740
19767
|
default:
|
19741
19768
|
return ConnectionQuality.Unknown;
|
19742
19769
|
}
|
@@ -19745,6 +19772,10 @@ class Participant extends eventsExports.EventEmitter {
|
|
19745
19772
|
get isEncrypted() {
|
19746
19773
|
return this.tracks.size > 0 && Array.from(this.tracks.values()).every(tr => tr.isEncrypted);
|
19747
19774
|
}
|
19775
|
+
get isAgent() {
|
19776
|
+
var _a, _b;
|
19777
|
+
return (_b = (_a = this.permissions) === null || _a === void 0 ? void 0 : _a.agent) !== null && _b !== void 0 ? _b : false;
|
19778
|
+
}
|
19748
19779
|
/** @internal */
|
19749
19780
|
constructor(sid, identity, name, metadata) {
|
19750
19781
|
super();
|
@@ -20635,7 +20666,7 @@ class LocalParticipant extends Participant {
|
|
20635
20666
|
*/
|
20636
20667
|
setupEngine(engine) {
|
20637
20668
|
this.engine = engine;
|
20638
|
-
this.engine.
|
20669
|
+
this.engine.on(EngineEvent.RemoteMute, (trackSid, muted) => {
|
20639
20670
|
const pub = this.tracks.get(trackSid);
|
20640
20671
|
if (!pub || !pub.track) {
|
20641
20672
|
return;
|
@@ -20645,10 +20676,8 @@ class LocalParticipant extends Participant {
|
|
20645
20676
|
} else {
|
20646
20677
|
pub.unmute();
|
20647
20678
|
}
|
20648
|
-
};
|
20649
|
-
this.engine.
|
20650
|
-
this.engine.client.onLocalTrackUnpublished = this.handleLocalTrackUnpublished;
|
20651
|
-
this.engine.on(EngineEvent.Connected, this.handleReconnected).on(EngineEvent.SignalRestarted, this.handleReconnected).on(EngineEvent.SignalResumed, this.handleReconnected).on(EngineEvent.Restarting, this.handleReconnecting).on(EngineEvent.Resuming, this.handleReconnecting).on(EngineEvent.Disconnected, this.handleDisconnected);
|
20679
|
+
});
|
20680
|
+
this.engine.on(EngineEvent.Connected, this.handleReconnected).on(EngineEvent.SignalRestarted, this.handleReconnected).on(EngineEvent.SignalResumed, this.handleReconnected).on(EngineEvent.Restarting, this.handleReconnecting).on(EngineEvent.Resuming, this.handleReconnecting).on(EngineEvent.LocalTrackUnpublished, this.handleLocalTrackUnpublished).on(EngineEvent.SubscribedQualityUpdate, this.handleSubscribedQualityUpdate).on(EngineEvent.Disconnected, this.handleDisconnected);
|
20652
20681
|
}
|
20653
20682
|
/**
|
20654
20683
|
* Sets and updates the metadata of the local participant.
|
@@ -21808,18 +21837,26 @@ class Room extends eventsExports.EventEmitter {
|
|
21808
21837
|
}
|
21809
21838
|
});
|
21810
21839
|
this.startVideo = () => __awaiter(this, void 0, void 0, function* () {
|
21840
|
+
const elements = [];
|
21811
21841
|
for (const p of this.participants.values()) {
|
21812
21842
|
p.videoTracks.forEach(tr => {
|
21813
21843
|
var _a;
|
21814
21844
|
(_a = tr.track) === null || _a === void 0 ? void 0 : _a.attachedElements.forEach(el => {
|
21815
|
-
|
21816
|
-
|
21817
|
-
|
21818
|
-
}
|
21819
|
-
});
|
21845
|
+
if (!elements.includes(el)) {
|
21846
|
+
elements.push(el);
|
21847
|
+
}
|
21820
21848
|
});
|
21821
21849
|
});
|
21822
21850
|
}
|
21851
|
+
yield Promise.all(elements.map(el => el.play())).then(() => {
|
21852
|
+
this.handleVideoPlaybackStarted();
|
21853
|
+
}).catch(e => {
|
21854
|
+
if (e.name === 'NotAllowedError') {
|
21855
|
+
this.handleVideoPlaybackFailed();
|
21856
|
+
} else {
|
21857
|
+
livekitLogger.warn('Resuming video playback failed, make sure you call `startVideo` directly in a user gesture handler');
|
21858
|
+
}
|
21859
|
+
});
|
21823
21860
|
});
|
21824
21861
|
this.handleRestarting = () => {
|
21825
21862
|
this.clearConnectionReconcile();
|
@@ -22126,7 +22163,7 @@ class Room extends eventsExports.EventEmitter {
|
|
22126
22163
|
this.localParticipant.activeDeviceMap.set('audioinput', unwrapConstraint(this.options.audioCaptureDefaults.deviceId));
|
22127
22164
|
}
|
22128
22165
|
if ((_a = this.options.audioOutput) === null || _a === void 0 ? void 0 : _a.deviceId) {
|
22129
|
-
this.switchActiveDevice('audiooutput', unwrapConstraint(this.options.audioOutput.deviceId));
|
22166
|
+
this.switchActiveDevice('audiooutput', unwrapConstraint(this.options.audioOutput.deviceId)).catch(e => livekitLogger.warn("Could not set audio output: ".concat(e.message)));
|
22130
22167
|
}
|
22131
22168
|
if (this.options.e2ee) {
|
22132
22169
|
this.setupE2EE();
|
@@ -22643,6 +22680,7 @@ class Room extends eventsExports.EventEmitter {
|
|
22643
22680
|
});
|
22644
22681
|
}
|
22645
22682
|
createParticipant(id, info) {
|
22683
|
+
var _a;
|
22646
22684
|
let participant;
|
22647
22685
|
if (info) {
|
22648
22686
|
participant = RemoteParticipant.fromParticipantInfo(this.engine.client, info);
|
@@ -22652,6 +22690,9 @@ class Room extends eventsExports.EventEmitter {
|
|
22652
22690
|
if (this.options.expWebAudioMix) {
|
22653
22691
|
participant.setAudioContext(this.audioContext);
|
22654
22692
|
}
|
22693
|
+
if ((_a = this.options.audioOutput) === null || _a === void 0 ? void 0 : _a.deviceId) {
|
22694
|
+
participant.setAudioOutput(this.options.audioOutput).catch(e => livekitLogger.warn("Could not set audio output: ".concat(e.message)));
|
22695
|
+
}
|
22655
22696
|
return participant;
|
22656
22697
|
}
|
22657
22698
|
getOrCreateParticipant(id, info) {
|