@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.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
- // Transceiver-based tracking: maps peerId -> { cameraTransceiver, screenTransceiver, screenMid }
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.events.onScreenShareStarted?.(peerId2, null);
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
- "Creating peer connection for",
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
- const transceiver = event.transceiver;
715
- const isScreenTrack = transceiver.mid === this.peerTransceivers[id]?.screenMid;
716
- console.log(
717
- `[ontrack] ${id}: kind=${event.track.kind}, mid=${transceiver.mid}, isScreen=${isScreenTrack}`
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(`[ontrack] ${event.track.kind} track unmuted for ${id}`);
685
+ console.log(`${event.track.kind} track unmuted for ${id}`);
723
686
  };
724
687
  }
725
- if (isScreenTrack) {
726
- const videoTrack2 = event.track.kind === "video" ? event.track : incomingStream.getVideoTracks()[0];
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: videoTrack2,
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(`[ICE Connection] ${id}: ${pc.iceConnectionState}`);
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 (e) {
763
- console.warn("Failed to restart ICE:", e);
724
+ } catch {
764
725
  }
765
726
  }
766
727
  };
767
- return pc;
768
- }
769
- /**
770
- * Capture the screen transceiver's MID after SDP negotiation completes.
771
- * The MID is assigned during negotiation and is stable for the life of the connection.
772
- */
773
- captureScreenMid(peerId) {
774
- const pc = this.peers[peerId];
775
- if (!pc) return;
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] = await this.createPeer(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] = await this.createPeer(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] = await this.createPeer(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
- screenTrack.onended = () => {
948
- console.log("[Screen Share] User stopped via browser button");
878
+ this.screenStream.getVideoTracks()[0].onended = () => {
949
879
  this.stopScreenShare();
950
880
  };
951
- for (const [peerId, pc] of Object.entries(this.peers)) {
952
- const txInfo = this.peerTransceivers[peerId];
953
- if (!txInfo) {
954
- console.warn(
955
- `[Screen Share] No transceiver info for ${peerId}, skipping`
956
- );
957
- continue;
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
- async stopScreenShare() {
908
+ stopScreenShare() {
996
909
  if (!this.screenStream) return;
997
- console.log("[Screen Share] Stopping...");
998
910
  this.screenStream.getTracks().forEach((t) => t.stop());
999
- for (const [peerId, pc] of Object.entries(this.peers)) {
1000
- const txInfo = this.peerTransceivers[peerId];
1001
- if (!txInfo) continue;
1002
- try {
1003
- await txInfo.screenTransceiver.sender.replaceTrack(null);
1004
- if (txInfo.screenTransceiver.currentDirection === "sendrecv") {
1005
- txInfo.screenTransceiver.direction = "recvonly";
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
- } catch (err) {
1012
- console.error(
1013
- `[Screen Share] Failed to clear transceiver for ${peerId}:`,
1014
- err
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) {