@afosecure/meetingsdk 1.0.8 → 1.1.1
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.js +208 -83
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +208 -83
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -430,6 +430,7 @@ var VideoSDKCore = class {
|
|
|
430
430
|
if (!p?.id || p.id === this.myId) return;
|
|
431
431
|
this.state.addParticipant(p);
|
|
432
432
|
this.events.onUserJoined?.(p);
|
|
433
|
+
await this.createOffer(p.id);
|
|
433
434
|
break;
|
|
434
435
|
}
|
|
435
436
|
case "OFFER":
|
|
@@ -439,14 +440,26 @@ var VideoSDKCore = class {
|
|
|
439
440
|
const pc = this.peers[msg.sender];
|
|
440
441
|
if (!pc) return;
|
|
441
442
|
if (pc.signalingState !== "have-local-offer") {
|
|
442
|
-
console.warn(
|
|
443
|
+
console.warn(
|
|
444
|
+
`[Signaling] Unexpected ANSWER in state "${pc.signalingState}", ignoring`
|
|
445
|
+
);
|
|
443
446
|
return;
|
|
444
447
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
448
|
+
try {
|
|
449
|
+
await pc.setRemoteDescription({
|
|
450
|
+
type: "answer",
|
|
451
|
+
sdp: msg.payload
|
|
452
|
+
});
|
|
453
|
+
await this.flushIce(msg.sender, pc);
|
|
454
|
+
} catch (err) {
|
|
455
|
+
console.error("[Signaling] Failed to apply answer:", err);
|
|
456
|
+
this.emitError(
|
|
457
|
+
"ANSWER_FAILED",
|
|
458
|
+
`Failed to apply answer from ${msg.sender}`,
|
|
459
|
+
err,
|
|
460
|
+
true
|
|
461
|
+
);
|
|
462
|
+
}
|
|
450
463
|
break;
|
|
451
464
|
}
|
|
452
465
|
case "ICE": {
|
|
@@ -541,17 +554,47 @@ var VideoSDKCore = class {
|
|
|
541
554
|
// ---------------- PEER ----------------
|
|
542
555
|
createPeer(id) {
|
|
543
556
|
if (!this.localStream) throw new Error("No local stream");
|
|
557
|
+
console.log(
|
|
558
|
+
"Adding tracks",
|
|
559
|
+
this.localStream.getTracks().map((t) => ({
|
|
560
|
+
kind: t.kind,
|
|
561
|
+
enabled: t.enabled,
|
|
562
|
+
state: t.readyState
|
|
563
|
+
}))
|
|
564
|
+
);
|
|
544
565
|
const pc = new RTCPeerConnection({
|
|
545
566
|
iceServers: [
|
|
546
567
|
{
|
|
547
|
-
urls:
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
568
|
+
urls: "stun:stun.relay.metered.ca:80"
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
urls: "turn:global.relay.metered.ca:80",
|
|
572
|
+
username: "25aed888d2d360e9fae0e812",
|
|
573
|
+
credential: "WPYstojO9Wf3+HsQ"
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
urls: "turn:global.relay.metered.ca:80?transport=tcp",
|
|
577
|
+
username: "25aed888d2d360e9fae0e812",
|
|
578
|
+
credential: "WPYstojO9Wf3+HsQ"
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
urls: "turn:global.relay.metered.ca:443",
|
|
582
|
+
username: "25aed888d2d360e9fae0e812",
|
|
583
|
+
credential: "WPYstojO9Wf3+HsQ"
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
urls: "turns:global.relay.metered.ca:443?transport=tcp",
|
|
587
|
+
username: "25aed888d2d360e9fae0e812",
|
|
588
|
+
credential: "WPYstojO9Wf3+HsQ"
|
|
551
589
|
}
|
|
552
590
|
]
|
|
553
591
|
});
|
|
554
592
|
pc.ontrack = (event) => {
|
|
593
|
+
console.log(`Track received: ${event.track.kind}`, {
|
|
594
|
+
trackId: event.track.id,
|
|
595
|
+
streamCount: event.streams.length,
|
|
596
|
+
streamTrackCount: event.streams[0]?.getTracks().length
|
|
597
|
+
});
|
|
555
598
|
const incomingStream = event.streams[0];
|
|
556
599
|
const participant = this.state.getParticipant(id);
|
|
557
600
|
const isScreenStream = incomingStream.id === participant?.media?.remoteScreenStreamId;
|
|
@@ -584,6 +627,15 @@ var VideoSDKCore = class {
|
|
|
584
627
|
target: id
|
|
585
628
|
});
|
|
586
629
|
};
|
|
630
|
+
pc.oniceconnectionstatechange = () => {
|
|
631
|
+
console.log(`ICE Connection State: ${pc.iceConnectionState}`);
|
|
632
|
+
if (pc.iceConnectionState === "failed" || pc.iceConnectionState === "disconnected") {
|
|
633
|
+
this.emitError(
|
|
634
|
+
"ICE_FAILED",
|
|
635
|
+
"Connection failed. Please check your network or refresh."
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
};
|
|
587
639
|
pc.onconnectionstatechange = () => {
|
|
588
640
|
if (pc.connectionState === "failed") {
|
|
589
641
|
try {
|
|
@@ -606,7 +658,21 @@ var VideoSDKCore = class {
|
|
|
606
658
|
}
|
|
607
659
|
// ---------------- OFFER ----------------
|
|
608
660
|
async createOffer(id, isRenegotiation = false) {
|
|
609
|
-
if (!isRenegotiation && this.initiators.has(id))
|
|
661
|
+
if (!isRenegotiation && this.initiators.has(id)) {
|
|
662
|
+
console.debug(
|
|
663
|
+
`[Offer] Already initiating with ${id}, skipping duplicate`
|
|
664
|
+
);
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
if (isRenegotiation && this.peers[id]) {
|
|
668
|
+
const pc2 = this.peers[id];
|
|
669
|
+
if (pc2.signalingState !== "stable") {
|
|
670
|
+
console.warn(
|
|
671
|
+
`[Offer] Cannot renegotiate: peer in state "${pc2.signalingState}"`
|
|
672
|
+
);
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
610
676
|
if (!isRenegotiation) {
|
|
611
677
|
this.initiators.add(id);
|
|
612
678
|
}
|
|
@@ -614,46 +680,80 @@ var VideoSDKCore = class {
|
|
|
614
680
|
this.peers[id] = this.createPeer(id);
|
|
615
681
|
}
|
|
616
682
|
const pc = this.peers[id];
|
|
617
|
-
|
|
618
|
-
|
|
683
|
+
try {
|
|
684
|
+
const offer = await pc.createOffer();
|
|
685
|
+
await pc.setLocalDescription(offer);
|
|
686
|
+
this.send({
|
|
687
|
+
type: "OFFER",
|
|
688
|
+
payload: offer.sdp,
|
|
689
|
+
sender: this.myId,
|
|
690
|
+
target: id
|
|
691
|
+
});
|
|
692
|
+
console.debug(`[Offer] Sent to ${id}`);
|
|
693
|
+
} catch (err) {
|
|
694
|
+
console.error(`[Offer] Failed for ${id}:`, err);
|
|
695
|
+
this.emitError(
|
|
696
|
+
"OFFER_FAILED",
|
|
697
|
+
`Failed to create offer for ${id}`,
|
|
698
|
+
err,
|
|
699
|
+
true
|
|
700
|
+
);
|
|
619
701
|
}
|
|
620
|
-
const offer = await pc.createOffer();
|
|
621
|
-
await pc.setLocalDescription(offer);
|
|
622
|
-
this.send({
|
|
623
|
-
type: "OFFER",
|
|
624
|
-
payload: offer.sdp,
|
|
625
|
-
sender: this.myId,
|
|
626
|
-
target: id
|
|
627
|
-
});
|
|
628
702
|
}
|
|
629
703
|
// ---------------- ANSWER ----------------
|
|
630
704
|
async handleOffer(sdp, id) {
|
|
705
|
+
if (this.initiators.has(id) && this.peers[id]) {
|
|
706
|
+
const pc2 = this.peers[id];
|
|
707
|
+
if (pc2.signalingState !== "stable") {
|
|
708
|
+
console.warn(
|
|
709
|
+
`[Signaling] Offer collision with ${id}. We initiated, ignoring their offer.`
|
|
710
|
+
);
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
631
714
|
if (!this.peers[id]) {
|
|
632
715
|
this.peers[id] = this.createPeer(id);
|
|
633
716
|
}
|
|
634
717
|
const pc = this.peers[id];
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
718
|
+
try {
|
|
719
|
+
if (pc.signalingState !== "stable" && pc.signalingState !== "have-local-offer") {
|
|
720
|
+
console.warn(
|
|
721
|
+
`[Signaling] Cannot accept OFFER in state "${pc.signalingState}"`
|
|
722
|
+
);
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
await pc.setRemoteDescription({
|
|
726
|
+
type: "offer",
|
|
727
|
+
sdp
|
|
728
|
+
});
|
|
729
|
+
const pending = this.pendingIceCandidates[id] || [];
|
|
730
|
+
for (const candidate of pending) {
|
|
731
|
+
try {
|
|
732
|
+
await pc.addIceCandidate(candidate);
|
|
733
|
+
} catch (err) {
|
|
734
|
+
console.warn("[ICE] Failed to add candidate:", err);
|
|
735
|
+
}
|
|
645
736
|
}
|
|
737
|
+
delete this.pendingIceCandidates[id];
|
|
738
|
+
const answer = await pc.createAnswer();
|
|
739
|
+
await pc.setLocalDescription(answer);
|
|
740
|
+
await this.flushIce(id, pc);
|
|
741
|
+
this.send({
|
|
742
|
+
type: "ANSWER",
|
|
743
|
+
payload: answer.sdp,
|
|
744
|
+
sender: this.myId,
|
|
745
|
+
target: id
|
|
746
|
+
});
|
|
747
|
+
console.debug(`[Answer] Sent to ${id}`);
|
|
748
|
+
} catch (err) {
|
|
749
|
+
console.error(`[Signaling] Failed to handle OFFER from ${id}:`, err);
|
|
750
|
+
this.emitError(
|
|
751
|
+
"OFFER_HANDLING_FAILED",
|
|
752
|
+
`Failed to handle offer from ${id}`,
|
|
753
|
+
err,
|
|
754
|
+
true
|
|
755
|
+
);
|
|
646
756
|
}
|
|
647
|
-
delete this.pendingIceCandidates[id];
|
|
648
|
-
const answer = await pc.createAnswer();
|
|
649
|
-
await pc.setLocalDescription(answer);
|
|
650
|
-
await this.flushIce(id, pc);
|
|
651
|
-
this.send({
|
|
652
|
-
type: "ANSWER",
|
|
653
|
-
payload: answer.sdp,
|
|
654
|
-
sender: this.myId,
|
|
655
|
-
target: id
|
|
656
|
-
});
|
|
657
757
|
}
|
|
658
758
|
// ---------------- CLEANUP ----------------
|
|
659
759
|
closePeer(id) {
|
|
@@ -668,39 +768,55 @@ var VideoSDKCore = class {
|
|
|
668
768
|
this.state.removeParticipant(id);
|
|
669
769
|
}
|
|
670
770
|
async startScreenShare() {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
this.screenStream = await navigator.mediaDevices.getDisplayMedia({
|
|
675
|
-
video: true,
|
|
676
|
-
audio: true
|
|
677
|
-
});
|
|
678
|
-
this.isScreenSharing = true;
|
|
679
|
-
this.state.updateLocalParticipant({
|
|
680
|
-
media: {
|
|
681
|
-
isScreenSharing: true,
|
|
682
|
-
screenStream: this.screenStream
|
|
771
|
+
try {
|
|
772
|
+
if (this.state.presenterId && this.state.presenterId !== this.myId) {
|
|
773
|
+
throw new Error("Another user is already sharing their screen.");
|
|
683
774
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
this.
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
this.screenSenders[peerId] = [];
|
|
691
|
-
this.screenStream.getTracks().forEach((track) => {
|
|
692
|
-
const sender = pc.addTrack(track, this.screenStream);
|
|
693
|
-
this.screenSenders[peerId].push(sender);
|
|
775
|
+
if (!navigator.mediaDevices?.getDisplayMedia) {
|
|
776
|
+
throw new Error("Screen sharing not supported on this device");
|
|
777
|
+
}
|
|
778
|
+
this.screenStream = await navigator.mediaDevices.getDisplayMedia({
|
|
779
|
+
video: true
|
|
780
|
+
// audio: true,
|
|
694
781
|
});
|
|
695
|
-
this.
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
782
|
+
this.isScreenSharing = true;
|
|
783
|
+
this.state.updateLocalParticipant({
|
|
784
|
+
media: {
|
|
785
|
+
isScreenSharing: true,
|
|
786
|
+
screenStream: this.screenStream,
|
|
787
|
+
screenTrack: this.screenStream.getVideoTracks()[0]
|
|
788
|
+
}
|
|
789
|
+
});
|
|
790
|
+
this.state.setPresenterId(this.myId);
|
|
791
|
+
this.screenStream.getVideoTracks()[0].onended = () => {
|
|
792
|
+
this.stopScreenShare();
|
|
793
|
+
};
|
|
794
|
+
Object.entries(this.peers).forEach(([peerId, pc]) => {
|
|
795
|
+
this.screenSenders[peerId] = [];
|
|
796
|
+
this.screenStream.getTracks().forEach((track) => {
|
|
797
|
+
const sender = pc.addTrack(track, this.screenStream);
|
|
798
|
+
this.screenSenders[peerId].push(sender);
|
|
799
|
+
});
|
|
800
|
+
this.createOffer(peerId, true);
|
|
801
|
+
});
|
|
802
|
+
this.send({
|
|
803
|
+
type: "SCREEN_SHARE_START",
|
|
804
|
+
sender: this.myId,
|
|
805
|
+
room_id: this.roomId,
|
|
806
|
+
stream_id: this.screenStream.id.replace(/[{}]/g, "")
|
|
807
|
+
});
|
|
808
|
+
return this.screenStream;
|
|
809
|
+
} catch (err) {
|
|
810
|
+
this.emitError(
|
|
811
|
+
"SCREEN_SHARE_FAILED",
|
|
812
|
+
err?.message || "Failed to start screen sharing",
|
|
813
|
+
err,
|
|
814
|
+
true
|
|
815
|
+
);
|
|
816
|
+
this.isScreenSharing = false;
|
|
817
|
+
this.screenStream = null;
|
|
818
|
+
throw err;
|
|
819
|
+
}
|
|
704
820
|
}
|
|
705
821
|
stopScreenShare() {
|
|
706
822
|
if (!this.screenStream) return;
|
|
@@ -938,7 +1054,6 @@ var useLocalParticipant = () => {
|
|
|
938
1054
|
video.srcObject = stream;
|
|
939
1055
|
video.autoplay = true;
|
|
940
1056
|
video.playsInline = true;
|
|
941
|
-
video.muted = true;
|
|
942
1057
|
video.play().catch((err) => {
|
|
943
1058
|
console.warn(`Autoplay failed for local view:`, err);
|
|
944
1059
|
});
|
|
@@ -988,6 +1103,15 @@ var useRemoteMedia = (participantId) => {
|
|
|
988
1103
|
const [participant, setParticipant] = (0, import_react6.useState)(
|
|
989
1104
|
() => sdk.state.getParticipant(participantId) || null
|
|
990
1105
|
);
|
|
1106
|
+
const buildMediaStream = (participant2) => {
|
|
1107
|
+
if (!participant2?.media) return null;
|
|
1108
|
+
const stream = new MediaStream();
|
|
1109
|
+
const videoTrack = participant2.media.stream?.getVideoTracks?.()?.[0];
|
|
1110
|
+
const audioTrack = participant2.media.stream?.getAudioTracks?.()?.[0];
|
|
1111
|
+
if (videoTrack) stream.addTrack(videoTrack);
|
|
1112
|
+
if (audioTrack) stream.addTrack(audioTrack);
|
|
1113
|
+
return stream;
|
|
1114
|
+
};
|
|
991
1115
|
(0, import_react6.useEffect)(() => {
|
|
992
1116
|
const unsub = sdk.state.subscribe(`participant:${participantId}`, () => {
|
|
993
1117
|
const p = sdk.state.getParticipant(participantId);
|
|
@@ -1001,13 +1125,14 @@ var useRemoteMedia = (participantId) => {
|
|
|
1001
1125
|
const stream = participant?.media?.stream;
|
|
1002
1126
|
if (!stream) return;
|
|
1003
1127
|
node.srcObject = stream;
|
|
1004
|
-
node.autoplay = true;
|
|
1005
|
-
node.playsInline = true;
|
|
1006
1128
|
node.muted = true;
|
|
1007
|
-
node.
|
|
1129
|
+
node.playsInline = true;
|
|
1130
|
+
node.autoplay = true;
|
|
1131
|
+
node.play().catch((err) => {
|
|
1132
|
+
console.log("can't play video:", err);
|
|
1133
|
+
});
|
|
1008
1134
|
},
|
|
1009
|
-
|
|
1010
|
-
[participant?.media?.stream, participant?.media?.cameraTrack]
|
|
1135
|
+
[participant?.media?.stream]
|
|
1011
1136
|
);
|
|
1012
1137
|
const audioRef = (0, import_react6.useCallback)(
|
|
1013
1138
|
(node) => {
|
|
@@ -1015,12 +1140,12 @@ var useRemoteMedia = (participantId) => {
|
|
|
1015
1140
|
const stream = participant?.media?.stream;
|
|
1016
1141
|
if (!stream) return;
|
|
1017
1142
|
node.srcObject = stream;
|
|
1018
|
-
node.
|
|
1019
|
-
node.
|
|
1020
|
-
|
|
1143
|
+
node.muted = false;
|
|
1144
|
+
node.play().catch((err) => {
|
|
1145
|
+
console.log("can't play Audio:", err);
|
|
1146
|
+
});
|
|
1021
1147
|
},
|
|
1022
|
-
|
|
1023
|
-
[participant?.media?.stream, participant?.media?.micEnabled]
|
|
1148
|
+
[participant?.media?.stream]
|
|
1024
1149
|
);
|
|
1025
1150
|
return {
|
|
1026
1151
|
videoRef,
|