@defcomm/meetingsdk 0.1.8 → 0.2.0
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/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +110 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +110 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -316,6 +316,8 @@ declare class SFUClient {
|
|
|
316
316
|
private maxReconnectAttempts;
|
|
317
317
|
private reconnectBaseMs;
|
|
318
318
|
private joinWaiter;
|
|
319
|
+
private transportRecoveryInProgress;
|
|
320
|
+
private transportRecoveryTimer;
|
|
319
321
|
private pendingIce;
|
|
320
322
|
private subscriberNegotiating;
|
|
321
323
|
private offerQueue;
|
|
@@ -353,6 +355,9 @@ declare class SFUClient {
|
|
|
353
355
|
private onError;
|
|
354
356
|
private autoSubscribe;
|
|
355
357
|
constructor(options?: SFUClientOptions);
|
|
358
|
+
private heartbeatTimer;
|
|
359
|
+
private startHeartbeat;
|
|
360
|
+
private stopHeartbeat;
|
|
356
361
|
private createId;
|
|
357
362
|
private resumeStorageKey;
|
|
358
363
|
private loadResumeToken;
|
|
@@ -421,6 +426,7 @@ declare class SFUClient {
|
|
|
421
426
|
private closePeerConnectionsOnly;
|
|
422
427
|
private cleanupAll;
|
|
423
428
|
private logSubscriberVideoStats;
|
|
429
|
+
private recoverWebRTC;
|
|
424
430
|
}
|
|
425
431
|
|
|
426
432
|
type PubSubHandle = {
|
package/dist/index.d.ts
CHANGED
|
@@ -316,6 +316,8 @@ declare class SFUClient {
|
|
|
316
316
|
private maxReconnectAttempts;
|
|
317
317
|
private reconnectBaseMs;
|
|
318
318
|
private joinWaiter;
|
|
319
|
+
private transportRecoveryInProgress;
|
|
320
|
+
private transportRecoveryTimer;
|
|
319
321
|
private pendingIce;
|
|
320
322
|
private subscriberNegotiating;
|
|
321
323
|
private offerQueue;
|
|
@@ -353,6 +355,9 @@ declare class SFUClient {
|
|
|
353
355
|
private onError;
|
|
354
356
|
private autoSubscribe;
|
|
355
357
|
constructor(options?: SFUClientOptions);
|
|
358
|
+
private heartbeatTimer;
|
|
359
|
+
private startHeartbeat;
|
|
360
|
+
private stopHeartbeat;
|
|
356
361
|
private createId;
|
|
357
362
|
private resumeStorageKey;
|
|
358
363
|
private loadResumeToken;
|
|
@@ -421,6 +426,7 @@ declare class SFUClient {
|
|
|
421
426
|
private closePeerConnectionsOnly;
|
|
422
427
|
private cleanupAll;
|
|
423
428
|
private logSubscriberVideoStats;
|
|
429
|
+
private recoverWebRTC;
|
|
424
430
|
}
|
|
425
431
|
|
|
426
432
|
type PubSubHandle = {
|
package/dist/index.js
CHANGED
|
@@ -408,6 +408,8 @@ var SFUClient = class {
|
|
|
408
408
|
this.maxReconnectAttempts = 8;
|
|
409
409
|
this.reconnectBaseMs = 750;
|
|
410
410
|
this.joinWaiter = null;
|
|
411
|
+
this.transportRecoveryInProgress = false;
|
|
412
|
+
this.transportRecoveryTimer = null;
|
|
411
413
|
this.pendingIce = {
|
|
412
414
|
publisher: [],
|
|
413
415
|
subscriber: []
|
|
@@ -426,6 +428,7 @@ var SFUClient = class {
|
|
|
426
428
|
this.trackToSource = /* @__PURE__ */ new Map();
|
|
427
429
|
this.localTrackIds = /* @__PURE__ */ new Map();
|
|
428
430
|
this.subscriberStatsTimer = null;
|
|
431
|
+
this.heartbeatTimer = null;
|
|
429
432
|
this.apiBase = options.apiBase || "https://api.example.com/api";
|
|
430
433
|
this.wsBase = options.wsBase || "wss://api.example.com/ws";
|
|
431
434
|
this.participantId = options.participantId || this.createId();
|
|
@@ -470,6 +473,24 @@ var SFUClient = class {
|
|
|
470
473
|
this.onError = options.onError || console.error;
|
|
471
474
|
this.autoSubscribe = options.autoSubscribe !== false;
|
|
472
475
|
}
|
|
476
|
+
startHeartbeat() {
|
|
477
|
+
this.stopHeartbeat();
|
|
478
|
+
this.heartbeatTimer = setInterval(() => {
|
|
479
|
+
if (this.ws?.readyState !== WebSocket.OPEN) return;
|
|
480
|
+
this.send({
|
|
481
|
+
type: "ping",
|
|
482
|
+
payload: {
|
|
483
|
+
nonce: crypto.randomUUID()
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
}, 1e4);
|
|
487
|
+
}
|
|
488
|
+
stopHeartbeat() {
|
|
489
|
+
if (this.heartbeatTimer) {
|
|
490
|
+
clearInterval(this.heartbeatTimer);
|
|
491
|
+
this.heartbeatTimer = null;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
473
494
|
createId() {
|
|
474
495
|
return typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `id_${Math.random().toString(36).slice(2)}_${Date.now()}`;
|
|
475
496
|
}
|
|
@@ -630,6 +651,7 @@ var SFUClient = class {
|
|
|
630
651
|
);
|
|
631
652
|
this.ws = ws;
|
|
632
653
|
ws.onopen = () => {
|
|
654
|
+
this.startHeartbeat();
|
|
633
655
|
this.setState("joining");
|
|
634
656
|
this.joiningWithResume = Boolean(this.resumeToken);
|
|
635
657
|
const joinPayload = {
|
|
@@ -653,6 +675,7 @@ var SFUClient = class {
|
|
|
653
675
|
this.onError(event);
|
|
654
676
|
};
|
|
655
677
|
ws.onclose = () => {
|
|
678
|
+
this.stopHeartbeat();
|
|
656
679
|
if (this.ws !== ws) return;
|
|
657
680
|
this.ws = null;
|
|
658
681
|
if (this.intentionalClose || this.state === "leaving") {
|
|
@@ -934,11 +957,21 @@ var SFUClient = class {
|
|
|
934
957
|
break;
|
|
935
958
|
}
|
|
936
959
|
case "error": {
|
|
937
|
-
const
|
|
938
|
-
this.
|
|
960
|
+
const message2 = payload.message || "SFU signaling error";
|
|
961
|
+
if (this.state === "reconnecting" && message2.includes("participant session is stale")) {
|
|
962
|
+
console.debug(
|
|
963
|
+
"[SFU] Ignoring stale-session error during recovery",
|
|
964
|
+
message2
|
|
965
|
+
);
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
const error = new Error(message2);
|
|
939
969
|
if (this.state === "joining" || this.state === "waiting_approval") {
|
|
970
|
+
this.onError(error);
|
|
940
971
|
this.failJoin(error);
|
|
972
|
+
return;
|
|
941
973
|
}
|
|
974
|
+
this.onError(error);
|
|
942
975
|
break;
|
|
943
976
|
}
|
|
944
977
|
default:
|
|
@@ -1016,17 +1049,49 @@ var SFUClient = class {
|
|
|
1016
1049
|
if (event.candidate) this.sendCandidate("subscriber", event.candidate);
|
|
1017
1050
|
};
|
|
1018
1051
|
this.publisher.onconnectionstatechange = () => {
|
|
1019
|
-
const
|
|
1052
|
+
const publisher = this.publisher;
|
|
1053
|
+
if (!publisher) return;
|
|
1054
|
+
const state = publisher.connectionState;
|
|
1055
|
+
console.debug("[SFU] Publisher connection state", {
|
|
1056
|
+
connectionState: publisher.connectionState,
|
|
1057
|
+
iceConnectionState: publisher.iceConnectionState,
|
|
1058
|
+
iceGatheringState: publisher.iceGatheringState,
|
|
1059
|
+
signalingState: publisher.signalingState
|
|
1060
|
+
});
|
|
1020
1061
|
if (state === "failed") {
|
|
1021
|
-
this.
|
|
1062
|
+
this.recoverWebRTC("publisher_failed");
|
|
1022
1063
|
}
|
|
1023
1064
|
};
|
|
1024
1065
|
this.subscriber.onconnectionstatechange = () => {
|
|
1025
|
-
const
|
|
1066
|
+
const subscriber = this.subscriber;
|
|
1067
|
+
if (!subscriber) return;
|
|
1068
|
+
const state = subscriber.connectionState;
|
|
1069
|
+
console.debug("[SFU] Subscriber connection state", {
|
|
1070
|
+
connectionState: subscriber.connectionState,
|
|
1071
|
+
iceConnectionState: subscriber.iceConnectionState,
|
|
1072
|
+
iceGatheringState: subscriber.iceGatheringState,
|
|
1073
|
+
signalingState: subscriber.signalingState
|
|
1074
|
+
});
|
|
1026
1075
|
if (state === "failed") {
|
|
1027
|
-
this.
|
|
1076
|
+
this.recoverWebRTC("subscriber_failed");
|
|
1028
1077
|
}
|
|
1029
1078
|
};
|
|
1079
|
+
this.publisher.oniceconnectionstatechange = () => {
|
|
1080
|
+
const publisher = this.publisher;
|
|
1081
|
+
if (!publisher) return;
|
|
1082
|
+
console.debug("[SFU] Publisher ICE state", {
|
|
1083
|
+
iceConnectionState: publisher.iceConnectionState,
|
|
1084
|
+
connectionState: publisher.connectionState
|
|
1085
|
+
});
|
|
1086
|
+
};
|
|
1087
|
+
this.subscriber.oniceconnectionstatechange = () => {
|
|
1088
|
+
const subscriber = this.subscriber;
|
|
1089
|
+
if (!subscriber) return;
|
|
1090
|
+
console.debug("[SFU] Subscriber ICE state", {
|
|
1091
|
+
iceConnectionState: subscriber.iceConnectionState,
|
|
1092
|
+
connectionState: subscriber.connectionState
|
|
1093
|
+
});
|
|
1094
|
+
};
|
|
1030
1095
|
this.subscriber.ontrack = (event) => {
|
|
1031
1096
|
void this.handleRemoteTrack(event);
|
|
1032
1097
|
};
|
|
@@ -1497,6 +1562,7 @@ var SFUClient = class {
|
|
|
1497
1562
|
}
|
|
1498
1563
|
}
|
|
1499
1564
|
async leave() {
|
|
1565
|
+
this.stopHeartbeat();
|
|
1500
1566
|
this.intentionalClose = true;
|
|
1501
1567
|
this.setState("leaving");
|
|
1502
1568
|
if (this.reconnectTimer) {
|
|
@@ -1632,6 +1698,44 @@ var SFUClient = class {
|
|
|
1632
1698
|
} catch {
|
|
1633
1699
|
}
|
|
1634
1700
|
}
|
|
1701
|
+
recoverWebRTC(reason) {
|
|
1702
|
+
if (this.intentionalClose) return;
|
|
1703
|
+
if (this.transportRecoveryInProgress) {
|
|
1704
|
+
console.debug("[SFU] WebRTC recovery already in progress", {
|
|
1705
|
+
reason
|
|
1706
|
+
});
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
this.transportRecoveryInProgress = true;
|
|
1710
|
+
console.warn("[SFU] WebRTC transport failed; starting recovery", {
|
|
1711
|
+
reason,
|
|
1712
|
+
publisherState: this.publisher?.connectionState,
|
|
1713
|
+
publisherIceState: this.publisher?.iceConnectionState,
|
|
1714
|
+
subscriberState: this.subscriber?.connectionState,
|
|
1715
|
+
subscriberIceState: this.subscriber?.iceConnectionState
|
|
1716
|
+
});
|
|
1717
|
+
this.setState("reconnecting");
|
|
1718
|
+
this.transportRecoveryTimer = setTimeout(() => {
|
|
1719
|
+
this.transportRecoveryTimer = null;
|
|
1720
|
+
if (this.intentionalClose) {
|
|
1721
|
+
this.transportRecoveryInProgress = false;
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
const ws = this.ws;
|
|
1725
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
1726
|
+
try {
|
|
1727
|
+
ws.close(4e3, "webrtc_recovery");
|
|
1728
|
+
} catch (error) {
|
|
1729
|
+
console.warn("[SFU] Failed to close WebSocket for recovery", error);
|
|
1730
|
+
this.transportRecoveryInProgress = false;
|
|
1731
|
+
this.scheduleReconnect();
|
|
1732
|
+
}
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
this.transportRecoveryInProgress = false;
|
|
1736
|
+
this.scheduleReconnect();
|
|
1737
|
+
}, 250);
|
|
1738
|
+
}
|
|
1635
1739
|
};
|
|
1636
1740
|
|
|
1637
1741
|
// src/core/VideoCore.ts
|