@afosecure/meetingsdk 1.3.1 → 1.3.3
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 +2 -21
- package/dist/index.d.ts +2 -21
- package/dist/index.js +64 -163
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +64 -163
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -177,8 +177,7 @@ var VideoSDKCore = class {
|
|
|
177
177
|
this.localStream = null;
|
|
178
178
|
this.screenStream = null;
|
|
179
179
|
this.isScreenSharing = false;
|
|
180
|
-
|
|
181
|
-
this.peerTransceivers = {};
|
|
180
|
+
this.screenSenders = {};
|
|
182
181
|
this.pingInterval = null;
|
|
183
182
|
this.pendingIceCandidates = {};
|
|
184
183
|
this.pendingOffers = {};
|
|
@@ -207,7 +206,7 @@ var VideoSDKCore = class {
|
|
|
207
206
|
this.joinRejecter = void 0;
|
|
208
207
|
console.error("[MeetingSDK Error]", err);
|
|
209
208
|
}
|
|
210
|
-
// STREAM
|
|
209
|
+
// ---------------- STREAM ----------------
|
|
211
210
|
async initLocal(video, name) {
|
|
212
211
|
this.participantName = name;
|
|
213
212
|
try {
|
|
@@ -244,7 +243,7 @@ var VideoSDKCore = class {
|
|
|
244
243
|
throw err;
|
|
245
244
|
}
|
|
246
245
|
}
|
|
247
|
-
// CONNECT
|
|
246
|
+
// ---------------- CONNECT ----------------
|
|
248
247
|
async connect(roomId, name) {
|
|
249
248
|
this.room.id = roomId;
|
|
250
249
|
this.reset();
|
|
@@ -390,11 +389,10 @@ var VideoSDKCore = class {
|
|
|
390
389
|
this.pingInterval = null;
|
|
391
390
|
}
|
|
392
391
|
}
|
|
393
|
-
// RESET
|
|
392
|
+
// ---------------- RESET ----------------
|
|
394
393
|
reset() {
|
|
395
394
|
Object.values(this.peers).forEach((pc) => pc.close());
|
|
396
395
|
this.peers = {};
|
|
397
|
-
this.peerTransceivers = {};
|
|
398
396
|
this.initiators.clear();
|
|
399
397
|
this.pendingIceCandidates = {};
|
|
400
398
|
this.state.resetRemoteState();
|
|
@@ -449,7 +447,6 @@ var VideoSDKCore = class {
|
|
|
449
447
|
type: "answer",
|
|
450
448
|
sdp: msg.payload
|
|
451
449
|
});
|
|
452
|
-
this.captureScreenMid(msg.sender);
|
|
453
450
|
await this.flushIce(msg.sender, pc);
|
|
454
451
|
} catch (err) {
|
|
455
452
|
console.error("[Signaling] Failed to apply answer:", err);
|
|
@@ -486,6 +483,7 @@ var VideoSDKCore = class {
|
|
|
486
483
|
if (msg.presenterId) {
|
|
487
484
|
this.state.setPresenterId(msg.presenterId);
|
|
488
485
|
this.events.onScreenShareStarted?.(msg.presenterId, null);
|
|
486
|
+
this.state.setPresenterId(msg.presenterId);
|
|
489
487
|
}
|
|
490
488
|
for (const p of msg.participants || []) {
|
|
491
489
|
if (!p?.id || p.id === this.myId) continue;
|
|
@@ -568,10 +566,12 @@ var VideoSDKCore = class {
|
|
|
568
566
|
});
|
|
569
567
|
break;
|
|
570
568
|
}
|
|
569
|
+
// ============ NEW: HANDLE JOIN_APPROVED WITH RECONNECT ============
|
|
571
570
|
case "JOIN_APPROVED": {
|
|
572
571
|
await this.handleJoinApproved(msg);
|
|
573
572
|
break;
|
|
574
573
|
}
|
|
574
|
+
// ============ END: JOIN_APPROVED ============
|
|
575
575
|
case "JOIN_REJECTED": {
|
|
576
576
|
const decision = "rejected";
|
|
577
577
|
console.log("JOIN_REJECTED - user not allowed to join");
|
|
@@ -624,7 +624,8 @@ var VideoSDKCore = class {
|
|
|
624
624
|
if (!this.state.presenterId) {
|
|
625
625
|
this.state.setPresenterId(peerId2);
|
|
626
626
|
}
|
|
627
|
-
this.
|
|
627
|
+
const screenStream = this.state.getParticipant(peerId2)?.media?.screenStream;
|
|
628
|
+
this.events.onScreenShareStarted?.(peerId2, screenStream || null);
|
|
628
629
|
break;
|
|
629
630
|
}
|
|
630
631
|
case "SCREEN_SHARE_STOP": {
|
|
@@ -651,17 +652,8 @@ var VideoSDKCore = class {
|
|
|
651
652
|
}
|
|
652
653
|
}
|
|
653
654
|
}
|
|
654
|
-
// PEER
|
|
655
|
-
|
|
656
|
-
* Create a peer connection with pre-established transceiver layout:
|
|
657
|
-
* - Audio transceiver (sendrecv)
|
|
658
|
-
* - Camera video transceiver (sendrecv)
|
|
659
|
-
* - Screen video transceiver (initially recvonly, becomes sendrecv when sharing)
|
|
660
|
-
*
|
|
661
|
-
* This fixed layout ensures late joiners get the screen transceiver m-line
|
|
662
|
-
* negotiated from the very first offer, even if no one is sharing yet.
|
|
663
|
-
*/
|
|
664
|
-
async createPeer(id) {
|
|
655
|
+
// ---------------- PEER ----------------
|
|
656
|
+
createPeer(id) {
|
|
665
657
|
if (!this.localStream) throw new Error("No local stream");
|
|
666
658
|
if (!this.iceServers || this.iceServers.length === 0) {
|
|
667
659
|
throw new Error(
|
|
@@ -669,9 +661,7 @@ var VideoSDKCore = class {
|
|
|
669
661
|
);
|
|
670
662
|
}
|
|
671
663
|
console.log(
|
|
672
|
-
"
|
|
673
|
-
id,
|
|
674
|
-
"with tracks:",
|
|
664
|
+
"Adding tracks",
|
|
675
665
|
this.localStream.getTracks().map((t) => ({
|
|
676
666
|
kind: t.kind,
|
|
677
667
|
enabled: t.enabled,
|
|
@@ -681,52 +671,25 @@ var VideoSDKCore = class {
|
|
|
681
671
|
const pc = new RTCPeerConnection({
|
|
682
672
|
iceServers: this.iceServers
|
|
683
673
|
});
|
|
684
|
-
const audioTransceiver = pc.addTransceiver("audio", {
|
|
685
|
-
direction: "sendrecv"
|
|
686
|
-
});
|
|
687
|
-
const audioTrack = this.localStream.getAudioTracks()[0];
|
|
688
|
-
if (audioTrack) {
|
|
689
|
-
await audioTransceiver.sender.replaceTrack(audioTrack);
|
|
690
|
-
}
|
|
691
|
-
const cameraTransceiver = pc.addTransceiver("video", {
|
|
692
|
-
direction: "sendrecv"
|
|
693
|
-
});
|
|
694
|
-
const videoTrack = this.localStream.getVideoTracks()[0];
|
|
695
|
-
if (videoTrack) {
|
|
696
|
-
await cameraTransceiver.sender.replaceTrack(videoTrack);
|
|
697
|
-
}
|
|
698
|
-
const screenTransceiver = pc.addTransceiver("video", {
|
|
699
|
-
direction: this.isScreenSharing ? "sendrecv" : "recvonly"
|
|
700
|
-
});
|
|
701
|
-
if (this.isScreenSharing && this.screenStream) {
|
|
702
|
-
const screenTrack = this.screenStream.getVideoTracks()[0];
|
|
703
|
-
if (screenTrack) {
|
|
704
|
-
await screenTransceiver.sender.replaceTrack(screenTrack);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
this.peerTransceivers[id] = {
|
|
708
|
-
cameraTransceiver,
|
|
709
|
-
screenTransceiver,
|
|
710
|
-
screenMid: null
|
|
711
|
-
// will be populated after negotiation
|
|
712
|
-
};
|
|
713
674
|
pc.ontrack = (event) => {
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
console.log(
|
|
717
|
-
|
|
718
|
-
);
|
|
675
|
+
console.log("ontrack");
|
|
676
|
+
console.log("kind:", event.track.kind);
|
|
677
|
+
console.log("mid:", event.transceiver.mid);
|
|
678
|
+
console.log("streams:", event.streams);
|
|
679
|
+
console.log("stream id:", event.streams[0]?.id);
|
|
719
680
|
const incomingStream = event.streams?.[0] || new MediaStream([event.track]);
|
|
681
|
+
const participant = this.state.getParticipant(id);
|
|
682
|
+
const isScreenStream = participant?.media?.isScreenSharing && incomingStream.id === participant?.media?.remoteScreenStreamId;
|
|
720
683
|
if (event.track.muted) {
|
|
721
684
|
event.track.onunmute = () => {
|
|
722
|
-
console.log(
|
|
685
|
+
console.log(`${event.track.kind} track unmuted for ${id}`);
|
|
723
686
|
};
|
|
724
687
|
}
|
|
725
|
-
if (
|
|
726
|
-
const
|
|
688
|
+
if (isScreenStream) {
|
|
689
|
+
const videoTrack = event.track.kind === "video" ? event.track : incomingStream.getVideoTracks()[0] || participant?.media?.screenTrack;
|
|
727
690
|
this.state.updateParticipantMedia(id, {
|
|
728
691
|
screenStream: incomingStream,
|
|
729
|
-
screenTrack:
|
|
692
|
+
screenTrack: videoTrack,
|
|
730
693
|
isScreenSharing: true
|
|
731
694
|
});
|
|
732
695
|
if (!this.state.presenterId) {
|
|
@@ -752,41 +715,29 @@ var VideoSDKCore = class {
|
|
|
752
715
|
});
|
|
753
716
|
};
|
|
754
717
|
pc.oniceconnectionstatechange = () => {
|
|
755
|
-
console.log(`
|
|
718
|
+
console.log(`ICE Connection State: ${pc.iceConnectionState}`);
|
|
756
719
|
};
|
|
757
720
|
pc.onconnectionstatechange = () => {
|
|
758
|
-
console.log(`[Connection] ${id}: ${pc.connectionState}`);
|
|
759
721
|
if (pc.connectionState === "failed") {
|
|
760
722
|
try {
|
|
761
723
|
pc.restartIce();
|
|
762
|
-
} catch
|
|
763
|
-
console.warn("Failed to restart ICE:", e);
|
|
724
|
+
} catch {
|
|
764
725
|
}
|
|
765
726
|
}
|
|
766
727
|
};
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
const transceivers = pc.getTransceivers();
|
|
777
|
-
const screenTransceiver = this.peerTransceivers[peerId]?.screenTransceiver;
|
|
778
|
-
if (!screenTransceiver) return;
|
|
779
|
-
const negotiatedTransceiver = transceivers.find(
|
|
780
|
-
(t) => t === screenTransceiver
|
|
781
|
-
);
|
|
782
|
-
if (negotiatedTransceiver?.mid) {
|
|
783
|
-
this.peerTransceivers[peerId].screenMid = negotiatedTransceiver.mid;
|
|
784
|
-
console.log(
|
|
785
|
-
`[Negotiation] Captured screenMid for ${peerId}: ${negotiatedTransceiver.mid}`
|
|
786
|
-
);
|
|
728
|
+
this.localStream.getTracks().forEach((track) => {
|
|
729
|
+
pc.addTrack(track, this.localStream);
|
|
730
|
+
});
|
|
731
|
+
if (this.isScreenSharing && this.screenStream) {
|
|
732
|
+
this.screenSenders[id] = [];
|
|
733
|
+
this.screenStream.getTracks().forEach((track) => {
|
|
734
|
+
const sender = pc.addTrack(track, this.screenStream);
|
|
735
|
+
this.screenSenders[id].push(sender);
|
|
736
|
+
});
|
|
787
737
|
}
|
|
738
|
+
return pc;
|
|
788
739
|
}
|
|
789
|
-
// OFFER
|
|
740
|
+
// ---------------- OFFER ----------------
|
|
790
741
|
async createOffer(id, isRenegotiation = false) {
|
|
791
742
|
if (!isRenegotiation && !this.shouldInitiate(id)) {
|
|
792
743
|
console.debug(
|
|
@@ -804,13 +755,12 @@ var VideoSDKCore = class {
|
|
|
804
755
|
this.initiators.add(id);
|
|
805
756
|
}
|
|
806
757
|
if (!this.peers[id]) {
|
|
807
|
-
this.peers[id] =
|
|
758
|
+
this.peers[id] = this.createPeer(id);
|
|
808
759
|
}
|
|
809
760
|
const pc = this.peers[id];
|
|
810
761
|
try {
|
|
811
762
|
const offer = await pc.createOffer();
|
|
812
763
|
await pc.setLocalDescription(offer);
|
|
813
|
-
this.captureScreenMid(id);
|
|
814
764
|
this.send({
|
|
815
765
|
type: "OFFER",
|
|
816
766
|
payload: offer.sdp,
|
|
@@ -820,18 +770,12 @@ var VideoSDKCore = class {
|
|
|
820
770
|
console.debug(`[Offer] Sent to ${id}`);
|
|
821
771
|
} catch (err) {
|
|
822
772
|
console.error(`[Offer] Failed for ${id}:`, err);
|
|
823
|
-
this.emitError(
|
|
824
|
-
"OFFER_CREATION_FAILED",
|
|
825
|
-
`Failed to create offer for ${id}`,
|
|
826
|
-
err,
|
|
827
|
-
true
|
|
828
|
-
);
|
|
829
773
|
}
|
|
830
774
|
}
|
|
831
775
|
shouldInitiate(peerId) {
|
|
832
776
|
return this.myId < peerId;
|
|
833
777
|
}
|
|
834
|
-
// ANSWER
|
|
778
|
+
// ---------------- ANSWER ----------------
|
|
835
779
|
async handleOffer(sdp, id) {
|
|
836
780
|
if (!this.iceServers || this.iceServers.length === 0) {
|
|
837
781
|
console.warn("[Offer] Waiting for iceServers, queuing offer from", id);
|
|
@@ -839,7 +783,7 @@ var VideoSDKCore = class {
|
|
|
839
783
|
return;
|
|
840
784
|
}
|
|
841
785
|
if (!this.peers[id]) {
|
|
842
|
-
this.peers[id] =
|
|
786
|
+
this.peers[id] = this.createPeer(id);
|
|
843
787
|
}
|
|
844
788
|
const pc = this.peers[id];
|
|
845
789
|
try {
|
|
@@ -855,9 +799,8 @@ var VideoSDKCore = class {
|
|
|
855
799
|
);
|
|
856
800
|
pc.close();
|
|
857
801
|
delete this.peers[id];
|
|
858
|
-
delete this.peerTransceivers[id];
|
|
859
802
|
this.initiators.delete(id);
|
|
860
|
-
this.peers[id] =
|
|
803
|
+
this.peers[id] = this.createPeer(id);
|
|
861
804
|
}
|
|
862
805
|
}
|
|
863
806
|
if (this.peers[id].signalingState !== "stable" && this.peers[id].signalingState !== "have-local-offer") {
|
|
@@ -870,7 +813,6 @@ var VideoSDKCore = class {
|
|
|
870
813
|
type: "offer",
|
|
871
814
|
sdp
|
|
872
815
|
});
|
|
873
|
-
this.captureScreenMid(id);
|
|
874
816
|
const pending = this.pendingIceCandidates[id] || [];
|
|
875
817
|
for (const candidate of pending) {
|
|
876
818
|
try {
|
|
@@ -900,26 +842,18 @@ var VideoSDKCore = class {
|
|
|
900
842
|
);
|
|
901
843
|
}
|
|
902
844
|
}
|
|
903
|
-
// CLEANUP
|
|
845
|
+
// ---------------- CLEANUP ----------------
|
|
904
846
|
closePeer(id) {
|
|
905
847
|
const pc = this.peers[id];
|
|
906
848
|
if (!pc) return;
|
|
907
849
|
pc.ontrack = null;
|
|
908
850
|
pc.onicecandidate = null;
|
|
909
851
|
pc.onconnectionstatechange = null;
|
|
910
|
-
pc.oniceconnectionstatechange = null;
|
|
911
852
|
pc.close();
|
|
912
853
|
delete this.peers[id];
|
|
913
|
-
delete this.peerTransceivers[id];
|
|
914
854
|
this.initiators.delete(id);
|
|
915
855
|
this.state.removeParticipant(id);
|
|
916
856
|
}
|
|
917
|
-
// SCREEN SHARE (TRANSCEIVER-BASED)
|
|
918
|
-
/**
|
|
919
|
-
* Start screen sharing using replaceTrack on the pre-established screen transceiver.
|
|
920
|
-
* No need to add/remove tracks, no renegotiation needed (transceiver already in SDP).
|
|
921
|
-
* Just swap the track and update direction if needed.
|
|
922
|
-
*/
|
|
923
857
|
async startScreenShare() {
|
|
924
858
|
try {
|
|
925
859
|
if (this.state.presenterId && this.state.presenterId !== this.myId) {
|
|
@@ -930,55 +864,34 @@ var VideoSDKCore = class {
|
|
|
930
864
|
}
|
|
931
865
|
this.screenStream = await navigator.mediaDevices.getDisplayMedia({
|
|
932
866
|
video: true
|
|
867
|
+
// audio: true,
|
|
933
868
|
});
|
|
934
|
-
const screenTrack = this.screenStream.getVideoTracks()[0];
|
|
935
|
-
if (!screenTrack) {
|
|
936
|
-
throw new Error("No video track in screen stream");
|
|
937
|
-
}
|
|
938
869
|
this.isScreenSharing = true;
|
|
939
870
|
this.state.updateLocalParticipant({
|
|
940
871
|
media: {
|
|
941
872
|
isScreenSharing: true,
|
|
942
873
|
screenStream: this.screenStream,
|
|
943
|
-
screenTrack
|
|
874
|
+
screenTrack: this.screenStream.getVideoTracks()[0]
|
|
944
875
|
}
|
|
945
876
|
});
|
|
946
877
|
this.state.setPresenterId(this.myId);
|
|
947
|
-
|
|
948
|
-
console.log("[Screen Share] User stopped via browser button");
|
|
878
|
+
this.screenStream.getVideoTracks()[0].onended = () => {
|
|
949
879
|
this.stopScreenShare();
|
|
950
880
|
};
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
try {
|
|
960
|
-
await txInfo.screenTransceiver.sender.replaceTrack(screenTrack);
|
|
961
|
-
if (txInfo.screenTransceiver.currentDirection === "recvonly") {
|
|
962
|
-
txInfo.screenTransceiver.direction = "sendrecv";
|
|
963
|
-
console.log(
|
|
964
|
-
`[Screen Share] Flipped ${peerId} screen transceiver to sendrecv`
|
|
965
|
-
);
|
|
966
|
-
await this.createOffer(peerId, true);
|
|
967
|
-
}
|
|
968
|
-
} catch (err) {
|
|
969
|
-
console.error(
|
|
970
|
-
`[Screen Share] Failed to update transceiver for ${peerId}:`,
|
|
971
|
-
err
|
|
972
|
-
);
|
|
973
|
-
}
|
|
974
|
-
}
|
|
881
|
+
Object.entries(this.peers).forEach(([peerId, pc]) => {
|
|
882
|
+
this.screenSenders[peerId] = [];
|
|
883
|
+
this.screenStream.getTracks().forEach((track) => {
|
|
884
|
+
const sender = pc.addTrack(track, this.screenStream);
|
|
885
|
+
this.screenSenders[peerId].push(sender);
|
|
886
|
+
});
|
|
887
|
+
this.createOffer(peerId, true);
|
|
888
|
+
});
|
|
975
889
|
this.send({
|
|
976
890
|
type: "SCREEN_SHARE_START",
|
|
977
891
|
sender: this.myId,
|
|
978
892
|
room_id: this.room.id,
|
|
979
893
|
stream_id: this.screenStream.id.replace(/[{}]/g, "")
|
|
980
894
|
});
|
|
981
|
-
console.log("[Screen Share] Started successfully");
|
|
982
895
|
return this.screenStream;
|
|
983
896
|
} catch (err) {
|
|
984
897
|
this.emitError(
|
|
@@ -992,29 +905,21 @@ var VideoSDKCore = class {
|
|
|
992
905
|
throw err;
|
|
993
906
|
}
|
|
994
907
|
}
|
|
995
|
-
|
|
908
|
+
stopScreenShare() {
|
|
996
909
|
if (!this.screenStream) return;
|
|
997
|
-
console.log("[Screen Share] Stopping...");
|
|
998
910
|
this.screenStream.getTracks().forEach((t) => t.stop());
|
|
999
|
-
|
|
1000
|
-
const
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
console.log(
|
|
1007
|
-
`[Screen Share] Flipped ${peerId} screen transceiver to recvonly`
|
|
1008
|
-
);
|
|
1009
|
-
await this.createOffer(peerId, true);
|
|
911
|
+
Object.entries(this.peers).forEach(([peerId, pc]) => {
|
|
912
|
+
const senders = this.screenSenders[peerId] || [];
|
|
913
|
+
senders.forEach((sender) => {
|
|
914
|
+
try {
|
|
915
|
+
pc.removeTrack(sender);
|
|
916
|
+
} catch (err) {
|
|
917
|
+
console.warn(err);
|
|
1010
918
|
}
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
);
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
919
|
+
});
|
|
920
|
+
delete this.screenSenders[peerId];
|
|
921
|
+
this.createOffer(peerId, true);
|
|
922
|
+
});
|
|
1018
923
|
this.screenStream = null;
|
|
1019
924
|
this.isScreenSharing = false;
|
|
1020
925
|
this.state.updateLocalParticipant({
|
|
@@ -1032,9 +937,7 @@ var VideoSDKCore = class {
|
|
|
1032
937
|
sender: this.myId,
|
|
1033
938
|
room_id: this.room.id
|
|
1034
939
|
});
|
|
1035
|
-
console.log("[Screen Share] Stopped");
|
|
1036
940
|
}
|
|
1037
|
-
// CHAT
|
|
1038
941
|
sendChatMessage(payload) {
|
|
1039
942
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
1040
943
|
console.warn("WS not connected");
|
|
@@ -1067,13 +970,11 @@ var VideoSDKCore = class {
|
|
|
1067
970
|
client_ts: Date.now()
|
|
1068
971
|
});
|
|
1069
972
|
}
|
|
1070
|
-
// DISCONNECT
|
|
1071
973
|
disconnect() {
|
|
1072
974
|
this.intentionalDisconnect = true;
|
|
1073
975
|
this.stopScreenShare();
|
|
1074
976
|
Object.values(this.peers).forEach((pc) => pc.close());
|
|
1075
977
|
this.peers = {};
|
|
1076
|
-
this.peerTransceivers = {};
|
|
1077
978
|
this.initiators.clear();
|
|
1078
979
|
this.stopHeartbeat();
|
|
1079
980
|
if (this.ws?.readyState === WebSocket.OPEN) {
|