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.
Files changed (39) hide show
  1. package/dist/livekit-client.esm.mjs +91 -50
  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/proto/livekit_models_pb.d.ts +11 -1
  6. package/dist/src/proto/livekit_models_pb.d.ts.map +1 -1
  7. package/dist/src/room/RTCEngine.d.ts +4 -1
  8. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  9. package/dist/src/room/Room.d.ts.map +1 -1
  10. package/dist/src/room/events.d.ts +4 -1
  11. package/dist/src/room/events.d.ts.map +1 -1
  12. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  13. package/dist/src/room/participant/Participant.d.ts +6 -0
  14. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  15. package/dist/src/room/stats.d.ts +1 -0
  16. package/dist/src/room/stats.d.ts.map +1 -1
  17. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  18. package/dist/src/room/track/Track.d.ts +0 -3
  19. package/dist/src/room/track/Track.d.ts.map +1 -1
  20. package/dist/src/version.d.ts +1 -1
  21. package/dist/ts4.2/src/proto/livekit_models_pb.d.ts +11 -1
  22. package/dist/ts4.2/src/room/RTCEngine.d.ts +4 -0
  23. package/dist/ts4.2/src/room/events.d.ts +4 -1
  24. package/dist/ts4.2/src/room/participant/Participant.d.ts +6 -0
  25. package/dist/ts4.2/src/room/stats.d.ts +1 -0
  26. package/dist/ts4.2/src/room/track/Track.d.ts +0 -3
  27. package/dist/ts4.2/src/version.d.ts +1 -1
  28. package/package.json +2 -2
  29. package/src/proto/livekit_models_pb.ts +15 -1
  30. package/src/proto/livekit_rtc_pb.ts +1 -1
  31. package/src/room/RTCEngine.ts +13 -0
  32. package/src/room/Room.ts +26 -8
  33. package/src/room/events.ts +3 -0
  34. package/src/room/participant/LocalParticipant.ts +4 -6
  35. package/src/room/participant/Participant.ts +11 -0
  36. package/src/room/stats.ts +2 -0
  37. package/src/room/track/RemoteVideoTrack.ts +8 -0
  38. package/src/room/track/Track.ts +34 -48
  39. 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.3";
10589
+ var version$1 = "1.15.5";
10569
10590
 
10570
10591
  const version = version$1;
10571
- const protocolVersion = 10;
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
- if (allMediaStreamTracks.some(tr => tr.kind === 'audio')) {
13033
- // manually play audio to detect audio playback status
13034
- element.play().then(() => {
13035
- this.emit(TrackEvent.AudioPlaybackStarted);
13036
- }).catch(e => {
13037
- // If audio playback isn't allowed make sure we still play back the video
13038
- if (element && allMediaStreamTracks.some(tr => tr.kind === 'video') && e.name === 'NotAllowedError') {
13039
- element.muted = true;
13040
- element.play().catch(() => {
13041
- // catch for Safari, exceeded options at this point to automatically play the media element
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, we watch the `suspended` event do deal with these failures */
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.client.onRemoteMuteChanged = (trackSid, muted) => {
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.client.onSubscribedQualityUpdate = this.handleSubscribedQualityUpdate;
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
- el.play().catch(e => {
21816
- if (e.name === 'NotAllowedError') {
21817
- livekitLogger.warn('Resuming video playback failed, make sure you call `startVideo` directly in a user gesture handler');
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) {