@defcomm/meetingsdk 0.2.4 → 0.2.5
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 +4 -16
- package/dist/index.d.ts +4 -16
- package/dist/index.js +181 -247
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +181 -247
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -385,9 +385,6 @@ var SFUClient = class {
|
|
|
385
385
|
this.localStream = null;
|
|
386
386
|
this.screenStream = null;
|
|
387
387
|
this.videoSender = null;
|
|
388
|
-
this.audioMuted = false;
|
|
389
|
-
this.videoMuted = false;
|
|
390
|
-
this.activeRecording = null;
|
|
391
388
|
this.audioSender = null;
|
|
392
389
|
this.screenSender = null;
|
|
393
390
|
this.audioTransceiver = null;
|
|
@@ -408,7 +405,7 @@ var SFUClient = class {
|
|
|
408
405
|
this.joiningWithResume = false;
|
|
409
406
|
this.reconnectTimer = null;
|
|
410
407
|
this.reconnectAttempt = 0;
|
|
411
|
-
this.maxReconnectAttempts =
|
|
408
|
+
this.maxReconnectAttempts = 8;
|
|
412
409
|
this.reconnectBaseMs = 750;
|
|
413
410
|
this.joinWaiter = null;
|
|
414
411
|
this.transportRecoveryInProgress = false;
|
|
@@ -431,8 +428,7 @@ var SFUClient = class {
|
|
|
431
428
|
this.trackToSource = /* @__PURE__ */ new Map();
|
|
432
429
|
this.localTrackIds = /* @__PURE__ */ new Map();
|
|
433
430
|
this.subscriberStatsTimer = null;
|
|
434
|
-
this.
|
|
435
|
-
this.roomSyncInFlight = false;
|
|
431
|
+
this.lastRecordingId = null;
|
|
436
432
|
this.heartbeatTimer = null;
|
|
437
433
|
this.apiBase = options.apiBase || "https://api.example.com/api";
|
|
438
434
|
this.wsBase = options.wsBase || "wss://api.example.com/ws";
|
|
@@ -445,6 +441,8 @@ var SFUClient = class {
|
|
|
445
441
|
});
|
|
446
442
|
this.onParticipantPresence = options.onParticipantPresence || (() => {
|
|
447
443
|
});
|
|
444
|
+
this.onParticipantMediaState = options.onParticipantMediaState || (() => {
|
|
445
|
+
});
|
|
448
446
|
this.onTrackPublished = options.onTrackPublished || (() => {
|
|
449
447
|
});
|
|
450
448
|
this.onTrackUnpublished = options.onTrackUnpublished || (() => {
|
|
@@ -471,14 +469,10 @@ var SFUClient = class {
|
|
|
471
469
|
});
|
|
472
470
|
this.onTrackStateChanged = options.onTrackStateChanged || (() => {
|
|
473
471
|
});
|
|
474
|
-
this.onParticipantMediaState = options.onParticipantMediaState || (() => {
|
|
475
|
-
});
|
|
476
472
|
this.onRecordingStarted = options.onRecordingStarted || (() => {
|
|
477
473
|
});
|
|
478
474
|
this.onRecordingStopped = options.onRecordingStopped || (() => {
|
|
479
475
|
});
|
|
480
|
-
this.onRoomState = options.onRoomState || (() => {
|
|
481
|
-
});
|
|
482
476
|
this.onError = options.onError || console.error;
|
|
483
477
|
this.autoSubscribe = options.autoSubscribe !== false;
|
|
484
478
|
}
|
|
@@ -500,29 +494,6 @@ var SFUClient = class {
|
|
|
500
494
|
this.heartbeatTimer = null;
|
|
501
495
|
}
|
|
502
496
|
}
|
|
503
|
-
startRoomStateSync() {
|
|
504
|
-
this.stopRoomStateSync();
|
|
505
|
-
this.roomSyncTimer = setInterval(() => {
|
|
506
|
-
if (this.state !== "connected") return;
|
|
507
|
-
void this.syncRoomState();
|
|
508
|
-
}, 5e3);
|
|
509
|
-
}
|
|
510
|
-
stopRoomStateSync() {
|
|
511
|
-
if (this.roomSyncTimer) {
|
|
512
|
-
clearInterval(this.roomSyncTimer);
|
|
513
|
-
this.roomSyncTimer = null;
|
|
514
|
-
}
|
|
515
|
-
this.roomSyncInFlight = false;
|
|
516
|
-
}
|
|
517
|
-
async syncRoomState() {
|
|
518
|
-
if (this.roomSyncInFlight || !this.isSocketOpen()) return;
|
|
519
|
-
this.roomSyncInFlight = true;
|
|
520
|
-
try {
|
|
521
|
-
this.send({ type: "sync_room_state" });
|
|
522
|
-
} finally {
|
|
523
|
-
this.roomSyncInFlight = false;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
497
|
createId() {
|
|
527
498
|
return typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `id_${Math.random().toString(36).slice(2)}_${Date.now()}`;
|
|
528
499
|
}
|
|
@@ -620,13 +591,11 @@ var SFUClient = class {
|
|
|
620
591
|
this.resumeToken = null;
|
|
621
592
|
}
|
|
622
593
|
this.room = nextRoom;
|
|
623
|
-
this.audioMuted = Boolean(options.audioMuted);
|
|
624
|
-
this.videoMuted = Boolean(options.videoMuted);
|
|
625
594
|
this.joinOptions = {
|
|
626
595
|
displayName: options.displayName,
|
|
627
596
|
avatarUrl: options.avatarUrl,
|
|
628
|
-
audioMuted:
|
|
629
|
-
videoMuted:
|
|
597
|
+
audioMuted: options.audioMuted,
|
|
598
|
+
videoMuted: options.videoMuted
|
|
630
599
|
};
|
|
631
600
|
if (options.participantId) this.participantId = options.participantId;
|
|
632
601
|
if (!this.resumeToken) {
|
|
@@ -696,8 +665,8 @@ var SFUClient = class {
|
|
|
696
665
|
resume_token: this.resumeToken,
|
|
697
666
|
display_name: options.displayName,
|
|
698
667
|
avatar_url: options.avatarUrl,
|
|
699
|
-
audio_muted: this.audioMuted,
|
|
700
|
-
video_muted: this.videoMuted
|
|
668
|
+
audio_muted: options.audioMuted ?? this.joinOptions.audioMuted ?? false,
|
|
669
|
+
video_muted: options.videoMuted ?? this.joinOptions.videoMuted ?? false
|
|
701
670
|
};
|
|
702
671
|
if (this.pendingJoinRequestId) {
|
|
703
672
|
this.send({
|
|
@@ -738,20 +707,8 @@ var SFUClient = class {
|
|
|
738
707
|
scheduleReconnect() {
|
|
739
708
|
if (this.reconnectTimer || this.intentionalClose) return;
|
|
740
709
|
if (this.reconnectAttempt >= this.maxReconnectAttempts) {
|
|
741
|
-
const error = new Error("SFU reconnect attempts exhausted");
|
|
742
|
-
console.error("[SFU] Reconnect attempts exhausted; leaving meeting", error);
|
|
743
|
-
this.intentionalClose = true;
|
|
744
|
-
this.stopHeartbeat();
|
|
745
|
-
this.stopRoomStateSync();
|
|
746
|
-
this.cleanupAll();
|
|
747
710
|
this.setState("disconnected");
|
|
748
|
-
this.
|
|
749
|
-
code: "RECONNECT_TIMEOUT",
|
|
750
|
-
message: error.message,
|
|
751
|
-
recoverable: false
|
|
752
|
-
});
|
|
753
|
-
this.onDisconnected();
|
|
754
|
-
this.failJoin(error);
|
|
711
|
+
this.failJoin(new Error("SFU reconnect attempts exhausted"));
|
|
755
712
|
return;
|
|
756
713
|
}
|
|
757
714
|
this.reconnectAttempt += 1;
|
|
@@ -824,8 +781,8 @@ var SFUClient = class {
|
|
|
824
781
|
resume_token: this.resumeToken,
|
|
825
782
|
display_name: this.joinOptions.displayName,
|
|
826
783
|
avatar_url: this.joinOptions.avatarUrl,
|
|
827
|
-
audio_muted: this.audioMuted,
|
|
828
|
-
video_muted: this.videoMuted
|
|
784
|
+
audio_muted: this.joinOptions.audioMuted ?? false,
|
|
785
|
+
video_muted: this.joinOptions.videoMuted ?? false
|
|
829
786
|
}
|
|
830
787
|
});
|
|
831
788
|
}
|
|
@@ -900,8 +857,22 @@ var SFUClient = class {
|
|
|
900
857
|
if (!track?.track_id) break;
|
|
901
858
|
this.rememberTrack(track);
|
|
902
859
|
if (track.participant_id === this.currentParticipantId) {
|
|
903
|
-
if (track.source === "audio")
|
|
904
|
-
|
|
860
|
+
if (track.source === "audio") {
|
|
861
|
+
this.localTrackIds.set("audio", track.track_id);
|
|
862
|
+
const muted = !(this.localStream?.getAudioTracks()[0]?.enabled ?? true);
|
|
863
|
+
this.send({
|
|
864
|
+
type: "track_state",
|
|
865
|
+
payload: { track_id: track.track_id, muted }
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
if (track.source === "camera") {
|
|
869
|
+
this.localTrackIds.set("camera", track.track_id);
|
|
870
|
+
const muted = !(this.localStream?.getVideoTracks()[0]?.enabled ?? true);
|
|
871
|
+
this.send({
|
|
872
|
+
type: "track_state",
|
|
873
|
+
payload: { track_id: track.track_id, muted }
|
|
874
|
+
});
|
|
875
|
+
}
|
|
905
876
|
if (track.source === "screen")
|
|
906
877
|
this.localTrackIds.set("screen", track.track_id);
|
|
907
878
|
break;
|
|
@@ -930,27 +901,6 @@ var SFUClient = class {
|
|
|
930
901
|
this.onTrackUnpublished(track);
|
|
931
902
|
break;
|
|
932
903
|
}
|
|
933
|
-
case "participant_media_state": {
|
|
934
|
-
const participantId = payload.participant_id;
|
|
935
|
-
if (!participantId) break;
|
|
936
|
-
const participant = this.participants.get(participantId);
|
|
937
|
-
if (participant) {
|
|
938
|
-
participant.audio_muted = Boolean(payload.audio_muted);
|
|
939
|
-
participant.video_muted = Boolean(payload.video_muted);
|
|
940
|
-
this.participants.set(participantId, participant);
|
|
941
|
-
}
|
|
942
|
-
for (const track of this.trackMetadata.values()) {
|
|
943
|
-
if (track.participant_id !== participantId) continue;
|
|
944
|
-
if (track.source === "audio") track.muted = Boolean(payload.audio_muted);
|
|
945
|
-
if (track.source === "camera") track.muted = Boolean(payload.video_muted);
|
|
946
|
-
}
|
|
947
|
-
this.onParticipantMediaState(
|
|
948
|
-
participantId,
|
|
949
|
-
Boolean(payload.audio_muted),
|
|
950
|
-
Boolean(payload.video_muted)
|
|
951
|
-
);
|
|
952
|
-
break;
|
|
953
|
-
}
|
|
954
904
|
case "track_state_changed": {
|
|
955
905
|
const trackId = payload.track_id || payload.track?.track_id;
|
|
956
906
|
if (!trackId) break;
|
|
@@ -972,20 +922,16 @@ var SFUClient = class {
|
|
|
972
922
|
case "subscription_updated": {
|
|
973
923
|
break;
|
|
974
924
|
}
|
|
975
|
-
case "room_state": {
|
|
976
|
-
await this.applyRoomState(payload);
|
|
977
|
-
break;
|
|
978
|
-
}
|
|
979
925
|
case "recording_started": {
|
|
980
|
-
this.
|
|
926
|
+
this.lastRecordingId = payload.recording_id || this.lastRecordingId;
|
|
927
|
+
this.onRecordingStarted({
|
|
981
928
|
recording_id: payload.recording_id,
|
|
982
929
|
started_at: payload.started_at
|
|
983
|
-
};
|
|
984
|
-
this.onRecordingStarted(this.activeRecording);
|
|
930
|
+
});
|
|
985
931
|
break;
|
|
986
932
|
}
|
|
987
933
|
case "recording_stopped": {
|
|
988
|
-
this.
|
|
934
|
+
this.lastRecordingId = null;
|
|
989
935
|
this.onRecordingStopped({
|
|
990
936
|
recording_id: payload.recording_id,
|
|
991
937
|
stopped_at: payload.stopped_at
|
|
@@ -1021,6 +967,29 @@ var SFUClient = class {
|
|
|
1021
967
|
this.onScreenShareStopped(participantId, trackId);
|
|
1022
968
|
break;
|
|
1023
969
|
}
|
|
970
|
+
case "room_state": {
|
|
971
|
+
await this.reconcileRoomState(payload);
|
|
972
|
+
break;
|
|
973
|
+
}
|
|
974
|
+
case "participant_media_state": {
|
|
975
|
+
const participantId = payload.participant_id;
|
|
976
|
+
if (participantId) {
|
|
977
|
+
const current = this.participants.get(participantId);
|
|
978
|
+
if (current) {
|
|
979
|
+
this.participants.set(participantId, {
|
|
980
|
+
...current,
|
|
981
|
+
audio_muted: Boolean(payload.audio_muted),
|
|
982
|
+
video_muted: Boolean(payload.video_muted)
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
this.onParticipantMediaState?.(
|
|
987
|
+
participantId,
|
|
988
|
+
Boolean(payload.audio_muted),
|
|
989
|
+
Boolean(payload.video_muted)
|
|
990
|
+
);
|
|
991
|
+
break;
|
|
992
|
+
}
|
|
1024
993
|
case "error": {
|
|
1025
994
|
const message2 = payload.message || "SFU signaling error";
|
|
1026
995
|
if (this.state === "reconnecting" && message2.includes("participant session is stale")) {
|
|
@@ -1043,66 +1012,89 @@ var SFUClient = class {
|
|
|
1043
1012
|
console.debug("[SFU] Ignoring unknown server message", message);
|
|
1044
1013
|
}
|
|
1045
1014
|
}
|
|
1046
|
-
async
|
|
1047
|
-
const
|
|
1048
|
-
for (const participant of payload
|
|
1049
|
-
if (participant?.participant_id)
|
|
1015
|
+
async reconcileRoomState(payload) {
|
|
1016
|
+
const nextParticipants = /* @__PURE__ */ new Map();
|
|
1017
|
+
for (const participant of payload.participants || []) {
|
|
1018
|
+
if (participant?.participant_id) {
|
|
1019
|
+
nextParticipants.set(participant.participant_id, participant);
|
|
1020
|
+
}
|
|
1050
1021
|
}
|
|
1051
|
-
for (const
|
|
1052
|
-
if (
|
|
1053
|
-
this.participants.delete(
|
|
1054
|
-
this.
|
|
1055
|
-
this.onParticipantLeft(id);
|
|
1022
|
+
for (const participantId of this.participants.keys()) {
|
|
1023
|
+
if (participantId !== this.currentParticipantId && !nextParticipants.has(participantId)) {
|
|
1024
|
+
this.participants.delete(participantId);
|
|
1025
|
+
this.onParticipantLeft(participantId);
|
|
1056
1026
|
}
|
|
1057
1027
|
}
|
|
1058
|
-
for (const
|
|
1059
|
-
if (
|
|
1060
|
-
const previous = this.participants.get(
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
}
|
|
1067
|
-
if (
|
|
1068
|
-
|
|
1028
|
+
for (const participant of nextParticipants.values()) {
|
|
1029
|
+
if (participant.participant_id === this.currentParticipantId) continue;
|
|
1030
|
+
const previous = this.participants.get(participant.participant_id);
|
|
1031
|
+
const wasScreenSharing = Boolean(previous?.screen_sharing);
|
|
1032
|
+
const isScreenSharing = Boolean(participant.screen_sharing);
|
|
1033
|
+
this.participants.set(participant.participant_id, participant);
|
|
1034
|
+
if (!previous) {
|
|
1035
|
+
this.onParticipantJoined(participant);
|
|
1036
|
+
}
|
|
1037
|
+
if (participant.presence) {
|
|
1038
|
+
this.onParticipantPresence(
|
|
1039
|
+
participant.participant_id,
|
|
1040
|
+
String(participant.presence).toLowerCase()
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
1043
|
+
this.onParticipantMediaState(
|
|
1044
|
+
participant.participant_id,
|
|
1045
|
+
Boolean(participant.audio_muted),
|
|
1046
|
+
Boolean(participant.video_muted)
|
|
1047
|
+
);
|
|
1048
|
+
if (!wasScreenSharing && isScreenSharing) {
|
|
1049
|
+
this.onScreenShareStarted(participant.participant_id, void 0);
|
|
1050
|
+
} else if (wasScreenSharing && !isScreenSharing) {
|
|
1051
|
+
this.onScreenShareStopped(
|
|
1052
|
+
participant.participant_id,
|
|
1053
|
+
participant.screen_track_id || void 0
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1069
1056
|
}
|
|
1070
1057
|
const nextTracks = /* @__PURE__ */ new Map();
|
|
1071
|
-
for (const track of payload
|
|
1072
|
-
if (
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
this.
|
|
1080
|
-
this.trackToParticipant.delete(
|
|
1081
|
-
this.trackToSource.delete(
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
recording_id: payload.recording.recording_id,
|
|
1087
|
-
started_at: payload.recording.started_at
|
|
1088
|
-
};
|
|
1089
|
-
if (!this.activeRecording || this.activeRecording.recording_id !== current.recording_id) {
|
|
1090
|
-
this.activeRecording = current;
|
|
1091
|
-
this.onRecordingStarted(current);
|
|
1058
|
+
for (const track of payload.tracks || []) {
|
|
1059
|
+
if (track?.track_id) {
|
|
1060
|
+
nextTracks.set(track.track_id, track);
|
|
1061
|
+
this.rememberTrack(track);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
for (const [trackId, oldTrack] of [...this.trackMetadata.entries()]) {
|
|
1065
|
+
if (!nextTracks.has(trackId)) {
|
|
1066
|
+
this.trackMetadata.delete(trackId);
|
|
1067
|
+
this.trackToParticipant.delete(trackId);
|
|
1068
|
+
this.trackToSource.delete(trackId);
|
|
1069
|
+
this.subscribedTracks.delete(trackId);
|
|
1070
|
+
if (oldTrack.participant_id !== this.currentParticipantId) {
|
|
1071
|
+
this.onTrackUnpublished(oldTrack);
|
|
1072
|
+
}
|
|
1092
1073
|
}
|
|
1093
|
-
} else if (this.activeRecording) {
|
|
1094
|
-
const previous = this.activeRecording;
|
|
1095
|
-
this.activeRecording = null;
|
|
1096
|
-
this.onRecordingStopped({
|
|
1097
|
-
recording_id: previous.recording_id,
|
|
1098
|
-
stopped_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1099
|
-
});
|
|
1100
1074
|
}
|
|
1101
1075
|
if (this.autoSubscribe) {
|
|
1102
|
-
const missing = [...nextTracks.values()].filter(
|
|
1076
|
+
const missing = [...nextTracks.values()].filter(
|
|
1077
|
+
(track) => track.participant_id !== this.currentParticipantId && !this.subscribedTracks.has(track.track_id)
|
|
1078
|
+
).map((track) => track.track_id);
|
|
1103
1079
|
if (missing.length) await this.subscribeMultiple(missing);
|
|
1104
1080
|
}
|
|
1105
|
-
|
|
1081
|
+
const nextRecordingId = payload.recording?.recording_id || null;
|
|
1082
|
+
if (payload.recording) {
|
|
1083
|
+
if (this.lastRecordingId !== nextRecordingId) {
|
|
1084
|
+
this.lastRecordingId = nextRecordingId;
|
|
1085
|
+
this.onRecordingStarted({
|
|
1086
|
+
recording_id: payload.recording.recording_id,
|
|
1087
|
+
started_at: payload.recording.started_at
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
} else if (this.lastRecordingId) {
|
|
1091
|
+
const recordingId = this.lastRecordingId;
|
|
1092
|
+
this.lastRecordingId = null;
|
|
1093
|
+
this.onRecordingStopped({
|
|
1094
|
+
recording_id: recordingId,
|
|
1095
|
+
stopped_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1106
1098
|
}
|
|
1107
1099
|
rememberTrack(track) {
|
|
1108
1100
|
this.trackMetadata.set(track.track_id, track);
|
|
@@ -1133,23 +1125,8 @@ var SFUClient = class {
|
|
|
1133
1125
|
for (const track of payload.tracks || []) {
|
|
1134
1126
|
if (track?.track_id) this.rememberTrack(track);
|
|
1135
1127
|
}
|
|
1136
|
-
if (payload.recording) {
|
|
1137
|
-
this.activeRecording = {
|
|
1138
|
-
recording_id: payload.recording.recording_id,
|
|
1139
|
-
started_at: payload.recording.started_at
|
|
1140
|
-
};
|
|
1141
|
-
this.onRecordingStarted(this.activeRecording);
|
|
1142
|
-
} else if (this.activeRecording) {
|
|
1143
|
-
const previous = this.activeRecording;
|
|
1144
|
-
this.activeRecording = null;
|
|
1145
|
-
this.onRecordingStopped({
|
|
1146
|
-
recording_id: previous.recording_id,
|
|
1147
|
-
stopped_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1148
|
-
});
|
|
1149
|
-
}
|
|
1150
1128
|
await this.initializePeerConnections();
|
|
1151
1129
|
this.setState("connected");
|
|
1152
|
-
this.startRoomStateSync();
|
|
1153
1130
|
this.onConnected(payload, resumed);
|
|
1154
1131
|
for (const participant of this.participants.values()) {
|
|
1155
1132
|
if (participant.participant_id !== this.currentParticipantId) {
|
|
@@ -1605,31 +1582,25 @@ var SFUClient = class {
|
|
|
1605
1582
|
this.localStream?.getAudioTracks().forEach((track) => {
|
|
1606
1583
|
track.enabled = !muted;
|
|
1607
1584
|
});
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
}
|
|
1616
|
-
});
|
|
1617
|
-
}
|
|
1585
|
+
this.send({
|
|
1586
|
+
type: "set_media_state",
|
|
1587
|
+
payload: {
|
|
1588
|
+
audio_muted: muted,
|
|
1589
|
+
video_muted: !(this.localStream?.getVideoTracks()[0]?.enabled ?? true)
|
|
1590
|
+
}
|
|
1591
|
+
});
|
|
1618
1592
|
}
|
|
1619
1593
|
muteVideo(muted) {
|
|
1620
1594
|
this.localStream?.getVideoTracks().forEach((track) => {
|
|
1621
1595
|
track.enabled = !muted;
|
|
1622
1596
|
});
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
}
|
|
1631
|
-
});
|
|
1632
|
-
}
|
|
1597
|
+
this.send({
|
|
1598
|
+
type: "set_media_state",
|
|
1599
|
+
payload: {
|
|
1600
|
+
audio_muted: !(this.localStream?.getAudioTracks()[0]?.enabled ?? true),
|
|
1601
|
+
video_muted: muted
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1633
1604
|
}
|
|
1634
1605
|
async startRecording() {
|
|
1635
1606
|
if (!this.send({ type: "start_recording" })) {
|
|
@@ -1704,7 +1675,6 @@ var SFUClient = class {
|
|
|
1704
1675
|
}
|
|
1705
1676
|
async leave() {
|
|
1706
1677
|
this.stopHeartbeat();
|
|
1707
|
-
this.stopRoomStateSync();
|
|
1708
1678
|
this.intentionalClose = true;
|
|
1709
1679
|
this.setState("leaving");
|
|
1710
1680
|
if (this.reconnectTimer) {
|
|
@@ -2072,13 +2042,9 @@ var VideoSDKCore = class {
|
|
|
2072
2042
|
);
|
|
2073
2043
|
return;
|
|
2074
2044
|
}
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
throw new Error(
|
|
2079
|
-
`SFU client already exists in state "${state}". Disconnect explicitly before creating another connection.`
|
|
2080
|
-
);
|
|
2081
|
-
}
|
|
2045
|
+
throw new Error(
|
|
2046
|
+
`SFU client already exists in state "${state}". Disconnect explicitly before creating another connection.`
|
|
2047
|
+
);
|
|
2082
2048
|
}
|
|
2083
2049
|
const client = new SFUClient({
|
|
2084
2050
|
apiBase: this.apiBase,
|
|
@@ -2093,50 +2059,12 @@ var VideoSDKCore = class {
|
|
|
2093
2059
|
console.log(`[SFU] ${resumed ? "Resumed" : "Joined"} room`, payload);
|
|
2094
2060
|
this.state.updateLocalParticipant({
|
|
2095
2061
|
id: this.myId,
|
|
2096
|
-
name: this.participantName
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
for (const participant of roomState?.participants || []) {
|
|
2101
|
-
const pid = participant?.participant_id;
|
|
2102
|
-
if (!pid || pid === this.myId) continue;
|
|
2103
|
-
const current = this.state.getParticipant(pid);
|
|
2104
|
-
if (!current) continue;
|
|
2105
|
-
this.state.updateParticipantMedia(pid, {
|
|
2106
|
-
stream: current.media?.stream ?? null,
|
|
2107
|
-
micEnabled: !Boolean(participant.audio_muted),
|
|
2108
|
-
camEnabled: !Boolean(participant.video_muted),
|
|
2109
|
-
isScreenSharing: Boolean(participant.screen_sharing)
|
|
2110
|
-
});
|
|
2111
|
-
}
|
|
2112
|
-
const presenters = /* @__PURE__ */ new Set();
|
|
2113
|
-
for (const participant of roomState?.participants || []) {
|
|
2114
|
-
const pid = participant?.participant_id;
|
|
2115
|
-
if (!pid || pid === this.myId) continue;
|
|
2116
|
-
const current = this.state.getParticipant(pid);
|
|
2117
|
-
if (!current) continue;
|
|
2118
|
-
if (participant.screen_sharing) {
|
|
2119
|
-
presenters.add(pid);
|
|
2120
|
-
this.state.updateParticipantMedia(pid, {
|
|
2121
|
-
isScreenSharing: true,
|
|
2122
|
-
screenStream: current.media?.screenStream ?? null
|
|
2123
|
-
});
|
|
2124
|
-
} else if (current.media?.isScreenSharing) {
|
|
2125
|
-
const screen = this.remoteScreenStreams.get(pid);
|
|
2126
|
-
screen?.getTracks().forEach((track) => track.stop());
|
|
2127
|
-
this.remoteScreenStreams.delete(pid);
|
|
2128
|
-
this.state.updateParticipantMedia(pid, {
|
|
2129
|
-
isScreenSharing: false,
|
|
2130
|
-
screenStream: null,
|
|
2131
|
-
screenTrack: void 0
|
|
2132
|
-
});
|
|
2062
|
+
name: this.participantName,
|
|
2063
|
+
media: {
|
|
2064
|
+
micEnabled: this.localStream?.getAudioTracks()[0]?.enabled ?? true,
|
|
2065
|
+
camEnabled: this.localStream?.getVideoTracks()[0]?.enabled ?? true
|
|
2133
2066
|
}
|
|
2134
|
-
}
|
|
2135
|
-
const presenter = [...presenters][0] ?? null;
|
|
2136
|
-
if (this.state.presenterId !== presenter) {
|
|
2137
|
-
this.state.setPresenterId(presenter);
|
|
2138
|
-
}
|
|
2139
|
-
this.events.onRoomUpdate?.(roomState);
|
|
2067
|
+
});
|
|
2140
2068
|
},
|
|
2141
2069
|
onDisconnected: () => {
|
|
2142
2070
|
console.log("[SFU] Signaling WebSocket disconnected; reconnecting");
|
|
@@ -2204,22 +2132,44 @@ var VideoSDKCore = class {
|
|
|
2204
2132
|
return;
|
|
2205
2133
|
}
|
|
2206
2134
|
const pname = participant.user_metadata?.name || participant.display_name || "Participant";
|
|
2207
|
-
|
|
2135
|
+
const participantMedia = participant.media || {};
|
|
2136
|
+
const participantState = {
|
|
2208
2137
|
id: pid,
|
|
2209
2138
|
name: pname,
|
|
2210
|
-
connectionState: "connected",
|
|
2139
|
+
connectionState: participant.presence === "reconnecting" ? "reconnecting" : "connected",
|
|
2211
2140
|
media: {
|
|
2212
2141
|
micEnabled: !Boolean(participant.audio_muted),
|
|
2213
2142
|
camEnabled: !Boolean(participant.video_muted),
|
|
2214
|
-
isScreenSharing:
|
|
2143
|
+
isScreenSharing: Boolean(participant.screen_sharing),
|
|
2144
|
+
screenStream: participantMedia.screenStream ?? null,
|
|
2215
2145
|
stream: null
|
|
2216
2146
|
}
|
|
2217
|
-
}
|
|
2147
|
+
};
|
|
2148
|
+
if (!this.state.addParticipant(participantState)) {
|
|
2149
|
+
this.state.updateParticipantMedia(pid, participantState.media);
|
|
2150
|
+
}
|
|
2218
2151
|
this.events.onUserJoined?.({
|
|
2219
2152
|
id: pid,
|
|
2220
2153
|
name: pname
|
|
2221
2154
|
});
|
|
2222
2155
|
},
|
|
2156
|
+
onParticipantMediaState: (participantId, audioMuted, videoMuted) => {
|
|
2157
|
+
if (participantId === this.myId) {
|
|
2158
|
+
this.state.updateLocalParticipant({
|
|
2159
|
+
media: {
|
|
2160
|
+
micEnabled: !audioMuted,
|
|
2161
|
+
camEnabled: !videoMuted
|
|
2162
|
+
}
|
|
2163
|
+
});
|
|
2164
|
+
return;
|
|
2165
|
+
}
|
|
2166
|
+
this.state.updateParticipantMedia(participantId, {
|
|
2167
|
+
micEnabled: !audioMuted,
|
|
2168
|
+
camEnabled: !videoMuted
|
|
2169
|
+
});
|
|
2170
|
+
this.events.onMuteStateChanged?.(participantId, "audio", audioMuted);
|
|
2171
|
+
this.events.onMuteStateChanged?.(participantId, "video", videoMuted);
|
|
2172
|
+
},
|
|
2223
2173
|
onParticipantPresence: (participantId, presence) => {
|
|
2224
2174
|
if (participantId === this.myId) {
|
|
2225
2175
|
return;
|
|
@@ -2283,18 +2233,6 @@ var VideoSDKCore = class {
|
|
|
2283
2233
|
camEnabled: track.kind === "video" ? false : current.media?.camEnabled ?? true
|
|
2284
2234
|
});
|
|
2285
2235
|
},
|
|
2286
|
-
onParticipantMediaState: (participantId, audioMuted, videoMuted) => {
|
|
2287
|
-
if (participantId === this.myId) return;
|
|
2288
|
-
const current = this.state.getParticipant(participantId);
|
|
2289
|
-
if (!current) return;
|
|
2290
|
-
this.state.updateParticipantMedia(participantId, {
|
|
2291
|
-
stream: current.media?.stream ?? null,
|
|
2292
|
-
micEnabled: !audioMuted,
|
|
2293
|
-
camEnabled: !videoMuted
|
|
2294
|
-
});
|
|
2295
|
-
this.events.onMuteStateChanged?.(participantId, "audio", audioMuted);
|
|
2296
|
-
this.events.onMuteStateChanged?.(participantId, "video", videoMuted);
|
|
2297
|
-
},
|
|
2298
2236
|
onTrackStateChanged: (track) => {
|
|
2299
2237
|
const pid = track.participant_id;
|
|
2300
2238
|
if (!pid || pid === this.myId) {
|
|
@@ -2396,8 +2334,8 @@ var VideoSDKCore = class {
|
|
|
2396
2334
|
await client.getToken(roomId, {
|
|
2397
2335
|
displayName: name,
|
|
2398
2336
|
participantId: this.myId,
|
|
2399
|
-
audioMuted: this.
|
|
2400
|
-
videoMuted: this.
|
|
2337
|
+
audioMuted: !this.localStream?.getAudioTracks()[0]?.enabled,
|
|
2338
|
+
videoMuted: !this.localStream?.getVideoTracks()[0]?.enabled
|
|
2401
2339
|
});
|
|
2402
2340
|
}
|
|
2403
2341
|
// SFU STATE
|
|
@@ -2561,6 +2499,7 @@ var VideoSDKCore = class {
|
|
|
2561
2499
|
screenTrack: this.screenStream.getVideoTracks()[0]
|
|
2562
2500
|
}
|
|
2563
2501
|
});
|
|
2502
|
+
this.state.setPresenterId(this.myId);
|
|
2564
2503
|
return this.screenStream;
|
|
2565
2504
|
} catch (err) {
|
|
2566
2505
|
this.emitError(
|
|
@@ -2582,6 +2521,9 @@ var VideoSDKCore = class {
|
|
|
2582
2521
|
this.screenStream.getTracks().forEach((track) => track.stop());
|
|
2583
2522
|
this.screenStream = null;
|
|
2584
2523
|
this.isScreenSharing = false;
|
|
2524
|
+
if (this.state.presenterId === this.myId) {
|
|
2525
|
+
this.state.setPresenterId(null);
|
|
2526
|
+
}
|
|
2585
2527
|
this.state.updateLocalParticipant({
|
|
2586
2528
|
media: {
|
|
2587
2529
|
isScreenSharing: false,
|
|
@@ -2711,7 +2653,6 @@ var MeetingProvider = ({
|
|
|
2711
2653
|
/* @__PURE__ */ new Set()
|
|
2712
2654
|
);
|
|
2713
2655
|
const meetingLeftListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
2714
|
-
const roomUpdateListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
2715
2656
|
const trackStateListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
2716
2657
|
const recordingStartedListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
2717
2658
|
const recordingStoppedListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
@@ -2736,9 +2677,6 @@ var MeetingProvider = ({
|
|
|
2736
2677
|
onMeetingLeft: () => {
|
|
2737
2678
|
meetingLeftListeners.current.forEach((fn) => fn());
|
|
2738
2679
|
},
|
|
2739
|
-
onRoomUpdate: (data) => {
|
|
2740
|
-
roomUpdateListeners.current.forEach((fn) => fn(data));
|
|
2741
|
-
},
|
|
2742
2680
|
onTrackStateChanged: (track) => {
|
|
2743
2681
|
trackStateListeners.current.forEach((fn) => fn(track));
|
|
2744
2682
|
},
|
|
@@ -2837,10 +2775,6 @@ var MeetingProvider = ({
|
|
|
2837
2775
|
meetingLeftListeners.current.delete(cb);
|
|
2838
2776
|
};
|
|
2839
2777
|
},
|
|
2840
|
-
onRoomUpdate: (cb) => {
|
|
2841
|
-
roomUpdateListeners.current.add(cb);
|
|
2842
|
-
return () => roomUpdateListeners.current.delete(cb);
|
|
2843
|
-
},
|
|
2844
2778
|
onTrackStateChanged: (cb) => {
|
|
2845
2779
|
trackStateListeners.current.add(cb);
|
|
2846
2780
|
return () => trackStateListeners.current.delete(cb);
|