livekit-client 2.5.0 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. package/README.md +4 -0
  2. package/dist/livekit-client.esm.mjs +268 -71
  3. package/dist/livekit-client.esm.mjs.map +1 -1
  4. package/dist/livekit-client.umd.js +1 -1
  5. package/dist/livekit-client.umd.js.map +1 -1
  6. package/dist/src/room/PCTransport.d.ts.map +1 -1
  7. package/dist/src/room/Room.d.ts +5 -0
  8. package/dist/src/room/Room.d.ts.map +1 -1
  9. package/dist/src/room/events.d.ts +10 -2
  10. package/dist/src/room/events.d.ts.map +1 -1
  11. package/dist/src/room/participant/LocalParticipant.d.ts +4 -1
  12. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  13. package/dist/src/room/participant/Participant.d.ts +1 -0
  14. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  15. package/dist/src/room/timers.d.ts +4 -4
  16. package/dist/src/room/timers.d.ts.map +1 -1
  17. package/dist/src/room/track/options.d.ts +1 -1
  18. package/dist/src/room/types.d.ts +2 -0
  19. package/dist/src/room/types.d.ts.map +1 -1
  20. package/dist/src/room/utils.d.ts +1 -1
  21. package/dist/src/room/utils.d.ts.map +1 -1
  22. package/dist/ts4.2/src/room/Room.d.ts +5 -0
  23. package/dist/ts4.2/src/room/events.d.ts +10 -2
  24. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +4 -1
  25. package/dist/ts4.2/src/room/participant/Participant.d.ts +1 -0
  26. package/dist/ts4.2/src/room/timers.d.ts +4 -4
  27. package/dist/ts4.2/src/room/track/options.d.ts +1 -1
  28. package/dist/ts4.2/src/room/types.d.ts +2 -0
  29. package/dist/ts4.2/src/room/utils.d.ts +1 -1
  30. package/package.json +2 -2
  31. package/src/room/PCTransport.ts +3 -1
  32. package/src/room/RTCEngine.ts +1 -1
  33. package/src/room/Room.ts +28 -1
  34. package/src/room/events.ts +10 -0
  35. package/src/room/participant/LocalParticipant.ts +112 -76
  36. package/src/room/participant/Participant.ts +1 -0
  37. package/src/room/timers.ts +15 -6
  38. package/src/room/track/LocalVideoTrack.test.ts +60 -0
  39. package/src/room/track/LocalVideoTrack.ts +1 -1
  40. package/src/room/track/options.ts +1 -1
  41. package/src/room/types.ts +2 -0
  42. package/src/room/utils.ts +10 -0
package/README.md CHANGED
@@ -75,6 +75,10 @@ import {
75
75
  RemoteTrackPublication,
76
76
  Room,
77
77
  RoomEvent,
78
+ VideoPresets,
79
+ Track,
80
+ LocalTrackPublication,
81
+ LocalParticipant
78
82
  } from 'livekit-client';
79
83
 
80
84
  // creates a new room with options
@@ -3397,6 +3397,122 @@ target => {
3397
3397
  }
3398
3398
  });
3399
3399
 
3400
+ // @generated by protoc-gen-es v1.10.0 with parameter "target=js+dts"
3401
+ // @generated from file livekit_metrics.proto (package livekit, syntax proto3)
3402
+ /* eslint-disable */
3403
+ // @ts-nocheck
3404
+
3405
+
3406
+ /**
3407
+ * @generated from message livekit.MetricsBatch
3408
+ */
3409
+ const MetricsBatch = /*@__PURE__*/proto3.makeMessageType("livekit.MetricsBatch", () => [{
3410
+ no: 1,
3411
+ name: "str_data",
3412
+ kind: "scalar",
3413
+ T: 9 /* ScalarType.STRING */,
3414
+ repeated: true
3415
+ }, {
3416
+ no: 2,
3417
+ name: "time_series",
3418
+ kind: "message",
3419
+ T: TimeSeriesMetric,
3420
+ repeated: true
3421
+ }, {
3422
+ no: 3,
3423
+ name: "events",
3424
+ kind: "message",
3425
+ T: EventMetric,
3426
+ repeated: true
3427
+ }]);
3428
+
3429
+ /**
3430
+ * @generated from message livekit.TimeSeriesMetric
3431
+ */
3432
+ const TimeSeriesMetric = /*@__PURE__*/proto3.makeMessageType("livekit.TimeSeriesMetric", () => [{
3433
+ no: 1,
3434
+ name: "label",
3435
+ kind: "scalar",
3436
+ T: 13 /* ScalarType.UINT32 */
3437
+ }, {
3438
+ no: 2,
3439
+ name: "participant_identity",
3440
+ kind: "scalar",
3441
+ T: 13 /* ScalarType.UINT32 */
3442
+ }, {
3443
+ no: 3,
3444
+ name: "track_sid",
3445
+ kind: "scalar",
3446
+ T: 13 /* ScalarType.UINT32 */
3447
+ }, {
3448
+ no: 4,
3449
+ name: "start_timestamp",
3450
+ kind: "scalar",
3451
+ T: 3 /* ScalarType.INT64 */
3452
+ }, {
3453
+ no: 5,
3454
+ name: "end_timestamp",
3455
+ kind: "scalar",
3456
+ T: 3 /* ScalarType.INT64 */
3457
+ }, {
3458
+ no: 6,
3459
+ name: "samples",
3460
+ kind: "message",
3461
+ T: MetricSample,
3462
+ repeated: true
3463
+ }]);
3464
+
3465
+ /**
3466
+ * @generated from message livekit.MetricSample
3467
+ */
3468
+ const MetricSample = /*@__PURE__*/proto3.makeMessageType("livekit.MetricSample", () => [{
3469
+ no: 1,
3470
+ name: "timestamp",
3471
+ kind: "scalar",
3472
+ T: 3 /* ScalarType.INT64 */
3473
+ }, {
3474
+ no: 2,
3475
+ name: "value",
3476
+ kind: "scalar",
3477
+ T: 2 /* ScalarType.FLOAT */
3478
+ }]);
3479
+
3480
+ /**
3481
+ * @generated from message livekit.EventMetric
3482
+ */
3483
+ const EventMetric = /*@__PURE__*/proto3.makeMessageType("livekit.EventMetric", () => [{
3484
+ no: 1,
3485
+ name: "label",
3486
+ kind: "scalar",
3487
+ T: 13 /* ScalarType.UINT32 */
3488
+ }, {
3489
+ no: 2,
3490
+ name: "participant_identity",
3491
+ kind: "scalar",
3492
+ T: 13 /* ScalarType.UINT32 */
3493
+ }, {
3494
+ no: 3,
3495
+ name: "track_sid",
3496
+ kind: "scalar",
3497
+ T: 13 /* ScalarType.UINT32 */
3498
+ }, {
3499
+ no: 4,
3500
+ name: "start_timestamp",
3501
+ kind: "scalar",
3502
+ T: 3 /* ScalarType.INT64 */
3503
+ }, {
3504
+ no: 5,
3505
+ name: "end_timestamp",
3506
+ kind: "scalar",
3507
+ T: 3 /* ScalarType.INT64 */,
3508
+ opt: true
3509
+ }, {
3510
+ no: 6,
3511
+ name: "metadata",
3512
+ kind: "scalar",
3513
+ T: 9 /* ScalarType.STRING */
3514
+ }]);
3515
+
3400
3516
  // Copyright 2023 LiveKit, Inc.
3401
3517
  //
3402
3518
  // Licensed under the Apache License, Version 2.0 (the "License");
@@ -3719,6 +3835,11 @@ const ParticipantPermission = /*@__PURE__*/proto3.makeMessageType("livekit.Parti
3719
3835
  name: "agent",
3720
3836
  kind: "scalar",
3721
3837
  T: 8 /* ScalarType.BOOL */
3838
+ }, {
3839
+ no: 12,
3840
+ name: "can_subscribe_metrics",
3841
+ kind: "scalar",
3842
+ T: 8 /* ScalarType.BOOL */
3722
3843
  }]);
3723
3844
 
3724
3845
  /**
@@ -4058,6 +4179,12 @@ const DataPacket = /*@__PURE__*/proto3.makeMessageType("livekit.DataPacket", ()
4058
4179
  kind: "message",
4059
4180
  T: Transcription,
4060
4181
  oneof: "value"
4182
+ }, {
4183
+ no: 8,
4184
+ name: "metrics",
4185
+ kind: "message",
4186
+ T: MetricsBatch,
4187
+ oneof: "value"
4061
4188
  }]);
4062
4189
 
4063
4190
  /**
@@ -4964,6 +5091,17 @@ const JoinResponse = /*@__PURE__*/proto3.makeMessageType("livekit.JoinResponse",
4964
5091
  name: "sif_trailer",
4965
5092
  kind: "scalar",
4966
5093
  T: 12 /* ScalarType.BYTES */
5094
+ }, {
5095
+ no: 14,
5096
+ name: "enabled_publish_codecs",
5097
+ kind: "message",
5098
+ T: Codec,
5099
+ repeated: true
5100
+ }, {
5101
+ no: 15,
5102
+ name: "fast_publish",
5103
+ kind: "scalar",
5104
+ T: 8 /* ScalarType.BOOL */
4967
5105
  }]);
4968
5106
 
4969
5107
  /**
@@ -10182,6 +10320,10 @@ var RoomEvent;
10182
10320
  * args: (kind: MediaDeviceKind, deviceId: string)
10183
10321
  */
10184
10322
  RoomEvent["ActiveDeviceChanged"] = "activeDeviceChanged";
10323
+ /**
10324
+ * fired when the first remote participant has subscribed to the localParticipant's track
10325
+ */
10326
+ RoomEvent["LocalTrackSubscribed"] = "localTrackSubscribed";
10185
10327
  })(RoomEvent || (RoomEvent = {}));
10186
10328
  var ParticipantEvent;
10187
10329
  (function (ParticipantEvent) {
@@ -10345,6 +10487,10 @@ var ParticipantEvent;
10345
10487
  * When a participant's attributes changed, this event will be emitted with the changed attributes
10346
10488
  */
10347
10489
  ParticipantEvent["AttributesChanged"] = "attributesChanged";
10490
+ /**
10491
+ * fired on local participant only, when the first remote participant has subscribed to the track specified in the payload
10492
+ */
10493
+ ParticipantEvent["LocalTrackSubscribed"] = "localTrackSubscribed";
10348
10494
  })(ParticipantEvent || (ParticipantEvent = {}));
10349
10495
  /** @internal */
10350
10496
  var EngineEvent;
@@ -10568,7 +10714,7 @@ function getOSVersion(ua) {
10568
10714
  return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
10569
10715
  }
10570
10716
 
10571
- var version$1 = "2.5.0";
10717
+ var version$1 = "2.5.1";
10572
10718
 
10573
10719
  const version = version$1;
10574
10720
  const protocolVersion = 15;
@@ -10579,12 +10725,12 @@ const protocolVersion = 15;
10579
10725
  * that the timer fires on time.
10580
10726
  */
10581
10727
  class CriticalTimers {}
10582
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
10583
10728
  CriticalTimers.setTimeout = function () {
10584
10729
  return setTimeout(...arguments);
10585
10730
  };
10731
+ CriticalTimers.setInterval =
10586
10732
  // eslint-disable-next-line @typescript-eslint/no-implied-eval
10587
- CriticalTimers.setInterval = function () {
10733
+ function () {
10588
10734
  return setInterval(...arguments);
10589
10735
  };
10590
10736
  CriticalTimers.clearTimeout = function () {
@@ -11696,7 +11842,7 @@ function toHttpUrl(url) {
11696
11842
  }
11697
11843
  return url;
11698
11844
  }
11699
- function extractTranscriptionSegments(transcription) {
11845
+ function extractTranscriptionSegments(transcription, firstReceivedTimesMap) {
11700
11846
  return transcription.segments.map(_ref => {
11701
11847
  let {
11702
11848
  id,
@@ -11706,13 +11852,23 @@ function extractTranscriptionSegments(transcription) {
11706
11852
  endTime,
11707
11853
  final
11708
11854
  } = _ref;
11855
+ var _a;
11856
+ const firstReceivedTime = (_a = firstReceivedTimesMap.get(id)) !== null && _a !== void 0 ? _a : Date.now();
11857
+ const lastReceivedTime = Date.now();
11858
+ if (final) {
11859
+ firstReceivedTimesMap.delete(id);
11860
+ } else {
11861
+ firstReceivedTimesMap.set(id, firstReceivedTime);
11862
+ }
11709
11863
  return {
11710
11864
  id,
11711
11865
  text,
11712
11866
  startTime: Number.parseInt(startTime.toString()),
11713
11867
  endTime: Number.parseInt(endTime.toString()),
11714
11868
  final,
11715
- language
11869
+ language,
11870
+ firstReceivedTime,
11871
+ lastReceivedTime
11716
11872
  };
11717
11873
  });
11718
11874
  }
@@ -14013,6 +14169,7 @@ the first few seconds. So we use a 70% of target bitrate here as the start bitra
14013
14169
  eliminate this issue.
14014
14170
  */
14015
14171
  const startBitrateForSVC = 0.7;
14172
+ const debounceInterval = 20;
14016
14173
  const PCEvents = {
14017
14174
  NegotiationStarted: 'negotiationStarted',
14018
14175
  NegotiationComplete: 'negotiationComplete',
@@ -14049,7 +14206,7 @@ class PCTransport extends eventsExports.EventEmitter {
14049
14206
  throw e;
14050
14207
  }
14051
14208
  }
14052
- }), 100);
14209
+ }), debounceInterval);
14053
14210
  this.close = () => {
14054
14211
  if (!this._pc) {
14055
14212
  return;
@@ -16017,7 +16174,7 @@ function videoLayersFromEncodings(width, height, encodings, svc) {
16017
16174
  const bitratesRatio = sm.suffix == 'h' ? 2 : 3;
16018
16175
  for (let i = 0; i < sm.spatial; i += 1) {
16019
16176
  layers.push(new VideoLayer({
16020
- quality: VideoQuality.HIGH - i,
16177
+ quality: Math.min(VideoQuality.HIGH, sm.spatial - 1) - i,
16021
16178
  width: Math.ceil(width / Math.pow(resRatio, i)),
16022
16179
  height: Math.ceil(height / Math.pow(resRatio, i)),
16023
16180
  bitrate: encodings[0].maxBitrate ? Math.ceil(encodings[0].maxBitrate / Math.pow(bitratesRatio, i)) : 0,
@@ -16276,7 +16433,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16276
16433
  yield this.configure(joinResponse);
16277
16434
  }
16278
16435
  // create offer
16279
- if (!this.subscriberPrimary) {
16436
+ if (!this.subscriberPrimary || joinResponse.fastPublish) {
16280
16437
  this.negotiate();
16281
16438
  }
16282
16439
  this.clientConfiguration = joinResponse.clientConfiguration;
@@ -18315,6 +18472,7 @@ class LocalParticipant extends Participant {
18315
18472
  this.participantTrackPermissions = [];
18316
18473
  this.allParticipantsAllowedToSubscribe = true;
18317
18474
  this.encryptionType = Encryption_Type.NONE;
18475
+ this.enabledPublishVideoCodecs = [];
18318
18476
  this.handleReconnecting = () => {
18319
18477
  if (!this.reconnectFuture) {
18320
18478
  this.reconnectFuture = new Future();
@@ -18979,7 +19137,7 @@ class LocalParticipant extends Participant {
18979
19137
  }
18980
19138
  publish(track, opts, isStereo) {
18981
19139
  return __awaiter(this, void 0, void 0, function* () {
18982
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
19140
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
18983
19141
  const existingTrackOfSource = Array.from(this.trackPublications.values()).find(publishedTrack => track instanceof LocalTrack && publishedTrack.source === track.source);
18984
19142
  if (existingTrackOfSource && track.source !== Track.Source.Unknown) {
18985
19143
  this.log.info("publishing a second track with the same source: ".concat(track.source), Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
@@ -19002,6 +19160,12 @@ class LocalParticipant extends Participant {
19002
19160
  if (opts.videoCodec === undefined) {
19003
19161
  opts.videoCodec = defaultVideoCodec;
19004
19162
  }
19163
+ if (this.enabledPublishVideoCodecs.length > 0) {
19164
+ // fallback to a supported codec if it is not supported
19165
+ if (!this.enabledPublishVideoCodecs.some(c => opts.videoCodec === mimeTypeToVideoCodecString(c.mime))) {
19166
+ opts.videoCodec = mimeTypeToVideoCodecString(this.enabledPublishVideoCodecs[0].mime);
19167
+ }
19168
+ }
19005
19169
  const videoCodec = opts.videoCodec;
19006
19170
  // handle track actions
19007
19171
  track.on(TrackEvent.Muted, this.onTrackMuted);
@@ -19104,25 +19268,75 @@ class LocalParticipant extends Participant {
19104
19268
  if (!this.engine || this.engine.isClosed) {
19105
19269
  throw new UnexpectedConnectionState('cannot publish track when not connected');
19106
19270
  }
19107
- const ti = yield this.engine.addTrack(req);
19108
- // server might not support the codec the client has requested, in that case, fallback
19109
- // to a supported codec
19110
- let primaryCodecMime;
19111
- ti.codecs.forEach(codec => {
19112
- if (primaryCodecMime === undefined) {
19113
- primaryCodecMime = codec.mimeType;
19271
+ const negotiate = () => __awaiter(this, void 0, void 0, function* () {
19272
+ var _a, _b, _c;
19273
+ if (!this.engine.pcManager) {
19274
+ throw new UnexpectedConnectionState('pcManager is not ready');
19275
+ }
19276
+ track.sender = yield this.engine.createSender(track, opts, encodings);
19277
+ if (track instanceof LocalVideoTrack) {
19278
+ (_a = opts.degradationPreference) !== null && _a !== void 0 ? _a : opts.degradationPreference = getDefaultDegradationPreference(track);
19279
+ track.setDegradationPreference(opts.degradationPreference);
19280
+ }
19281
+ if (encodings) {
19282
+ if (isFireFox() && track.kind === Track.Kind.Audio) {
19283
+ /* Refer to RFC https://datatracker.ietf.org/doc/html/rfc7587#section-6.1,
19284
+ livekit-server uses maxaveragebitrate=510000 in the answer sdp to permit client to
19285
+ publish high quality audio track. But firefox always uses this value as the actual
19286
+ bitrates, causing the audio bitrates to rise to 510Kbps in any stereo case unexpectedly.
19287
+ So the client need to modify maxaverragebitrates in answer sdp to user provided value to
19288
+ fix the issue.
19289
+ */
19290
+ let trackTransceiver = undefined;
19291
+ for (const transceiver of this.engine.pcManager.publisher.getTransceivers()) {
19292
+ if (transceiver.sender === track.sender) {
19293
+ trackTransceiver = transceiver;
19294
+ break;
19295
+ }
19296
+ }
19297
+ if (trackTransceiver) {
19298
+ this.engine.pcManager.publisher.setTrackCodecBitrate({
19299
+ transceiver: trackTransceiver,
19300
+ codec: 'opus',
19301
+ maxbr: ((_b = encodings[0]) === null || _b === void 0 ? void 0 : _b.maxBitrate) ? encodings[0].maxBitrate / 1000 : 0
19302
+ });
19303
+ }
19304
+ } else if (track.codec && isSVCCodec(track.codec) && ((_c = encodings[0]) === null || _c === void 0 ? void 0 : _c.maxBitrate)) {
19305
+ this.engine.pcManager.publisher.setTrackCodecBitrate({
19306
+ cid: req.cid,
19307
+ codec: track.codec,
19308
+ maxbr: encodings[0].maxBitrate / 1000
19309
+ });
19310
+ }
19114
19311
  }
19312
+ yield this.engine.negotiate();
19115
19313
  });
19116
- if (primaryCodecMime && track.kind === Track.Kind.Video) {
19117
- const updatedCodec = mimeTypeToVideoCodecString(primaryCodecMime);
19118
- if (updatedCodec !== videoCodec) {
19119
- this.log.debug('falling back to server selected codec', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
19120
- codec: updatedCodec
19121
- }));
19122
- opts.videoCodec = updatedCodec;
19123
- // recompute encodings since bitrates/etc could have changed
19124
- encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, req.width, req.height, opts);
19314
+ let ti;
19315
+ if (this.enabledPublishVideoCodecs.length > 0) {
19316
+ const rets = yield Promise.all([this.engine.addTrack(req), negotiate()]);
19317
+ ti = rets[0];
19318
+ } else {
19319
+ ti = yield this.engine.addTrack(req);
19320
+ // server might not support the codec the client has requested, in that case, fallback
19321
+ // to a supported codec
19322
+ let primaryCodecMime;
19323
+ ti.codecs.forEach(codec => {
19324
+ if (primaryCodecMime === undefined) {
19325
+ primaryCodecMime = codec.mimeType;
19326
+ }
19327
+ });
19328
+ if (primaryCodecMime && track.kind === Track.Kind.Video) {
19329
+ const updatedCodec = mimeTypeToVideoCodecString(primaryCodecMime);
19330
+ if (updatedCodec !== videoCodec) {
19331
+ this.log.debug('falling back to server selected codec', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
19332
+ codec: updatedCodec
19333
+ }));
19334
+ opts.videoCodec = updatedCodec;
19335
+ // recompute encodings since bitrates/etc could have changed
19336
+ encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, req.width, req.height, opts);
19337
+ }
19125
19338
  }
19339
+ yield negotiate();
19126
19340
  }
19127
19341
  const publication = new LocalTrackPublication(track.kind, ti, track, {
19128
19342
  loggerName: this.roomOptions.loggerName,
@@ -19131,50 +19345,10 @@ class LocalParticipant extends Participant {
19131
19345
  // save options for when it needs to be republished again
19132
19346
  publication.options = opts;
19133
19347
  track.sid = ti.sid;
19134
- if (!this.engine.pcManager) {
19135
- throw new UnexpectedConnectionState('pcManager is not ready');
19136
- }
19137
19348
  this.log.debug("publishing ".concat(track.kind, " with encodings"), Object.assign(Object.assign({}, this.logContext), {
19138
19349
  encodings,
19139
19350
  trackInfo: ti
19140
19351
  }));
19141
- track.sender = yield this.engine.createSender(track, opts, encodings);
19142
- if (track instanceof LocalVideoTrack) {
19143
- (_l = opts.degradationPreference) !== null && _l !== void 0 ? _l : opts.degradationPreference = getDefaultDegradationPreference(track);
19144
- track.setDegradationPreference(opts.degradationPreference);
19145
- }
19146
- if (encodings) {
19147
- if (isFireFox() && track.kind === Track.Kind.Audio) {
19148
- /* Refer to RFC https://datatracker.ietf.org/doc/html/rfc7587#section-6.1,
19149
- livekit-server uses maxaveragebitrate=510000 in the answer sdp to permit client to
19150
- publish high quality audio track. But firefox always uses this value as the actual
19151
- bitrates, causing the audio bitrates to rise to 510Kbps in any stereo case unexpectedly.
19152
- So the client need to modify maxaverragebitrates in answer sdp to user provided value to
19153
- fix the issue.
19154
- */
19155
- let trackTransceiver = undefined;
19156
- for (const transceiver of this.engine.pcManager.publisher.getTransceivers()) {
19157
- if (transceiver.sender === track.sender) {
19158
- trackTransceiver = transceiver;
19159
- break;
19160
- }
19161
- }
19162
- if (trackTransceiver) {
19163
- this.engine.pcManager.publisher.setTrackCodecBitrate({
19164
- transceiver: trackTransceiver,
19165
- codec: 'opus',
19166
- maxbr: ((_m = encodings[0]) === null || _m === void 0 ? void 0 : _m.maxBitrate) ? encodings[0].maxBitrate / 1000 : 0
19167
- });
19168
- }
19169
- } else if (track.codec && isSVCCodec(track.codec) && ((_o = encodings[0]) === null || _o === void 0 ? void 0 : _o.maxBitrate)) {
19170
- this.engine.pcManager.publisher.setTrackCodecBitrate({
19171
- cid: req.cid,
19172
- codec: track.codec,
19173
- maxbr: encodings[0].maxBitrate / 1000
19174
- });
19175
- }
19176
- }
19177
- yield this.engine.negotiate();
19178
19352
  if (track instanceof LocalVideoTrack) {
19179
19353
  track.startMonitor(this.engine.client);
19180
19354
  } else if (track instanceof LocalAudioTrack) {
@@ -19240,9 +19414,12 @@ class LocalParticipant extends Participant {
19240
19414
  if (!this.engine || this.engine.isClosed) {
19241
19415
  throw new UnexpectedConnectionState('cannot publish track when not connected');
19242
19416
  }
19243
- const ti = yield this.engine.addTrack(req);
19244
- yield this.engine.createSimulcastSender(track, simulcastTrack, opts, encodings);
19245
- yield this.engine.negotiate();
19417
+ const negotiate = () => __awaiter(this, void 0, void 0, function* () {
19418
+ yield this.engine.createSimulcastSender(track, simulcastTrack, opts, encodings);
19419
+ yield this.engine.negotiate();
19420
+ });
19421
+ const rets = yield Promise.all([this.engine.addTrack(req), negotiate()]);
19422
+ const ti = rets[0];
19246
19423
  this.log.debug("published ".concat(videoCodec, " for track ").concat(track.sid), Object.assign(Object.assign({}, this.logContext), {
19247
19424
  encodings,
19248
19425
  trackInfo: ti
@@ -19426,6 +19603,10 @@ class LocalParticipant extends Participant {
19426
19603
  }
19427
19604
  }
19428
19605
  /** @internal */
19606
+ setEnabledPublishCodecs(codecs) {
19607
+ this.enabledPublishVideoCodecs = codecs.filter(c => c.mime.split('/')[0].toLowerCase() === 'video');
19608
+ }
19609
+ /** @internal */
19429
19610
  updateInfo(info) {
19430
19611
  if (info.sid !== this.sid) {
19431
19612
  // drop updates that specify a wrong sid.
@@ -20147,6 +20328,7 @@ class Room extends eventsExports.EventEmitter {
20147
20328
  const pi = joinResponse.participant;
20148
20329
  this.localParticipant.sid = pi.sid;
20149
20330
  this.localParticipant.identity = pi.identity;
20331
+ this.localParticipant.setEnabledPublishCodecs(joinResponse.enabledPublishCodecs);
20150
20332
  if (this.options.e2ee && this.e2eeManager) {
20151
20333
  try {
20152
20334
  this.e2eeManager.setSifTrailer(joinResponse.sifTrailer);
@@ -20559,7 +20741,7 @@ class Room extends eventsExports.EventEmitter {
20559
20741
  // find the participant
20560
20742
  const participant = transcription.transcribedParticipantIdentity === this.localParticipant.identity ? this.localParticipant : this.getParticipantByIdentity(transcription.transcribedParticipantIdentity);
20561
20743
  const publication = participant === null || participant === void 0 ? void 0 : participant.trackPublications.get(transcription.trackId);
20562
- const segments = extractTranscriptionSegments(transcription);
20744
+ const segments = extractTranscriptionSegments(transcription, this.transcriptionReceivedTimes);
20563
20745
  publication === null || publication === void 0 ? void 0 : publication.emit(TrackEvent.TranscriptionReceived, segments);
20564
20746
  participant === null || participant === void 0 ? void 0 : participant.emit(ParticipantEvent.TranscriptionReceived, segments, publication);
20565
20747
  this.emit(RoomEvent.TranscriptionReceived, segments, participant, publication);
@@ -20674,6 +20856,7 @@ class Room extends eventsExports.EventEmitter {
20674
20856
  this.sidToIdentity = new Map();
20675
20857
  this.options = Object.assign(Object.assign({}, roomOptionDefaults), options);
20676
20858
  this.log = getLogger((_a = this.options.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Room);
20859
+ this.transcriptionReceivedTimes = new Map();
20677
20860
  this.options.audioCaptureDefaults = Object.assign(Object.assign({}, audioDefaults), options === null || options === void 0 ? void 0 : options.audioCaptureDefaults);
20678
20861
  this.options.videoCaptureDefaults = Object.assign(Object.assign({}, videoDefaults), options === null || options === void 0 ? void 0 : options.videoCaptureDefaults);
20679
20862
  this.options.publishDefaults = Object.assign(Object.assign({}, publishDefaults), options === null || options === void 0 ? void 0 : options.publishDefaults);
@@ -20819,6 +21002,19 @@ class Room extends eventsExports.EventEmitter {
20819
21002
  }
20820
21003
  }).on(EngineEvent.DCBufferStatusChanged, (status, kind) => {
20821
21004
  this.emit(RoomEvent.DCBufferStatusChanged, status, kind);
21005
+ }).on(EngineEvent.LocalTrackSubscribed, subscribedSid => {
21006
+ const trackPublication = this.localParticipant.getTrackPublications().find(_ref2 => {
21007
+ let {
21008
+ trackSid
21009
+ } = _ref2;
21010
+ return trackSid === subscribedSid;
21011
+ });
21012
+ if (!trackPublication) {
21013
+ this.log.warn('could not find local track subscription for subscribed event', this.logContext);
21014
+ return;
21015
+ }
21016
+ this.localParticipant.emit(ParticipantEvent.LocalTrackSubscribed, trackPublication);
21017
+ this.emitWhenConnected(RoomEvent.LocalTrackSubscribed, trackPublication, this.localParticipant);
20822
21018
  });
20823
21019
  if (this.localParticipant) {
20824
21020
  this.localParticipant.setupEngine(this.engine);
@@ -21188,6 +21384,7 @@ class Room extends eventsExports.EventEmitter {
21188
21384
  this.clearConnectionReconcile();
21189
21385
  this.isResuming = false;
21190
21386
  this.bufferedEvents = [];
21387
+ this.transcriptionReceivedTimes.clear();
21191
21388
  if (this.state === ConnectionState.Disconnected) {
21192
21389
  return;
21193
21390
  }
@@ -21431,8 +21628,8 @@ class Room extends eventsExports.EventEmitter {
21431
21628
  return true;
21432
21629
  }
21433
21630
  emitBufferedEvents() {
21434
- this.bufferedEvents.forEach(_ref2 => {
21435
- let [ev, args] = _ref2;
21631
+ this.bufferedEvents.forEach(_ref3 => {
21632
+ let [ev, args] = _ref3;
21436
21633
  this.emit(ev, ...args);
21437
21634
  });
21438
21635
  this.bufferedEvents = [];