livekit-client 1.6.2 → 1.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/proto/livekit_rtc.ts
    CHANGED
    
    | @@ -9,6 +9,9 @@ import { | |
| 9 9 | 
             
              DisconnectReason,
         | 
| 10 10 | 
             
              disconnectReasonFromJSON,
         | 
| 11 11 | 
             
              disconnectReasonToJSON,
         | 
| 12 | 
            +
              Encryption_Type,
         | 
| 13 | 
            +
              encryption_TypeFromJSON,
         | 
| 14 | 
            +
              encryption_TypeToJSON,
         | 
| 12 15 | 
             
              ParticipantInfo,
         | 
| 13 16 | 
             
              ParticipantTracks,
         | 
| 14 17 | 
             
              Room,
         | 
| @@ -148,7 +151,8 @@ export interface SignalRequest { | |
| 148 151 | 
             
                | { $case: "subscriptionPermission"; subscriptionPermission: SubscriptionPermission }
         | 
| 149 152 | 
             
                | { $case: "syncState"; syncState: SyncState }
         | 
| 150 153 | 
             
                | { $case: "simulate"; simulate: SimulateScenario }
         | 
| 151 | 
            -
                | { $case: "ping"; ping: number } | 
| 154 | 
            +
                | { $case: "ping"; ping: number }
         | 
| 155 | 
            +
                | { $case: "updateMetadata"; updateMetadata: UpdateParticipantMetadata };
         | 
| 152 156 | 
             
            }
         | 
| 153 157 |  | 
| 154 158 | 
             
            export interface SignalResponse {
         | 
| @@ -169,7 +173,8 @@ export interface SignalResponse { | |
| 169 173 | 
             
                | { $case: "subscriptionPermissionUpdate"; subscriptionPermissionUpdate: SubscriptionPermissionUpdate }
         | 
| 170 174 | 
             
                | { $case: "refreshToken"; refreshToken: string }
         | 
| 171 175 | 
             
                | { $case: "trackUnpublished"; trackUnpublished: TrackUnpublishedResponse }
         | 
| 172 | 
            -
                | { $case: "pong"; pong: number } | 
| 176 | 
            +
                | { $case: "pong"; pong: number }
         | 
| 177 | 
            +
                | { $case: "reconnect"; reconnect: ReconnectResponse };
         | 
| 173 178 | 
             
            }
         | 
| 174 179 |  | 
| 175 180 | 
             
            export interface SimulcastCodec {
         | 
| @@ -198,6 +203,7 @@ export interface AddTrackRequest { | |
| 198 203 | 
             
              stereo: boolean;
         | 
| 199 204 | 
             
              /** true if RED (Redundant Encoding) is disabled for audio */
         | 
| 200 205 | 
             
              disableRed: boolean;
         | 
| 206 | 
            +
              encryption: Encryption_Type;
         | 
| 201 207 | 
             
            }
         | 
| 202 208 |  | 
| 203 209 | 
             
            export interface TrickleRequest {
         | 
| @@ -232,6 +238,11 @@ export interface JoinResponse { | |
| 232 238 | 
             
              serverInfo?: ServerInfo;
         | 
| 233 239 | 
             
            }
         | 
| 234 240 |  | 
| 241 | 
            +
            export interface ReconnectResponse {
         | 
| 242 | 
            +
              iceServers: ICEServer[];
         | 
| 243 | 
            +
              clientConfiguration?: ClientConfiguration;
         | 
| 244 | 
            +
            }
         | 
| 245 | 
            +
             | 
| 235 246 | 
             
            export interface TrackPublishedResponse {
         | 
| 236 247 | 
             
              cid: string;
         | 
| 237 248 | 
             
              track?: TrackInfo;
         | 
| @@ -267,8 +278,17 @@ export interface UpdateTrackSettings { | |
| 267 278 | 
             
              width: number;
         | 
| 268 279 | 
             
              /** for video, height to receive */
         | 
| 269 280 | 
             
              height: number;
         | 
| 270 | 
            -
              /** for video, frame rate to receive */
         | 
| 271 281 | 
             
              fps: number;
         | 
| 282 | 
            +
              /**
         | 
| 283 | 
            +
               * subscription priority. 1 being the highest (0 is unset)
         | 
| 284 | 
            +
               * when unset, server sill assign priority based on the order of subscription
         | 
| 285 | 
            +
               * server will use priority in the following ways:
         | 
| 286 | 
            +
               * 1. when subscribed tracks exceed per-participant subscription limit, server will
         | 
| 287 | 
            +
               *    pause the lowest priority tracks
         | 
| 288 | 
            +
               * 2. when the network is congested, server will assign available bandwidth to
         | 
| 289 | 
            +
               *    higher priority tracks first. lowest priority tracks can be paused
         | 
| 290 | 
            +
               */
         | 
| 291 | 
            +
              priority: number;
         | 
| 272 292 | 
             
            }
         | 
| 273 293 |  | 
| 274 294 | 
             
            export interface LeaveRequest {
         | 
| @@ -286,6 +306,10 @@ export interface UpdateVideoLayers { | |
| 286 306 | 
             
              layers: VideoLayer[];
         | 
| 287 307 | 
             
            }
         | 
| 288 308 |  | 
| 309 | 
            +
            export interface UpdateParticipantMetadata {
         | 
| 310 | 
            +
              metadata: string;
         | 
| 311 | 
            +
            }
         | 
| 312 | 
            +
             | 
| 289 313 | 
             
            export interface ICEServer {
         | 
| 290 314 | 
             
              urls: string[];
         | 
| 291 315 | 
             
              username: string;
         | 
| @@ -425,6 +449,9 @@ export const SignalRequest = { | |
| 425 449 | 
             
                if (message.message?.$case === "ping") {
         | 
| 426 450 | 
             
                  writer.uint32(112).int64(message.message.ping);
         | 
| 427 451 | 
             
                }
         | 
| 452 | 
            +
                if (message.message?.$case === "updateMetadata") {
         | 
| 453 | 
            +
                  UpdateParticipantMetadata.encode(message.message.updateMetadata, writer.uint32(122).fork()).ldelim();
         | 
| 454 | 
            +
                }
         | 
| 428 455 | 
             
                return writer;
         | 
| 429 456 | 
             
              },
         | 
| 430 457 |  | 
| @@ -480,6 +507,12 @@ export const SignalRequest = { | |
| 480 507 | 
             
                    case 14:
         | 
| 481 508 | 
             
                      message.message = { $case: "ping", ping: longToNumber(reader.int64() as Long) };
         | 
| 482 509 | 
             
                      break;
         | 
| 510 | 
            +
                    case 15:
         | 
| 511 | 
            +
                      message.message = {
         | 
| 512 | 
            +
                        $case: "updateMetadata",
         | 
| 513 | 
            +
                        updateMetadata: UpdateParticipantMetadata.decode(reader, reader.uint32()),
         | 
| 514 | 
            +
                      };
         | 
| 515 | 
            +
                      break;
         | 
| 483 516 | 
             
                    default:
         | 
| 484 517 | 
             
                      reader.skipType(tag & 7);
         | 
| 485 518 | 
             
                      break;
         | 
| @@ -519,6 +552,8 @@ export const SignalRequest = { | |
| 519 552 | 
             
                    ? { $case: "simulate", simulate: SimulateScenario.fromJSON(object.simulate) }
         | 
| 520 553 | 
             
                    : isSet(object.ping)
         | 
| 521 554 | 
             
                    ? { $case: "ping", ping: Number(object.ping) }
         | 
| 555 | 
            +
                    : isSet(object.updateMetadata)
         | 
| 556 | 
            +
                    ? { $case: "updateMetadata", updateMetadata: UpdateParticipantMetadata.fromJSON(object.updateMetadata) }
         | 
| 522 557 | 
             
                    : undefined,
         | 
| 523 558 | 
             
                };
         | 
| 524 559 | 
             
              },
         | 
| @@ -555,6 +590,9 @@ export const SignalRequest = { | |
| 555 590 | 
             
                message.message?.$case === "simulate" &&
         | 
| 556 591 | 
             
                  (obj.simulate = message.message?.simulate ? SimulateScenario.toJSON(message.message?.simulate) : undefined);
         | 
| 557 592 | 
             
                message.message?.$case === "ping" && (obj.ping = Math.round(message.message?.ping));
         | 
| 593 | 
            +
                message.message?.$case === "updateMetadata" && (obj.updateMetadata = message.message?.updateMetadata
         | 
| 594 | 
            +
                  ? UpdateParticipantMetadata.toJSON(message.message?.updateMetadata)
         | 
| 595 | 
            +
                  : undefined);
         | 
| 558 596 | 
             
                return obj;
         | 
| 559 597 | 
             
              },
         | 
| 560 598 |  | 
| @@ -641,6 +679,16 @@ export const SignalRequest = { | |
| 641 679 | 
             
                if (object.message?.$case === "ping" && object.message?.ping !== undefined && object.message?.ping !== null) {
         | 
| 642 680 | 
             
                  message.message = { $case: "ping", ping: object.message.ping };
         | 
| 643 681 | 
             
                }
         | 
| 682 | 
            +
                if (
         | 
| 683 | 
            +
                  object.message?.$case === "updateMetadata" &&
         | 
| 684 | 
            +
                  object.message?.updateMetadata !== undefined &&
         | 
| 685 | 
            +
                  object.message?.updateMetadata !== null
         | 
| 686 | 
            +
                ) {
         | 
| 687 | 
            +
                  message.message = {
         | 
| 688 | 
            +
                    $case: "updateMetadata",
         | 
| 689 | 
            +
                    updateMetadata: UpdateParticipantMetadata.fromPartial(object.message.updateMetadata),
         | 
| 690 | 
            +
                  };
         | 
| 691 | 
            +
                }
         | 
| 644 692 | 
             
                return message;
         | 
| 645 693 | 
             
              },
         | 
| 646 694 | 
             
            };
         | 
| @@ -703,6 +751,9 @@ export const SignalResponse = { | |
| 703 751 | 
             
                if (message.message?.$case === "pong") {
         | 
| 704 752 | 
             
                  writer.uint32(144).int64(message.message.pong);
         | 
| 705 753 | 
             
                }
         | 
| 754 | 
            +
                if (message.message?.$case === "reconnect") {
         | 
| 755 | 
            +
                  ReconnectResponse.encode(message.message.reconnect, writer.uint32(154).fork()).ldelim();
         | 
| 756 | 
            +
                }
         | 
| 706 757 | 
             
                return writer;
         | 
| 707 758 | 
             
              },
         | 
| 708 759 |  | 
| @@ -785,6 +836,9 @@ export const SignalResponse = { | |
| 785 836 | 
             
                    case 18:
         | 
| 786 837 | 
             
                      message.message = { $case: "pong", pong: longToNumber(reader.int64() as Long) };
         | 
| 787 838 | 
             
                      break;
         | 
| 839 | 
            +
                    case 19:
         | 
| 840 | 
            +
                      message.message = { $case: "reconnect", reconnect: ReconnectResponse.decode(reader, reader.uint32()) };
         | 
| 841 | 
            +
                      break;
         | 
| 788 842 | 
             
                    default:
         | 
| 789 843 | 
             
                      reader.skipType(tag & 7);
         | 
| 790 844 | 
             
                      break;
         | 
| @@ -835,6 +889,8 @@ export const SignalResponse = { | |
| 835 889 | 
             
                    ? { $case: "trackUnpublished", trackUnpublished: TrackUnpublishedResponse.fromJSON(object.trackUnpublished) }
         | 
| 836 890 | 
             
                    : isSet(object.pong)
         | 
| 837 891 | 
             
                    ? { $case: "pong", pong: Number(object.pong) }
         | 
| 892 | 
            +
                    : isSet(object.reconnect)
         | 
| 893 | 
            +
                    ? { $case: "reconnect", reconnect: ReconnectResponse.fromJSON(object.reconnect) }
         | 
| 838 894 | 
             
                    : undefined,
         | 
| 839 895 | 
             
                };
         | 
| 840 896 | 
             
              },
         | 
| @@ -882,6 +938,8 @@ export const SignalResponse = { | |
| 882 938 | 
             
                  ? TrackUnpublishedResponse.toJSON(message.message?.trackUnpublished)
         | 
| 883 939 | 
             
                  : undefined);
         | 
| 884 940 | 
             
                message.message?.$case === "pong" && (obj.pong = Math.round(message.message?.pong));
         | 
| 941 | 
            +
                message.message?.$case === "reconnect" &&
         | 
| 942 | 
            +
                  (obj.reconnect = message.message?.reconnect ? ReconnectResponse.toJSON(message.message?.reconnect) : undefined);
         | 
| 885 943 | 
             
                return obj;
         | 
| 886 944 | 
             
              },
         | 
| 887 945 |  | 
| @@ -999,6 +1057,13 @@ export const SignalResponse = { | |
| 999 1057 | 
             
                if (object.message?.$case === "pong" && object.message?.pong !== undefined && object.message?.pong !== null) {
         | 
| 1000 1058 | 
             
                  message.message = { $case: "pong", pong: object.message.pong };
         | 
| 1001 1059 | 
             
                }
         | 
| 1060 | 
            +
                if (
         | 
| 1061 | 
            +
                  object.message?.$case === "reconnect" &&
         | 
| 1062 | 
            +
                  object.message?.reconnect !== undefined &&
         | 
| 1063 | 
            +
                  object.message?.reconnect !== null
         | 
| 1064 | 
            +
                ) {
         | 
| 1065 | 
            +
                  message.message = { $case: "reconnect", reconnect: ReconnectResponse.fromPartial(object.message.reconnect) };
         | 
| 1066 | 
            +
                }
         | 
| 1002 1067 | 
             
                return message;
         | 
| 1003 1068 | 
             
              },
         | 
| 1004 1069 | 
             
            };
         | 
| @@ -1085,6 +1150,7 @@ function createBaseAddTrackRequest(): AddTrackRequest { | |
| 1085 1150 | 
             
                sid: "",
         | 
| 1086 1151 | 
             
                stereo: false,
         | 
| 1087 1152 | 
             
                disableRed: false,
         | 
| 1153 | 
            +
                encryption: 0,
         | 
| 1088 1154 | 
             
              };
         | 
| 1089 1155 | 
             
            }
         | 
| 1090 1156 |  | 
| @@ -1129,6 +1195,9 @@ export const AddTrackRequest = { | |
| 1129 1195 | 
             
                if (message.disableRed === true) {
         | 
| 1130 1196 | 
             
                  writer.uint32(104).bool(message.disableRed);
         | 
| 1131 1197 | 
             
                }
         | 
| 1198 | 
            +
                if (message.encryption !== 0) {
         | 
| 1199 | 
            +
                  writer.uint32(112).int32(message.encryption);
         | 
| 1200 | 
            +
                }
         | 
| 1132 1201 | 
             
                return writer;
         | 
| 1133 1202 | 
             
              },
         | 
| 1134 1203 |  | 
| @@ -1178,6 +1247,9 @@ export const AddTrackRequest = { | |
| 1178 1247 | 
             
                    case 13:
         | 
| 1179 1248 | 
             
                      message.disableRed = reader.bool();
         | 
| 1180 1249 | 
             
                      break;
         | 
| 1250 | 
            +
                    case 14:
         | 
| 1251 | 
            +
                      message.encryption = reader.int32() as any;
         | 
| 1252 | 
            +
                      break;
         | 
| 1181 1253 | 
             
                    default:
         | 
| 1182 1254 | 
             
                      reader.skipType(tag & 7);
         | 
| 1183 1255 | 
             
                      break;
         | 
| @@ -1203,6 +1275,7 @@ export const AddTrackRequest = { | |
| 1203 1275 | 
             
                  sid: isSet(object.sid) ? String(object.sid) : "",
         | 
| 1204 1276 | 
             
                  stereo: isSet(object.stereo) ? Boolean(object.stereo) : false,
         | 
| 1205 1277 | 
             
                  disableRed: isSet(object.disableRed) ? Boolean(object.disableRed) : false,
         | 
| 1278 | 
            +
                  encryption: isSet(object.encryption) ? encryption_TypeFromJSON(object.encryption) : 0,
         | 
| 1206 1279 | 
             
                };
         | 
| 1207 1280 | 
             
              },
         | 
| 1208 1281 |  | 
| @@ -1229,6 +1302,7 @@ export const AddTrackRequest = { | |
| 1229 1302 | 
             
                message.sid !== undefined && (obj.sid = message.sid);
         | 
| 1230 1303 | 
             
                message.stereo !== undefined && (obj.stereo = message.stereo);
         | 
| 1231 1304 | 
             
                message.disableRed !== undefined && (obj.disableRed = message.disableRed);
         | 
| 1305 | 
            +
                message.encryption !== undefined && (obj.encryption = encryption_TypeToJSON(message.encryption));
         | 
| 1232 1306 | 
             
                return obj;
         | 
| 1233 1307 | 
             
              },
         | 
| 1234 1308 |  | 
| @@ -1247,6 +1321,7 @@ export const AddTrackRequest = { | |
| 1247 1321 | 
             
                message.sid = object.sid ?? "";
         | 
| 1248 1322 | 
             
                message.stereo = object.stereo ?? false;
         | 
| 1249 1323 | 
             
                message.disableRed = object.disableRed ?? false;
         | 
| 1324 | 
            +
                message.encryption = object.encryption ?? 0;
         | 
| 1250 1325 | 
             
                return message;
         | 
| 1251 1326 | 
             
              },
         | 
| 1252 1327 | 
             
            };
         | 
| @@ -1550,6 +1625,74 @@ export const JoinResponse = { | |
| 1550 1625 | 
             
              },
         | 
| 1551 1626 | 
             
            };
         | 
| 1552 1627 |  | 
| 1628 | 
            +
            function createBaseReconnectResponse(): ReconnectResponse {
         | 
| 1629 | 
            +
              return { iceServers: [], clientConfiguration: undefined };
         | 
| 1630 | 
            +
            }
         | 
| 1631 | 
            +
             | 
| 1632 | 
            +
            export const ReconnectResponse = {
         | 
| 1633 | 
            +
              encode(message: ReconnectResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
         | 
| 1634 | 
            +
                for (const v of message.iceServers) {
         | 
| 1635 | 
            +
                  ICEServer.encode(v!, writer.uint32(10).fork()).ldelim();
         | 
| 1636 | 
            +
                }
         | 
| 1637 | 
            +
                if (message.clientConfiguration !== undefined) {
         | 
| 1638 | 
            +
                  ClientConfiguration.encode(message.clientConfiguration, writer.uint32(18).fork()).ldelim();
         | 
| 1639 | 
            +
                }
         | 
| 1640 | 
            +
                return writer;
         | 
| 1641 | 
            +
              },
         | 
| 1642 | 
            +
             | 
| 1643 | 
            +
              decode(input: _m0.Reader | Uint8Array, length?: number): ReconnectResponse {
         | 
| 1644 | 
            +
                const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
         | 
| 1645 | 
            +
                let end = length === undefined ? reader.len : reader.pos + length;
         | 
| 1646 | 
            +
                const message = createBaseReconnectResponse();
         | 
| 1647 | 
            +
                while (reader.pos < end) {
         | 
| 1648 | 
            +
                  const tag = reader.uint32();
         | 
| 1649 | 
            +
                  switch (tag >>> 3) {
         | 
| 1650 | 
            +
                    case 1:
         | 
| 1651 | 
            +
                      message.iceServers.push(ICEServer.decode(reader, reader.uint32()));
         | 
| 1652 | 
            +
                      break;
         | 
| 1653 | 
            +
                    case 2:
         | 
| 1654 | 
            +
                      message.clientConfiguration = ClientConfiguration.decode(reader, reader.uint32());
         | 
| 1655 | 
            +
                      break;
         | 
| 1656 | 
            +
                    default:
         | 
| 1657 | 
            +
                      reader.skipType(tag & 7);
         | 
| 1658 | 
            +
                      break;
         | 
| 1659 | 
            +
                  }
         | 
| 1660 | 
            +
                }
         | 
| 1661 | 
            +
                return message;
         | 
| 1662 | 
            +
              },
         | 
| 1663 | 
            +
             | 
| 1664 | 
            +
              fromJSON(object: any): ReconnectResponse {
         | 
| 1665 | 
            +
                return {
         | 
| 1666 | 
            +
                  iceServers: Array.isArray(object?.iceServers) ? object.iceServers.map((e: any) => ICEServer.fromJSON(e)) : [],
         | 
| 1667 | 
            +
                  clientConfiguration: isSet(object.clientConfiguration)
         | 
| 1668 | 
            +
                    ? ClientConfiguration.fromJSON(object.clientConfiguration)
         | 
| 1669 | 
            +
                    : undefined,
         | 
| 1670 | 
            +
                };
         | 
| 1671 | 
            +
              },
         | 
| 1672 | 
            +
             | 
| 1673 | 
            +
              toJSON(message: ReconnectResponse): unknown {
         | 
| 1674 | 
            +
                const obj: any = {};
         | 
| 1675 | 
            +
                if (message.iceServers) {
         | 
| 1676 | 
            +
                  obj.iceServers = message.iceServers.map((e) => e ? ICEServer.toJSON(e) : undefined);
         | 
| 1677 | 
            +
                } else {
         | 
| 1678 | 
            +
                  obj.iceServers = [];
         | 
| 1679 | 
            +
                }
         | 
| 1680 | 
            +
                message.clientConfiguration !== undefined && (obj.clientConfiguration = message.clientConfiguration
         | 
| 1681 | 
            +
                  ? ClientConfiguration.toJSON(message.clientConfiguration)
         | 
| 1682 | 
            +
                  : undefined);
         | 
| 1683 | 
            +
                return obj;
         | 
| 1684 | 
            +
              },
         | 
| 1685 | 
            +
             | 
| 1686 | 
            +
              fromPartial<I extends Exact<DeepPartial<ReconnectResponse>, I>>(object: I): ReconnectResponse {
         | 
| 1687 | 
            +
                const message = createBaseReconnectResponse();
         | 
| 1688 | 
            +
                message.iceServers = object.iceServers?.map((e) => ICEServer.fromPartial(e)) || [];
         | 
| 1689 | 
            +
                message.clientConfiguration = (object.clientConfiguration !== undefined && object.clientConfiguration !== null)
         | 
| 1690 | 
            +
                  ? ClientConfiguration.fromPartial(object.clientConfiguration)
         | 
| 1691 | 
            +
                  : undefined;
         | 
| 1692 | 
            +
                return message;
         | 
| 1693 | 
            +
              },
         | 
| 1694 | 
            +
            };
         | 
| 1695 | 
            +
             | 
| 1553 1696 | 
             
            function createBaseTrackPublishedResponse(): TrackPublishedResponse {
         | 
| 1554 1697 | 
             
              return { cid: "", track: undefined };
         | 
| 1555 1698 | 
             
            }
         | 
| @@ -1845,7 +1988,7 @@ export const UpdateSubscription = { | |
| 1845 1988 | 
             
            };
         | 
| 1846 1989 |  | 
| 1847 1990 | 
             
            function createBaseUpdateTrackSettings(): UpdateTrackSettings {
         | 
| 1848 | 
            -
              return { trackSids: [], disabled: false, quality: 0, width: 0, height: 0, fps: 0 };
         | 
| 1991 | 
            +
              return { trackSids: [], disabled: false, quality: 0, width: 0, height: 0, fps: 0, priority: 0 };
         | 
| 1849 1992 | 
             
            }
         | 
| 1850 1993 |  | 
| 1851 1994 | 
             
            export const UpdateTrackSettings = {
         | 
| @@ -1868,6 +2011,9 @@ export const UpdateTrackSettings = { | |
| 1868 2011 | 
             
                if (message.fps !== 0) {
         | 
| 1869 2012 | 
             
                  writer.uint32(56).uint32(message.fps);
         | 
| 1870 2013 | 
             
                }
         | 
| 2014 | 
            +
                if (message.priority !== 0) {
         | 
| 2015 | 
            +
                  writer.uint32(64).uint32(message.priority);
         | 
| 2016 | 
            +
                }
         | 
| 1871 2017 | 
             
                return writer;
         | 
| 1872 2018 | 
             
              },
         | 
| 1873 2019 |  | 
| @@ -1896,6 +2042,9 @@ export const UpdateTrackSettings = { | |
| 1896 2042 | 
             
                    case 7:
         | 
| 1897 2043 | 
             
                      message.fps = reader.uint32();
         | 
| 1898 2044 | 
             
                      break;
         | 
| 2045 | 
            +
                    case 8:
         | 
| 2046 | 
            +
                      message.priority = reader.uint32();
         | 
| 2047 | 
            +
                      break;
         | 
| 1899 2048 | 
             
                    default:
         | 
| 1900 2049 | 
             
                      reader.skipType(tag & 7);
         | 
| 1901 2050 | 
             
                      break;
         | 
| @@ -1912,6 +2061,7 @@ export const UpdateTrackSettings = { | |
| 1912 2061 | 
             
                  width: isSet(object.width) ? Number(object.width) : 0,
         | 
| 1913 2062 | 
             
                  height: isSet(object.height) ? Number(object.height) : 0,
         | 
| 1914 2063 | 
             
                  fps: isSet(object.fps) ? Number(object.fps) : 0,
         | 
| 2064 | 
            +
                  priority: isSet(object.priority) ? Number(object.priority) : 0,
         | 
| 1915 2065 | 
             
                };
         | 
| 1916 2066 | 
             
              },
         | 
| 1917 2067 |  | 
| @@ -1927,6 +2077,7 @@ export const UpdateTrackSettings = { | |
| 1927 2077 | 
             
                message.width !== undefined && (obj.width = Math.round(message.width));
         | 
| 1928 2078 | 
             
                message.height !== undefined && (obj.height = Math.round(message.height));
         | 
| 1929 2079 | 
             
                message.fps !== undefined && (obj.fps = Math.round(message.fps));
         | 
| 2080 | 
            +
                message.priority !== undefined && (obj.priority = Math.round(message.priority));
         | 
| 1930 2081 | 
             
                return obj;
         | 
| 1931 2082 | 
             
              },
         | 
| 1932 2083 |  | 
| @@ -1938,6 +2089,7 @@ export const UpdateTrackSettings = { | |
| 1938 2089 | 
             
                message.width = object.width ?? 0;
         | 
| 1939 2090 | 
             
                message.height = object.height ?? 0;
         | 
| 1940 2091 | 
             
                message.fps = object.fps ?? 0;
         | 
| 2092 | 
            +
                message.priority = object.priority ?? 0;
         | 
| 1941 2093 | 
             
                return message;
         | 
| 1942 2094 | 
             
              },
         | 
| 1943 2095 | 
             
            };
         | 
| @@ -2062,6 +2214,53 @@ export const UpdateVideoLayers = { | |
| 2062 2214 | 
             
              },
         | 
| 2063 2215 | 
             
            };
         | 
| 2064 2216 |  | 
| 2217 | 
            +
            function createBaseUpdateParticipantMetadata(): UpdateParticipantMetadata {
         | 
| 2218 | 
            +
              return { metadata: "" };
         | 
| 2219 | 
            +
            }
         | 
| 2220 | 
            +
             | 
| 2221 | 
            +
            export const UpdateParticipantMetadata = {
         | 
| 2222 | 
            +
              encode(message: UpdateParticipantMetadata, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
         | 
| 2223 | 
            +
                if (message.metadata !== "") {
         | 
| 2224 | 
            +
                  writer.uint32(10).string(message.metadata);
         | 
| 2225 | 
            +
                }
         | 
| 2226 | 
            +
                return writer;
         | 
| 2227 | 
            +
              },
         | 
| 2228 | 
            +
             | 
| 2229 | 
            +
              decode(input: _m0.Reader | Uint8Array, length?: number): UpdateParticipantMetadata {
         | 
| 2230 | 
            +
                const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
         | 
| 2231 | 
            +
                let end = length === undefined ? reader.len : reader.pos + length;
         | 
| 2232 | 
            +
                const message = createBaseUpdateParticipantMetadata();
         | 
| 2233 | 
            +
                while (reader.pos < end) {
         | 
| 2234 | 
            +
                  const tag = reader.uint32();
         | 
| 2235 | 
            +
                  switch (tag >>> 3) {
         | 
| 2236 | 
            +
                    case 1:
         | 
| 2237 | 
            +
                      message.metadata = reader.string();
         | 
| 2238 | 
            +
                      break;
         | 
| 2239 | 
            +
                    default:
         | 
| 2240 | 
            +
                      reader.skipType(tag & 7);
         | 
| 2241 | 
            +
                      break;
         | 
| 2242 | 
            +
                  }
         | 
| 2243 | 
            +
                }
         | 
| 2244 | 
            +
                return message;
         | 
| 2245 | 
            +
              },
         | 
| 2246 | 
            +
             | 
| 2247 | 
            +
              fromJSON(object: any): UpdateParticipantMetadata {
         | 
| 2248 | 
            +
                return { metadata: isSet(object.metadata) ? String(object.metadata) : "" };
         | 
| 2249 | 
            +
              },
         | 
| 2250 | 
            +
             | 
| 2251 | 
            +
              toJSON(message: UpdateParticipantMetadata): unknown {
         | 
| 2252 | 
            +
                const obj: any = {};
         | 
| 2253 | 
            +
                message.metadata !== undefined && (obj.metadata = message.metadata);
         | 
| 2254 | 
            +
                return obj;
         | 
| 2255 | 
            +
              },
         | 
| 2256 | 
            +
             | 
| 2257 | 
            +
              fromPartial<I extends Exact<DeepPartial<UpdateParticipantMetadata>, I>>(object: I): UpdateParticipantMetadata {
         | 
| 2258 | 
            +
                const message = createBaseUpdateParticipantMetadata();
         | 
| 2259 | 
            +
                message.metadata = object.metadata ?? "";
         | 
| 2260 | 
            +
                return message;
         | 
| 2261 | 
            +
              },
         | 
| 2262 | 
            +
            };
         | 
| 2263 | 
            +
             | 
| 2065 2264 | 
             
            function createBaseICEServer(): ICEServer {
         | 
| 2066 2265 | 
             
              return { urls: [], username: "", credential: "" };
         | 
| 2067 2266 | 
             
            }
         | 
| @@ -3192,7 +3391,7 @@ export const SimulateScenario = { | |
| 3192 3391 | 
             
            declare var self: any | undefined;
         | 
| 3193 3392 | 
             
            declare var window: any | undefined;
         | 
| 3194 3393 | 
             
            declare var global: any | undefined;
         | 
| 3195 | 
            -
            var  | 
| 3394 | 
            +
            var tsProtoGlobalThis: any = (() => {
         | 
| 3196 3395 | 
             
              if (typeof globalThis !== "undefined") {
         | 
| 3197 3396 | 
             
                return globalThis;
         | 
| 3198 3397 | 
             
              }
         | 
| @@ -3222,7 +3421,7 @@ export type Exact<P, I extends P> = P extends Builtin ? P | |
| 3222 3421 |  | 
| 3223 3422 | 
             
            function longToNumber(long: Long): number {
         | 
| 3224 3423 | 
             
              if (long.gt(Number.MAX_SAFE_INTEGER)) {
         | 
| 3225 | 
            -
                throw new  | 
| 3424 | 
            +
                throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
         | 
| 3226 3425 | 
             
              }
         | 
| 3227 3426 | 
             
              return long.toNumber();
         | 
| 3228 3427 | 
             
            }
         | 
    
        package/src/room/PCTransport.ts
    CHANGED
    
    | @@ -30,6 +30,8 @@ export default class PCTransport extends EventEmitter { | |
| 30 30 |  | 
| 31 31 | 
             
              remoteStereoMids: string[] = [];
         | 
| 32 32 |  | 
| 33 | 
            +
              remoteNackMids: string[] = [];
         | 
| 34 | 
            +
             | 
| 33 35 | 
             
              onOffer?: (offer: RTCSessionDescriptionInit) => void;
         | 
| 34 36 |  | 
| 35 37 | 
             
              constructor(config?: RTCConfiguration) {
         | 
| @@ -50,7 +52,9 @@ export default class PCTransport extends EventEmitter { | |
| 50 52 |  | 
| 51 53 | 
             
              async setRemoteDescription(sd: RTCSessionDescriptionInit): Promise<void> {
         | 
| 52 54 | 
             
                if (sd.type === 'offer') {
         | 
| 53 | 
            -
                   | 
| 55 | 
            +
                  let { stereoMids, nackMids } = extractStereoAndNackAudioFromOffer(sd);
         | 
| 56 | 
            +
                  this.remoteStereoMids = stereoMids;
         | 
| 57 | 
            +
                  this.remoteNackMids = nackMids;
         | 
| 54 58 | 
             
                }
         | 
| 55 59 | 
             
                await this.pc.setRemoteDescription(sd);
         | 
| 56 60 |  | 
| @@ -116,7 +120,7 @@ export default class PCTransport extends EventEmitter { | |
| 116 120 | 
             
                const sdpParsed = parse(offer.sdp ?? '');
         | 
| 117 121 | 
             
                sdpParsed.media.forEach((media) => {
         | 
| 118 122 | 
             
                  if (media.type === 'audio') {
         | 
| 119 | 
            -
                    ensureAudioNackAndStereo(media, []);
         | 
| 123 | 
            +
                    ensureAudioNackAndStereo(media, [], []);
         | 
| 120 124 | 
             
                  } else if (media.type === 'video') {
         | 
| 121 125 | 
             
                    // mung sdp for codec bitrate setting that can't apply by sendEncoding
         | 
| 122 126 | 
             
                    this.trackBitrates.some((trackbr): boolean => {
         | 
| @@ -169,7 +173,7 @@ export default class PCTransport extends EventEmitter { | |
| 169 173 | 
             
                const sdpParsed = parse(answer.sdp ?? '');
         | 
| 170 174 | 
             
                sdpParsed.media.forEach((media) => {
         | 
| 171 175 | 
             
                  if (media.type === 'audio') {
         | 
| 172 | 
            -
                    ensureAudioNackAndStereo(media, this.remoteStereoMids);
         | 
| 176 | 
            +
                    ensureAudioNackAndStereo(media, this.remoteStereoMids, this.remoteNackMids);
         | 
| 173 177 | 
             
                  }
         | 
| 174 178 | 
             
                });
         | 
| 175 179 | 
             
                await this.setMungedLocalDescription(answer, write(sdpParsed));
         | 
| @@ -226,6 +230,7 @@ function ensureAudioNackAndStereo( | |
| 226 230 | 
             
                payloads?: string | undefined;
         | 
| 227 231 | 
             
              } & MediaDescription,
         | 
| 228 232 | 
             
              stereoMids: string[],
         | 
| 233 | 
            +
              nackMids: string[],
         | 
| 229 234 | 
             
            ) {
         | 
| 230 235 | 
             
              // found opus codec to add nack fb
         | 
| 231 236 | 
             
              let opusPayload = 0;
         | 
| @@ -243,7 +248,10 @@ function ensureAudioNackAndStereo( | |
| 243 248 | 
             
                  media.rtcpFb = [];
         | 
| 244 249 | 
             
                }
         | 
| 245 250 |  | 
| 246 | 
            -
                if ( | 
| 251 | 
            +
                if (
         | 
| 252 | 
            +
                  nackMids.includes(media.mid!) &&
         | 
| 253 | 
            +
                  !media.rtcpFb.some((fb) => fb.payload === opusPayload && fb.type === 'nack')
         | 
| 254 | 
            +
                ) {
         | 
| 247 255 | 
             
                  media.rtcpFb.push({
         | 
| 248 256 | 
             
                    payload: opusPayload,
         | 
| 249 257 | 
             
                    type: 'nack',
         | 
| @@ -264,8 +272,12 @@ function ensureAudioNackAndStereo( | |
| 264 272 | 
             
              }
         | 
| 265 273 | 
             
            }
         | 
| 266 274 |  | 
| 267 | 
            -
            function  | 
| 275 | 
            +
            function extractStereoAndNackAudioFromOffer(offer: RTCSessionDescriptionInit): {
         | 
| 276 | 
            +
              stereoMids: string[];
         | 
| 277 | 
            +
              nackMids: string[];
         | 
| 278 | 
            +
            } {
         | 
| 268 279 | 
             
              const stereoMids: string[] = [];
         | 
| 280 | 
            +
              const nackMids: string[] = [];
         | 
| 269 281 | 
             
              const sdpParsed = parse(offer.sdp ?? '');
         | 
| 270 282 | 
             
              let opusPayload = 0;
         | 
| 271 283 | 
             
              sdpParsed.media.forEach((media) => {
         | 
| @@ -278,6 +290,10 @@ function extractStereoTracksFromOffer(offer: RTCSessionDescriptionInit): string[ | |
| 278 290 | 
             
                    return false;
         | 
| 279 291 | 
             
                  });
         | 
| 280 292 |  | 
| 293 | 
            +
                  if (media.rtcpFb?.some((fb) => fb.payload === opusPayload && fb.type === 'nack')) {
         | 
| 294 | 
            +
                    nackMids.push(media.mid!);
         | 
| 295 | 
            +
                  }
         | 
| 296 | 
            +
             | 
| 281 297 | 
             
                  media.fmtp.some((fmtp): boolean => {
         | 
| 282 298 | 
             
                    if (fmtp.payload === opusPayload) {
         | 
| 283 299 | 
             
                      if (fmtp.config.includes('sprop-stereo=1')) {
         | 
| @@ -289,5 +305,5 @@ function extractStereoTracksFromOffer(offer: RTCSessionDescriptionInit): string[ | |
| 289 305 | 
             
                  });
         | 
| 290 306 | 
             
                }
         | 
| 291 307 | 
             
              });
         | 
| 292 | 
            -
              return stereoMids;
         | 
| 308 | 
            +
              return { stereoMids, nackMids };
         | 
| 293 309 | 
             
            }
         | 
    
        package/src/room/RTCEngine.ts
    CHANGED
    
    | @@ -17,6 +17,7 @@ import { | |
| 17 17 | 
             
              AddTrackRequest,
         | 
| 18 18 | 
             
              JoinResponse,
         | 
| 19 19 | 
             
              LeaveRequest,
         | 
| 20 | 
            +
              ReconnectResponse,
         | 
| 20 21 | 
             
              SignalTarget,
         | 
| 21 22 | 
             
              TrackPublishedResponse,
         | 
| 22 23 | 
             
            } from '../proto/livekit_rtc';
         | 
| @@ -31,6 +32,7 @@ import { | |
| 31 32 | 
             
            import { EngineEvent } from './events';
         | 
| 32 33 | 
             
            import PCTransport, { PCEvents } from './PCTransport';
         | 
| 33 34 | 
             
            import type { ReconnectContext, ReconnectPolicy } from './ReconnectPolicy';
         | 
| 35 | 
            +
            import CriticalTimers from './timers';
         | 
| 34 36 | 
             
            import type LocalTrack from './track/LocalTrack';
         | 
| 35 37 | 
             
            import type LocalVideoTrack from './track/LocalVideoTrack';
         | 
| 36 38 | 
             
            import type { SimulcastTrackInfo } from './track/LocalVideoTrack';
         | 
| @@ -279,35 +281,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit | |
| 279 281 |  | 
| 280 282 | 
             
                this.participantSid = joinResponse.participant?.sid;
         | 
| 281 283 |  | 
| 282 | 
            -
                const rtcConfig =  | 
| 283 | 
            -
             | 
| 284 | 
            -
                // update ICE servers before creating PeerConnection
         | 
| 285 | 
            -
                if (joinResponse.iceServers && !rtcConfig.iceServers) {
         | 
| 286 | 
            -
                  const rtcIceServers: RTCIceServer[] = [];
         | 
| 287 | 
            -
                  joinResponse.iceServers.forEach((iceServer) => {
         | 
| 288 | 
            -
                    const rtcIceServer: RTCIceServer = {
         | 
| 289 | 
            -
                      urls: iceServer.urls,
         | 
| 290 | 
            -
                    };
         | 
| 291 | 
            -
                    if (iceServer.username) rtcIceServer.username = iceServer.username;
         | 
| 292 | 
            -
                    if (iceServer.credential) {
         | 
| 293 | 
            -
                      rtcIceServer.credential = iceServer.credential;
         | 
| 294 | 
            -
                    }
         | 
| 295 | 
            -
                    rtcIceServers.push(rtcIceServer);
         | 
| 296 | 
            -
                  });
         | 
| 297 | 
            -
                  rtcConfig.iceServers = rtcIceServers;
         | 
| 298 | 
            -
                }
         | 
| 299 | 
            -
             | 
| 300 | 
            -
                if (
         | 
| 301 | 
            -
                  joinResponse.clientConfiguration &&
         | 
| 302 | 
            -
                  joinResponse.clientConfiguration.forceRelay === ClientConfigSetting.ENABLED
         | 
| 303 | 
            -
                ) {
         | 
| 304 | 
            -
                  rtcConfig.iceTransportPolicy = 'relay';
         | 
| 305 | 
            -
                }
         | 
| 306 | 
            -
             | 
| 307 | 
            -
                // @ts-ignore
         | 
| 308 | 
            -
                rtcConfig.sdpSemantics = 'unified-plan';
         | 
| 309 | 
            -
                // @ts-ignore
         | 
| 310 | 
            -
                rtcConfig.continualGatheringPolicy = 'gather_continually';
         | 
| 284 | 
            +
                const rtcConfig = this.makeRTCConfiguration(joinResponse);
         | 
| 311 285 |  | 
| 312 286 | 
             
                this.publisher = new PCTransport(rtcConfig);
         | 
| 313 287 | 
             
                this.subscriber = new PCTransport(rtcConfig);
         | 
| @@ -448,6 +422,40 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit | |
| 448 422 | 
             
                };
         | 
| 449 423 | 
             
              }
         | 
| 450 424 |  | 
| 425 | 
            +
              private makeRTCConfiguration(serverResponse: JoinResponse | ReconnectResponse): RTCConfiguration {
         | 
| 426 | 
            +
                const rtcConfig = { ...this.rtcConfig };
         | 
| 427 | 
            +
             | 
| 428 | 
            +
                // update ICE servers before creating PeerConnection
         | 
| 429 | 
            +
                if (serverResponse.iceServers && !rtcConfig.iceServers) {
         | 
| 430 | 
            +
                  const rtcIceServers: RTCIceServer[] = [];
         | 
| 431 | 
            +
                  serverResponse.iceServers.forEach((iceServer) => {
         | 
| 432 | 
            +
                    const rtcIceServer: RTCIceServer = {
         | 
| 433 | 
            +
                      urls: iceServer.urls,
         | 
| 434 | 
            +
                    };
         | 
| 435 | 
            +
                    if (iceServer.username) rtcIceServer.username = iceServer.username;
         | 
| 436 | 
            +
                    if (iceServer.credential) {
         | 
| 437 | 
            +
                      rtcIceServer.credential = iceServer.credential;
         | 
| 438 | 
            +
                    }
         | 
| 439 | 
            +
                    rtcIceServers.push(rtcIceServer);
         | 
| 440 | 
            +
                  });
         | 
| 441 | 
            +
                  rtcConfig.iceServers = rtcIceServers;
         | 
| 442 | 
            +
                }
         | 
| 443 | 
            +
             | 
| 444 | 
            +
                if (
         | 
| 445 | 
            +
                  serverResponse.clientConfiguration &&
         | 
| 446 | 
            +
                  serverResponse.clientConfiguration.forceRelay === ClientConfigSetting.ENABLED
         | 
| 447 | 
            +
                ) {
         | 
| 448 | 
            +
                  rtcConfig.iceTransportPolicy = 'relay';
         | 
| 449 | 
            +
                }
         | 
| 450 | 
            +
             | 
| 451 | 
            +
                // @ts-ignore
         | 
| 452 | 
            +
                rtcConfig.sdpSemantics = 'unified-plan';
         | 
| 453 | 
            +
                // @ts-ignore
         | 
| 454 | 
            +
                rtcConfig.continualGatheringPolicy = 'gather_continually';
         | 
| 455 | 
            +
             | 
| 456 | 
            +
                return rtcConfig;
         | 
| 457 | 
            +
              }
         | 
| 458 | 
            +
             | 
| 451 459 | 
             
              private createDataChannels() {
         | 
| 452 460 | 
             
                if (!this.publisher) {
         | 
| 453 461 | 
             
                  return;
         | 
| @@ -673,14 +681,14 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit | |
| 673 681 | 
             
                  return;
         | 
| 674 682 | 
             
                }
         | 
| 675 683 |  | 
| 676 | 
            -
                log. | 
| 684 | 
            +
                log.warn(`${connection} disconnected`);
         | 
| 677 685 | 
             
                if (this.reconnectAttempts === 0) {
         | 
| 678 686 | 
             
                  // only reset start time on the first try
         | 
| 679 687 | 
             
                  this.reconnectStart = Date.now();
         | 
| 680 688 | 
             
                }
         | 
| 681 689 |  | 
| 682 690 | 
             
                const disconnect = (duration: number) => {
         | 
| 683 | 
            -
                  log. | 
| 691 | 
            +
                  log.warn(
         | 
| 684 692 | 
             
                    `could not recover connection after ${this.reconnectAttempts} attempts, ${duration}ms. giving up`,
         | 
| 685 693 | 
             
                  );
         | 
| 686 694 | 
             
                  this.emit(EngineEvent.Disconnected);
         | 
| @@ -703,10 +711,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit | |
| 703 711 |  | 
| 704 712 | 
             
                log.debug(`reconnecting in ${delay}ms`);
         | 
| 705 713 |  | 
| 706 | 
            -
                 | 
| 707 | 
            -
             | 
| 708 | 
            -
             | 
| 709 | 
            -
             | 
| 714 | 
            +
                this.clearReconnectTimeout();
         | 
| 715 | 
            +
                this.reconnectTimeout = CriticalTimers.setTimeout(
         | 
| 716 | 
            +
                  () => this.attemptReconnect(signalEvents),
         | 
| 717 | 
            +
                  delay,
         | 
| 718 | 
            +
                );
         | 
| 710 719 | 
             
              };
         | 
| 711 720 |  | 
| 712 721 | 
             
              private async attemptReconnect(signalEvents: boolean = false) {
         | 
| @@ -733,11 +742,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit | |
| 733 742 | 
             
                  } else {
         | 
| 734 743 | 
             
                    await this.resumeConnection(signalEvents);
         | 
| 735 744 | 
             
                  }
         | 
| 736 | 
            -
                  this. | 
| 745 | 
            +
                  this.clearPendingReconnect();
         | 
| 737 746 | 
             
                  this.fullReconnectOnNext = false;
         | 
| 738 | 
            -
                  if (this.reconnectTimeout) {
         | 
| 739 | 
            -
                    clearTimeout(this.reconnectTimeout);
         | 
| 740 | 
            -
                  }
         | 
| 741 747 | 
             
                } catch (e) {
         | 
| 742 748 | 
             
                  this.reconnectAttempts += 1;
         | 
| 743 749 | 
             
                  let reconnectRequired = false;
         | 
| @@ -841,7 +847,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit | |
| 841 847 | 
             
                }
         | 
| 842 848 |  | 
| 843 849 | 
             
                try {
         | 
| 844 | 
            -
                  await this.client.reconnect(this.url, this.token, this.participantSid);
         | 
| 850 | 
            +
                  const res = await this.client.reconnect(this.url, this.token, this.participantSid);
         | 
| 851 | 
            +
                  if (res) {
         | 
| 852 | 
            +
                    const rtcConfig = this.makeRTCConfiguration(res);
         | 
| 853 | 
            +
                    this.publisher.pc.setConfiguration(rtcConfig);
         | 
| 854 | 
            +
                    this.subscriber.pc.setConfiguration(rtcConfig);
         | 
| 855 | 
            +
                  }
         | 
| 845 856 | 
             
                } catch (e) {
         | 
| 846 857 | 
             
                  let message = '';
         | 
| 847 858 | 
             
                  if (e instanceof Error) {
         | 
| @@ -1034,19 +1045,21 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit | |
| 1034 1045 | 
             
                }
         | 
| 1035 1046 | 
             
              }
         | 
| 1036 1047 |  | 
| 1037 | 
            -
              private  | 
| 1048 | 
            +
              private clearReconnectTimeout() {
         | 
| 1038 1049 | 
             
                if (this.reconnectTimeout) {
         | 
| 1039 | 
            -
                  clearTimeout(this.reconnectTimeout);
         | 
| 1050 | 
            +
                  CriticalTimers.clearTimeout(this.reconnectTimeout);
         | 
| 1040 1051 | 
             
                }
         | 
| 1052 | 
            +
              }
         | 
| 1053 | 
            +
             | 
| 1054 | 
            +
              private clearPendingReconnect() {
         | 
| 1055 | 
            +
                this.clearReconnectTimeout();
         | 
| 1041 1056 | 
             
                this.reconnectAttempts = 0;
         | 
| 1042 1057 | 
             
              }
         | 
| 1043 1058 |  | 
| 1044 1059 | 
             
              private handleBrowserOnLine = () => {
         | 
| 1045 1060 | 
             
                // in case the engine is currently reconnecting, attempt a reconnect immediately after the browser state has changed to 'onLine'
         | 
| 1046 1061 | 
             
                if (this.client.isReconnecting) {
         | 
| 1047 | 
            -
                   | 
| 1048 | 
            -
                    clearTimeout(this.reconnectTimeout);
         | 
| 1049 | 
            -
                  }
         | 
| 1062 | 
            +
                  this.clearReconnectTimeout();
         | 
| 1050 1063 | 
             
                  this.attemptReconnect(true);
         | 
| 1051 1064 | 
             
                }
         | 
| 1052 1065 | 
             
              };
         |