@afosecure/meetingsdk 1.1.0 → 1.1.2
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 +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +182 -105
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +183 -106
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -167,6 +167,8 @@ var VideoSDKCore = class {
|
|
|
167
167
|
this.ws = null;
|
|
168
168
|
this.peers = {};
|
|
169
169
|
this.initiators = /* @__PURE__ */ new Set();
|
|
170
|
+
this.lastPong = Date.now();
|
|
171
|
+
this.intentionalDisconnect = false;
|
|
170
172
|
this.roomId = null;
|
|
171
173
|
this.localStream = null;
|
|
172
174
|
this.screenStream = null;
|
|
@@ -238,18 +240,18 @@ var VideoSDKCore = class {
|
|
|
238
240
|
this.emitError("WS_ERROR", "WebSocket encountered an error", err, true);
|
|
239
241
|
};
|
|
240
242
|
this.ws.onclose = (e) => {
|
|
241
|
-
this.emitError(
|
|
242
|
-
"WS_CLOSED",
|
|
243
|
-
`Connection closed (${e.code}) ${e.reason || ""}`,
|
|
244
|
-
e,
|
|
245
|
-
true
|
|
246
|
-
);
|
|
247
243
|
this.joinRejecter?.({
|
|
248
244
|
code: "WS_CLOSED",
|
|
249
245
|
message: "Connection closed before join completed",
|
|
250
246
|
raw: e
|
|
251
247
|
});
|
|
252
248
|
this.joinRejecter = void 0;
|
|
249
|
+
if (this.intentionalDisconnect) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (e.code === 1e3 || e.code === 1001) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
253
255
|
this.scheduleReconnect();
|
|
254
256
|
};
|
|
255
257
|
this.ws.onmessage = async (e) => {
|
|
@@ -373,46 +375,36 @@ var VideoSDKCore = class {
|
|
|
373
375
|
var _a, _b, _c, _d;
|
|
374
376
|
if (msg.sender === this.myId) return;
|
|
375
377
|
switch (msg.type) {
|
|
376
|
-
case "
|
|
377
|
-
|
|
378
|
-
this.state.setPresenterId(msg.presenterId);
|
|
379
|
-
this.events.onScreenShareStarted?.(msg.presenterId, null);
|
|
380
|
-
}
|
|
381
|
-
for (const p of msg.participants || []) {
|
|
382
|
-
if (!p?.id || p.id === this.myId) continue;
|
|
383
|
-
this.state.addParticipant(p);
|
|
384
|
-
this.events.onUserJoined?.(p);
|
|
385
|
-
}
|
|
378
|
+
case "PONG":
|
|
379
|
+
this.lastPong = Date.now();
|
|
386
380
|
break;
|
|
387
|
-
case "JOINED": {
|
|
388
|
-
this.startHeartbeat();
|
|
389
|
-
this.joinResolver?.();
|
|
390
|
-
this.joinResolver = void 0;
|
|
391
|
-
this.joinRejecter = void 0;
|
|
392
|
-
break;
|
|
393
|
-
}
|
|
394
|
-
case "USER_JOINED": {
|
|
395
|
-
const p = msg.participant;
|
|
396
|
-
if (!p?.id || p.id === this.myId) return;
|
|
397
|
-
this.state.addParticipant(p);
|
|
398
|
-
this.events.onUserJoined?.(p);
|
|
399
|
-
break;
|
|
400
|
-
}
|
|
401
381
|
case "OFFER":
|
|
402
382
|
await this.handleOffer(msg.payload, msg.sender);
|
|
403
383
|
break;
|
|
404
384
|
case "ANSWER": {
|
|
405
385
|
const pc = this.peers[msg.sender];
|
|
406
386
|
if (!pc) return;
|
|
407
|
-
if (pc.signalingState
|
|
408
|
-
console.warn(
|
|
387
|
+
if (pc.signalingState !== "have-local-offer") {
|
|
388
|
+
console.warn(
|
|
389
|
+
`[Signaling] Unexpected ANSWER in state "${pc.signalingState}", ignoring`
|
|
390
|
+
);
|
|
409
391
|
return;
|
|
410
392
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
393
|
+
try {
|
|
394
|
+
await pc.setRemoteDescription({
|
|
395
|
+
type: "answer",
|
|
396
|
+
sdp: msg.payload
|
|
397
|
+
});
|
|
398
|
+
await this.flushIce(msg.sender, pc);
|
|
399
|
+
} catch (err) {
|
|
400
|
+
console.error("[Signaling] Failed to apply answer:", err);
|
|
401
|
+
this.emitError(
|
|
402
|
+
"ANSWER_FAILED",
|
|
403
|
+
`Failed to apply answer from ${msg.sender}`,
|
|
404
|
+
err,
|
|
405
|
+
true
|
|
406
|
+
);
|
|
407
|
+
}
|
|
416
408
|
break;
|
|
417
409
|
}
|
|
418
410
|
case "ICE": {
|
|
@@ -435,6 +427,35 @@ var VideoSDKCore = class {
|
|
|
435
427
|
}
|
|
436
428
|
break;
|
|
437
429
|
}
|
|
430
|
+
case "EXISTING_USERS":
|
|
431
|
+
if (msg.presenterId) {
|
|
432
|
+
this.state.setPresenterId(msg.presenterId);
|
|
433
|
+
this.events.onScreenShareStarted?.(msg.presenterId, null);
|
|
434
|
+
}
|
|
435
|
+
for (const p of msg.participants || []) {
|
|
436
|
+
if (!p?.id || p.id === this.myId) continue;
|
|
437
|
+
this.state.addParticipant(p);
|
|
438
|
+
this.events.onUserJoined?.(p);
|
|
439
|
+
await this.createOffer(p.id);
|
|
440
|
+
}
|
|
441
|
+
break;
|
|
442
|
+
case "JOINED": {
|
|
443
|
+
this.intentionalDisconnect = false;
|
|
444
|
+
this.reconnectAttempts = 0;
|
|
445
|
+
this.startHeartbeat();
|
|
446
|
+
this.joinResolver?.();
|
|
447
|
+
this.joinResolver = void 0;
|
|
448
|
+
this.joinRejecter = void 0;
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
case "USER_JOINED": {
|
|
452
|
+
const p = msg.participant;
|
|
453
|
+
if (!p?.id || p.id === this.myId) return;
|
|
454
|
+
this.state.addParticipant(p);
|
|
455
|
+
this.events.onUserJoined?.(p);
|
|
456
|
+
await this.createOffer(p.id);
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
438
459
|
case "USER_LEFT":
|
|
439
460
|
const peerId = msg.participant.id;
|
|
440
461
|
this.closePeer(peerId);
|
|
@@ -518,17 +539,44 @@ var VideoSDKCore = class {
|
|
|
518
539
|
const pc = new RTCPeerConnection({
|
|
519
540
|
iceServers: [
|
|
520
541
|
{
|
|
521
|
-
urls:
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
542
|
+
urls: "stun:stun.relay.metered.ca:80"
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
urls: "turn:global.relay.metered.ca:80",
|
|
546
|
+
username: "25aed888d2d360e9fae0e812",
|
|
547
|
+
credential: "WPYstojO9Wf3+HsQ"
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
urls: "turn:global.relay.metered.ca:80?transport=tcp",
|
|
551
|
+
username: "25aed888d2d360e9fae0e812",
|
|
552
|
+
credential: "WPYstojO9Wf3+HsQ"
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
urls: "turn:global.relay.metered.ca:443",
|
|
556
|
+
username: "25aed888d2d360e9fae0e812",
|
|
557
|
+
credential: "WPYstojO9Wf3+HsQ"
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
urls: "turns:global.relay.metered.ca:443?transport=tcp",
|
|
561
|
+
username: "25aed888d2d360e9fae0e812",
|
|
562
|
+
credential: "WPYstojO9Wf3+HsQ"
|
|
525
563
|
}
|
|
526
564
|
]
|
|
527
565
|
});
|
|
528
566
|
pc.ontrack = (event) => {
|
|
529
|
-
|
|
567
|
+
console.log(`Track received: ${event.track.kind}`, {
|
|
568
|
+
trackId: event.track.id,
|
|
569
|
+
streamCount: event.streams.length,
|
|
570
|
+
streamTrackCount: event.streams[0]?.getTracks().length
|
|
571
|
+
});
|
|
572
|
+
const incomingStream = event.streams?.[0] || new MediaStream([event.track]);
|
|
530
573
|
const participant = this.state.getParticipant(id);
|
|
531
574
|
const isScreenStream = incomingStream.id === participant?.media?.remoteScreenStreamId;
|
|
575
|
+
if (event.track.kind === "video") {
|
|
576
|
+
event.track.onunmute = () => {
|
|
577
|
+
console.log("Video track unmuted for", id);
|
|
578
|
+
};
|
|
579
|
+
}
|
|
532
580
|
if (isScreenStream) {
|
|
533
581
|
const videoTrack = event.track.kind === "video" ? event.track : incomingStream.getVideoTracks()[0] || participant?.media?.screenTrack;
|
|
534
582
|
this.state.updateParticipantMedia(id, {
|
|
@@ -558,6 +606,9 @@ var VideoSDKCore = class {
|
|
|
558
606
|
target: id
|
|
559
607
|
});
|
|
560
608
|
};
|
|
609
|
+
pc.oniceconnectionstatechange = () => {
|
|
610
|
+
console.log(`ICE Connection State: ${pc.iceConnectionState}`);
|
|
611
|
+
};
|
|
561
612
|
pc.onconnectionstatechange = () => {
|
|
562
613
|
if (pc.connectionState === "failed") {
|
|
563
614
|
try {
|
|
@@ -580,18 +631,45 @@ var VideoSDKCore = class {
|
|
|
580
631
|
}
|
|
581
632
|
// ---------------- OFFER ----------------
|
|
582
633
|
async createOffer(id, isRenegotiation = false) {
|
|
634
|
+
if (!isRenegotiation && this.initiators.has(id)) {
|
|
635
|
+
console.debug(
|
|
636
|
+
`[Offer] Already initiating with ${id}, skipping duplicate`
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
if (isRenegotiation && this.peers[id]) {
|
|
640
|
+
const pc2 = this.peers[id];
|
|
641
|
+
if (pc2.signalingState !== "stable") {
|
|
642
|
+
console.warn(
|
|
643
|
+
`[Offer] Cannot renegotiate: peer in state "${pc2.signalingState}"`
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
if (!isRenegotiation) {
|
|
648
|
+
this.initiators.add(id);
|
|
649
|
+
}
|
|
583
650
|
if (!this.peers[id]) {
|
|
584
651
|
this.peers[id] = this.createPeer(id);
|
|
585
652
|
}
|
|
586
653
|
const pc = this.peers[id];
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
654
|
+
try {
|
|
655
|
+
const offer = await pc.createOffer();
|
|
656
|
+
await pc.setLocalDescription(offer);
|
|
657
|
+
this.send({
|
|
658
|
+
type: "OFFER",
|
|
659
|
+
payload: offer.sdp,
|
|
660
|
+
sender: this.myId,
|
|
661
|
+
target: id
|
|
662
|
+
});
|
|
663
|
+
console.debug(`[Offer] Sent to ${id}`);
|
|
664
|
+
} catch (err) {
|
|
665
|
+
console.error(`[Offer] Failed for ${id}:`, err);
|
|
666
|
+
this.emitError(
|
|
667
|
+
"OFFER_FAILED",
|
|
668
|
+
`Failed to create offer for ${id}`,
|
|
669
|
+
err,
|
|
670
|
+
true
|
|
671
|
+
);
|
|
672
|
+
}
|
|
595
673
|
}
|
|
596
674
|
// ---------------- ANSWER ----------------
|
|
597
675
|
async handleOffer(sdp, id) {
|
|
@@ -599,28 +677,45 @@ var VideoSDKCore = class {
|
|
|
599
677
|
this.peers[id] = this.createPeer(id);
|
|
600
678
|
}
|
|
601
679
|
const pc = this.peers[id];
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
680
|
+
try {
|
|
681
|
+
if (pc.signalingState !== "stable" && pc.signalingState !== "have-local-offer") {
|
|
682
|
+
console.warn(
|
|
683
|
+
`[Signaling] Cannot accept OFFER in state "${pc.signalingState}"`
|
|
684
|
+
);
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
await pc.setRemoteDescription({
|
|
688
|
+
type: "offer",
|
|
689
|
+
sdp
|
|
690
|
+
});
|
|
691
|
+
const pending = this.pendingIceCandidates[id] || [];
|
|
692
|
+
for (const candidate of pending) {
|
|
693
|
+
try {
|
|
694
|
+
await pc.addIceCandidate(candidate);
|
|
695
|
+
} catch (err) {
|
|
696
|
+
console.warn("[ICE] Failed to add candidate:", err);
|
|
697
|
+
}
|
|
612
698
|
}
|
|
699
|
+
delete this.pendingIceCandidates[id];
|
|
700
|
+
const answer = await pc.createAnswer();
|
|
701
|
+
await pc.setLocalDescription(answer);
|
|
702
|
+
await this.flushIce(id, pc);
|
|
703
|
+
this.send({
|
|
704
|
+
type: "ANSWER",
|
|
705
|
+
payload: answer.sdp,
|
|
706
|
+
sender: this.myId,
|
|
707
|
+
target: id
|
|
708
|
+
});
|
|
709
|
+
console.debug(`[Answer] Sent to ${id}`);
|
|
710
|
+
} catch (err) {
|
|
711
|
+
console.error(`[Signaling] Failed to handle OFFER from ${id}:`, err);
|
|
712
|
+
this.emitError(
|
|
713
|
+
"OFFER_HANDLING_FAILED",
|
|
714
|
+
`Failed to handle offer from ${id}`,
|
|
715
|
+
err,
|
|
716
|
+
true
|
|
717
|
+
);
|
|
613
718
|
}
|
|
614
|
-
delete this.pendingIceCandidates[id];
|
|
615
|
-
const answer = await pc.createAnswer();
|
|
616
|
-
await pc.setLocalDescription(answer);
|
|
617
|
-
await this.flushIce(id, pc);
|
|
618
|
-
this.send({
|
|
619
|
-
type: "ANSWER",
|
|
620
|
-
payload: answer.sdp,
|
|
621
|
-
sender: this.myId,
|
|
622
|
-
target: id
|
|
623
|
-
});
|
|
624
719
|
}
|
|
625
720
|
// ---------------- CLEANUP ----------------
|
|
626
721
|
closePeer(id) {
|
|
@@ -751,6 +846,7 @@ var VideoSDKCore = class {
|
|
|
751
846
|
});
|
|
752
847
|
}
|
|
753
848
|
disconnect() {
|
|
849
|
+
this.intentionalDisconnect = true;
|
|
754
850
|
this.stopScreenShare();
|
|
755
851
|
Object.values(this.peers).forEach((pc) => pc.close());
|
|
756
852
|
this.peers = {};
|
|
@@ -964,21 +1060,14 @@ var useParticipants = () => {
|
|
|
964
1060
|
};
|
|
965
1061
|
|
|
966
1062
|
// src/react/useRemoteMedia.ts
|
|
967
|
-
import {
|
|
1063
|
+
import { useEffect as useEffect5, useRef as useRef3, useState as useState4 } from "react";
|
|
968
1064
|
var useRemoteMedia = (participantId) => {
|
|
969
1065
|
const { sdk } = useMeetingContext();
|
|
1066
|
+
const videoRef = useRef3(null);
|
|
1067
|
+
const audioRef = useRef3(null);
|
|
970
1068
|
const [participant, setParticipant] = useState4(
|
|
971
1069
|
() => sdk.state.getParticipant(participantId) || null
|
|
972
1070
|
);
|
|
973
|
-
const buildMediaStream = (participant2) => {
|
|
974
|
-
if (!participant2?.media) return null;
|
|
975
|
-
const stream = new MediaStream();
|
|
976
|
-
const videoTrack = participant2.media.stream?.getVideoTracks?.()?.[0];
|
|
977
|
-
const audioTrack = participant2.media.stream?.getAudioTracks?.()?.[0];
|
|
978
|
-
if (videoTrack) stream.addTrack(videoTrack);
|
|
979
|
-
if (audioTrack) stream.addTrack(audioTrack);
|
|
980
|
-
return stream;
|
|
981
|
-
};
|
|
982
1071
|
useEffect5(() => {
|
|
983
1072
|
const unsub = sdk.state.subscribe(`participant:${participantId}`, () => {
|
|
984
1073
|
const p = sdk.state.getParticipant(participantId);
|
|
@@ -986,34 +1075,22 @@ var useRemoteMedia = (participantId) => {
|
|
|
986
1075
|
});
|
|
987
1076
|
return unsub;
|
|
988
1077
|
}, [participantId, sdk]);
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
node.playsInline = true;
|
|
998
|
-
node.autoplay = true;
|
|
999
|
-
node.play().catch(() => {
|
|
1078
|
+
useEffect5(() => {
|
|
1079
|
+
const stream = participant?.media?.stream;
|
|
1080
|
+
if (!stream) return;
|
|
1081
|
+
if (videoRef.current) {
|
|
1082
|
+
videoRef.current.srcObject = stream;
|
|
1083
|
+
videoRef.current.muted = true;
|
|
1084
|
+
videoRef.current.playsInline = true;
|
|
1085
|
+
videoRef.current.play().catch(() => {
|
|
1000
1086
|
});
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
(node) => {
|
|
1006
|
-
if (!node) return;
|
|
1007
|
-
const stream = participant?.media?.stream;
|
|
1008
|
-
if (!stream) return;
|
|
1009
|
-
node.pause();
|
|
1010
|
-
node.srcObject = stream;
|
|
1011
|
-
node.muted = false;
|
|
1012
|
-
node.play().catch(() => {
|
|
1087
|
+
}
|
|
1088
|
+
if (audioRef.current) {
|
|
1089
|
+
audioRef.current.srcObject = stream;
|
|
1090
|
+
audioRef.current.play().catch(() => {
|
|
1013
1091
|
});
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
);
|
|
1092
|
+
}
|
|
1093
|
+
}, [participant?.media?.stream]);
|
|
1017
1094
|
return {
|
|
1018
1095
|
videoRef,
|
|
1019
1096
|
audioRef,
|