@afosecure/meetingsdk 1.1.4 → 1.1.6
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 +15 -5
- package/dist/index.d.ts +15 -5
- package/dist/index.js +109 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -69
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { createContext, useContext, useMemo, useRef } from "react";
|
|
|
6
6
|
|
|
7
7
|
// src/config/ws.ts
|
|
8
8
|
var SDK_CONFIG = {
|
|
9
|
-
wsUrl: "
|
|
9
|
+
wsUrl: "ws://localhost:8080/ws"
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/core/MeetingState.ts
|
|
@@ -168,8 +168,12 @@ var VideoSDKCore = class {
|
|
|
168
168
|
this.peers = {};
|
|
169
169
|
this.initiators = /* @__PURE__ */ new Set();
|
|
170
170
|
this.lastPong = Date.now();
|
|
171
|
+
this.iceServers = [];
|
|
171
172
|
this.intentionalDisconnect = false;
|
|
172
|
-
this.
|
|
173
|
+
this.room = {
|
|
174
|
+
id: null,
|
|
175
|
+
name: null
|
|
176
|
+
};
|
|
173
177
|
this.localStream = null;
|
|
174
178
|
this.screenStream = null;
|
|
175
179
|
this.isScreenSharing = false;
|
|
@@ -189,7 +193,7 @@ var VideoSDKCore = class {
|
|
|
189
193
|
code,
|
|
190
194
|
message,
|
|
191
195
|
raw,
|
|
192
|
-
roomId: this.
|
|
196
|
+
roomId: this.room.id,
|
|
193
197
|
userId: this.myId,
|
|
194
198
|
recoverable
|
|
195
199
|
};
|
|
@@ -201,28 +205,43 @@ var VideoSDKCore = class {
|
|
|
201
205
|
// ---------------- STREAM ----------------
|
|
202
206
|
async initLocal(video, name) {
|
|
203
207
|
this.participantName = name;
|
|
204
|
-
|
|
208
|
+
try {
|
|
205
209
|
this.localStream = await navigator.mediaDevices.getUserMedia({
|
|
206
|
-
video:
|
|
207
|
-
|
|
210
|
+
video: {
|
|
211
|
+
width: { ideal: 1280 },
|
|
212
|
+
height: { ideal: 720 }
|
|
213
|
+
},
|
|
214
|
+
audio: {
|
|
215
|
+
echoCancellation: true,
|
|
216
|
+
noiseSuppression: true,
|
|
217
|
+
autoGainControl: true
|
|
218
|
+
}
|
|
208
219
|
});
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
name: this.participantName,
|
|
214
|
-
media: {
|
|
215
|
-
stream: this.localStream,
|
|
216
|
-
micEnabled: true,
|
|
217
|
-
camEnabled: true,
|
|
218
|
-
isScreenSharing: false
|
|
220
|
+
const hasVideo = this.localStream.getVideoTracks().some((t) => t.readyState === "live");
|
|
221
|
+
const hasAudio = this.localStream.getAudioTracks().some((t) => t.readyState === "live");
|
|
222
|
+
if (!hasVideo || !hasAudio) {
|
|
223
|
+
throw new Error(`Missing tracks: video=${hasVideo}, audio=${hasAudio}`);
|
|
219
224
|
}
|
|
220
|
-
|
|
221
|
-
|
|
225
|
+
video.srcObject = this.localStream;
|
|
226
|
+
this.state.updateLocalParticipant({
|
|
227
|
+
id: this.myId,
|
|
228
|
+
name: this.participantName,
|
|
229
|
+
media: {
|
|
230
|
+
stream: this.localStream,
|
|
231
|
+
micEnabled: true,
|
|
232
|
+
camEnabled: true,
|
|
233
|
+
isScreenSharing: false
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
this.state.localStream = this.localStream;
|
|
237
|
+
} catch (err) {
|
|
238
|
+
this.emitError("GET_USER_MEDIA_FAILED", err?.message, err, false);
|
|
239
|
+
throw err;
|
|
240
|
+
}
|
|
222
241
|
}
|
|
223
242
|
// ---------------- CONNECT ----------------
|
|
224
243
|
async connect(roomId, name) {
|
|
225
|
-
this.
|
|
244
|
+
this.room.id = roomId;
|
|
226
245
|
this.reset();
|
|
227
246
|
return new Promise((resolve, reject) => {
|
|
228
247
|
this.joinResolver = resolve;
|
|
@@ -291,8 +310,8 @@ var VideoSDKCore = class {
|
|
|
291
310
|
await this.connect(roomId, name);
|
|
292
311
|
}
|
|
293
312
|
/** Expose the roomId without making it fully public */
|
|
294
|
-
|
|
295
|
-
return this.
|
|
313
|
+
getMeeting() {
|
|
314
|
+
return this.room;
|
|
296
315
|
}
|
|
297
316
|
toggleMic() {
|
|
298
317
|
const mediaState = this.state.localParticipant?.media;
|
|
@@ -333,12 +352,12 @@ var VideoSDKCore = class {
|
|
|
333
352
|
});
|
|
334
353
|
}
|
|
335
354
|
scheduleReconnect() {
|
|
336
|
-
if (!this.
|
|
355
|
+
if (!this.room.id) return;
|
|
337
356
|
const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), 3e4);
|
|
338
357
|
clearTimeout(this.reconnectTimer);
|
|
339
358
|
this.reconnectTimer = window.setTimeout(async () => {
|
|
340
359
|
try {
|
|
341
|
-
await this.connect(this.
|
|
360
|
+
await this.connect(this.room.id, this.participantName);
|
|
342
361
|
this.reconnectAttempts = 0;
|
|
343
362
|
} catch {
|
|
344
363
|
this.reconnectAttempts++;
|
|
@@ -379,10 +398,18 @@ var VideoSDKCore = class {
|
|
|
379
398
|
this.lastPong = Date.now();
|
|
380
399
|
break;
|
|
381
400
|
case "OFFER":
|
|
401
|
+
console.log("[Offer] Received from", msg.sender, {
|
|
402
|
+
sdp: msg.payload.substring(0, 200)
|
|
403
|
+
});
|
|
382
404
|
await this.handleOffer(msg.payload, msg.sender);
|
|
383
405
|
break;
|
|
384
406
|
case "ANSWER": {
|
|
385
407
|
const pc = this.peers[msg.sender];
|
|
408
|
+
console.log("[Answer] Received from", msg.sender, {
|
|
409
|
+
signalingState: pc?.signalingState,
|
|
410
|
+
iceConnectionState: pc?.iceConnectionState,
|
|
411
|
+
connectionState: pc?.connectionState
|
|
412
|
+
});
|
|
386
413
|
if (!pc) return;
|
|
387
414
|
if (pc.signalingState !== "have-local-offer") {
|
|
388
415
|
console.warn(
|
|
@@ -436,10 +463,16 @@ var VideoSDKCore = class {
|
|
|
436
463
|
if (!p?.id || p.id === this.myId) continue;
|
|
437
464
|
this.state.addParticipant(p);
|
|
438
465
|
this.events.onUserJoined?.(p);
|
|
439
|
-
|
|
466
|
+
if (this.shouldInitiate(p.id)) {
|
|
467
|
+
await this.createOffer(p.id);
|
|
468
|
+
}
|
|
440
469
|
}
|
|
441
470
|
break;
|
|
442
471
|
case "JOINED": {
|
|
472
|
+
if (msg.iceServers) {
|
|
473
|
+
this.iceServers = msg.iceServers;
|
|
474
|
+
}
|
|
475
|
+
this.room.name = msg.room_name;
|
|
443
476
|
this.intentionalDisconnect = false;
|
|
444
477
|
this.reconnectAttempts = 0;
|
|
445
478
|
this.startHeartbeat();
|
|
@@ -453,7 +486,9 @@ var VideoSDKCore = class {
|
|
|
453
486
|
if (!p?.id || p.id === this.myId) return;
|
|
454
487
|
this.state.addParticipant(p);
|
|
455
488
|
this.events.onUserJoined?.(p);
|
|
456
|
-
|
|
489
|
+
if (this.shouldInitiate(p.id)) {
|
|
490
|
+
await this.createOffer(p.id);
|
|
491
|
+
}
|
|
457
492
|
break;
|
|
458
493
|
}
|
|
459
494
|
case "USER_LEFT":
|
|
@@ -528,6 +563,11 @@ var VideoSDKCore = class {
|
|
|
528
563
|
// ---------------- PEER ----------------
|
|
529
564
|
createPeer(id) {
|
|
530
565
|
if (!this.localStream) throw new Error("No local stream");
|
|
566
|
+
if (!this.iceServers || this.iceServers.length === 0) {
|
|
567
|
+
throw new Error(
|
|
568
|
+
"ICE Servers not configured. Backend must provide iceServers on JOIN."
|
|
569
|
+
);
|
|
570
|
+
}
|
|
531
571
|
console.log(
|
|
532
572
|
"Adding tracks",
|
|
533
573
|
this.localStream.getTracks().map((t) => ({
|
|
@@ -537,28 +577,15 @@ var VideoSDKCore = class {
|
|
|
537
577
|
}))
|
|
538
578
|
);
|
|
539
579
|
const pc = new RTCPeerConnection({
|
|
540
|
-
iceServers:
|
|
541
|
-
{
|
|
542
|
-
urls: [
|
|
543
|
-
"stun:stun1.1.google.com:19302",
|
|
544
|
-
"stun:stun2.1.google.com:19302"
|
|
545
|
-
]
|
|
546
|
-
}
|
|
547
|
-
],
|
|
548
|
-
iceCandidatePoolSize: 3
|
|
580
|
+
iceServers: this.iceServers
|
|
549
581
|
});
|
|
550
582
|
pc.ontrack = (event) => {
|
|
551
|
-
console.log(`Track received: ${event.track.kind}`, {
|
|
552
|
-
trackId: event.track.id,
|
|
553
|
-
streamCount: event.streams.length,
|
|
554
|
-
streamTrackCount: event.streams[0]?.getTracks().length
|
|
555
|
-
});
|
|
556
583
|
const incomingStream = event.streams?.[0] || new MediaStream([event.track]);
|
|
557
584
|
const participant = this.state.getParticipant(id);
|
|
558
585
|
const isScreenStream = incomingStream.id === participant?.media?.remoteScreenStreamId;
|
|
559
|
-
if (event.track.
|
|
586
|
+
if (event.track.muted) {
|
|
560
587
|
event.track.onunmute = () => {
|
|
561
|
-
console.log(
|
|
588
|
+
console.log(`${event.track.kind} track unmuted for ${id}`);
|
|
562
589
|
};
|
|
563
590
|
}
|
|
564
591
|
if (isScreenStream) {
|
|
@@ -615,18 +642,17 @@ var VideoSDKCore = class {
|
|
|
615
642
|
}
|
|
616
643
|
// ---------------- OFFER ----------------
|
|
617
644
|
async createOffer(id, isRenegotiation = false) {
|
|
645
|
+
if (!isRenegotiation && !this.shouldInitiate(id)) {
|
|
646
|
+
console.debug(
|
|
647
|
+
`[Offer] ${id} should initiate (${id} > ${this.myId}), skipping`
|
|
648
|
+
);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
618
651
|
if (!isRenegotiation && this.initiators.has(id)) {
|
|
619
652
|
console.debug(
|
|
620
653
|
`[Offer] Already initiating with ${id}, skipping duplicate`
|
|
621
654
|
);
|
|
622
|
-
|
|
623
|
-
if (isRenegotiation && this.peers[id]) {
|
|
624
|
-
const pc2 = this.peers[id];
|
|
625
|
-
if (pc2.signalingState !== "stable") {
|
|
626
|
-
console.warn(
|
|
627
|
-
`[Offer] Cannot renegotiate: peer in state "${pc2.signalingState}"`
|
|
628
|
-
);
|
|
629
|
-
}
|
|
655
|
+
return;
|
|
630
656
|
}
|
|
631
657
|
if (!isRenegotiation) {
|
|
632
658
|
this.initiators.add(id);
|
|
@@ -647,14 +673,11 @@ var VideoSDKCore = class {
|
|
|
647
673
|
console.debug(`[Offer] Sent to ${id}`);
|
|
648
674
|
} catch (err) {
|
|
649
675
|
console.error(`[Offer] Failed for ${id}:`, err);
|
|
650
|
-
this.emitError(
|
|
651
|
-
"OFFER_FAILED",
|
|
652
|
-
`Failed to create offer for ${id}`,
|
|
653
|
-
err,
|
|
654
|
-
true
|
|
655
|
-
);
|
|
656
676
|
}
|
|
657
677
|
}
|
|
678
|
+
shouldInitiate(peerId) {
|
|
679
|
+
return this.myId < peerId;
|
|
680
|
+
}
|
|
658
681
|
// ---------------- ANSWER ----------------
|
|
659
682
|
async handleOffer(sdp, id) {
|
|
660
683
|
if (!this.peers[id]) {
|
|
@@ -662,28 +685,44 @@ var VideoSDKCore = class {
|
|
|
662
685
|
}
|
|
663
686
|
const pc = this.peers[id];
|
|
664
687
|
try {
|
|
665
|
-
if (pc.signalingState
|
|
688
|
+
if (pc.signalingState === "have-local-offer") {
|
|
689
|
+
if (this.shouldInitiate(id)) {
|
|
690
|
+
console.warn(
|
|
691
|
+
`[Glare] Both sent OFFERs, we win (${this.myId} < ${id}), keeping our OFFER`
|
|
692
|
+
);
|
|
693
|
+
return;
|
|
694
|
+
} else {
|
|
695
|
+
console.warn(
|
|
696
|
+
`[Glare] Both sent OFFERs, they win (${id} < ${this.myId}), rolling back`
|
|
697
|
+
);
|
|
698
|
+
pc.close();
|
|
699
|
+
delete this.peers[id];
|
|
700
|
+
this.initiators.delete(id);
|
|
701
|
+
this.peers[id] = this.createPeer(id);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
if (this.peers[id].signalingState !== "stable" && this.peers[id].signalingState !== "have-local-offer") {
|
|
666
705
|
console.warn(
|
|
667
|
-
`[Signaling] Cannot accept OFFER in state "${
|
|
706
|
+
`[Signaling] Cannot accept OFFER in state "${this.peers[id].signalingState}"`
|
|
668
707
|
);
|
|
669
708
|
return;
|
|
670
709
|
}
|
|
671
|
-
await
|
|
710
|
+
await this.peers[id].setRemoteDescription({
|
|
672
711
|
type: "offer",
|
|
673
712
|
sdp
|
|
674
713
|
});
|
|
675
714
|
const pending = this.pendingIceCandidates[id] || [];
|
|
676
715
|
for (const candidate of pending) {
|
|
677
716
|
try {
|
|
678
|
-
await
|
|
717
|
+
await this.peers[id].addIceCandidate(candidate);
|
|
679
718
|
} catch (err) {
|
|
680
719
|
console.warn("[ICE] Failed to add candidate:", err);
|
|
681
720
|
}
|
|
682
721
|
}
|
|
683
722
|
delete this.pendingIceCandidates[id];
|
|
684
|
-
const answer = await
|
|
685
|
-
await
|
|
686
|
-
await this.flushIce(id,
|
|
723
|
+
const answer = await this.peers[id].createAnswer();
|
|
724
|
+
await this.peers[id].setLocalDescription(answer);
|
|
725
|
+
await this.flushIce(id, this.peers[id]);
|
|
687
726
|
this.send({
|
|
688
727
|
type: "ANSWER",
|
|
689
728
|
payload: answer.sdp,
|
|
@@ -748,7 +787,7 @@ var VideoSDKCore = class {
|
|
|
748
787
|
this.send({
|
|
749
788
|
type: "SCREEN_SHARE_START",
|
|
750
789
|
sender: this.myId,
|
|
751
|
-
room_id: this.
|
|
790
|
+
room_id: this.room.id,
|
|
752
791
|
stream_id: this.screenStream.id.replace(/[{}]/g, "")
|
|
753
792
|
});
|
|
754
793
|
return this.screenStream;
|
|
@@ -794,7 +833,7 @@ var VideoSDKCore = class {
|
|
|
794
833
|
this.send({
|
|
795
834
|
type: "SCREEN_SHARE_STOP",
|
|
796
835
|
sender: this.myId,
|
|
797
|
-
room_id: this.
|
|
836
|
+
room_id: this.room.id
|
|
798
837
|
});
|
|
799
838
|
}
|
|
800
839
|
sendChatMessage(payload) {
|
|
@@ -802,7 +841,7 @@ var VideoSDKCore = class {
|
|
|
802
841
|
console.warn("WS not connected");
|
|
803
842
|
return;
|
|
804
843
|
}
|
|
805
|
-
if (!this.
|
|
844
|
+
if (!this.room.id) {
|
|
806
845
|
console.warn("No roomId set");
|
|
807
846
|
return;
|
|
808
847
|
}
|
|
@@ -823,7 +862,7 @@ var VideoSDKCore = class {
|
|
|
823
862
|
message: payload.message.trim(),
|
|
824
863
|
user_id: this.myId,
|
|
825
864
|
sender_name: senderName,
|
|
826
|
-
room_id: this.
|
|
865
|
+
room_id: this.room.id,
|
|
827
866
|
target: isPrivate ? payload.target ?? null : null,
|
|
828
867
|
reply_to: payload.reply_to ?? null,
|
|
829
868
|
client_ts: Date.now()
|
|
@@ -844,7 +883,7 @@ var VideoSDKCore = class {
|
|
|
844
883
|
this.localStream.getTracks().forEach((track) => track.stop());
|
|
845
884
|
this.localStream = null;
|
|
846
885
|
}
|
|
847
|
-
this.
|
|
886
|
+
this.room.id = null;
|
|
848
887
|
this.state.localParticipant = null;
|
|
849
888
|
this.state.notify("localParticipant");
|
|
850
889
|
this.state.participants.clear();
|
|
@@ -939,7 +978,7 @@ var MeetingProvider = ({
|
|
|
939
978
|
startScreenShare: sdk.startScreenShare.bind(sdk),
|
|
940
979
|
stopScreenShare: sdk.stopScreenShare.bind(sdk),
|
|
941
980
|
sendMessage: sdk.sendChatMessage.bind(sdk),
|
|
942
|
-
|
|
981
|
+
room: sdk.getMeeting(),
|
|
943
982
|
localParticipant,
|
|
944
983
|
participants,
|
|
945
984
|
messages,
|
|
@@ -1022,7 +1061,8 @@ var useMeeting = (handlers) => {
|
|
|
1022
1061
|
const unsubscribe = ctx.onError(handlers.onError);
|
|
1023
1062
|
return unsubscribe;
|
|
1024
1063
|
}, [handlers?.onError]);
|
|
1025
|
-
|
|
1064
|
+
const { sdk: _, ...publicApi } = ctx;
|
|
1065
|
+
return publicApi;
|
|
1026
1066
|
};
|
|
1027
1067
|
|
|
1028
1068
|
// src/react/useParticipants.ts
|