@defcomm/meetingsdk 0.2.6 → 0.2.7
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 +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +163 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +163 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -367,6 +367,8 @@ var SFUClient = class {
|
|
|
367
367
|
this.intentionalClose = false;
|
|
368
368
|
this.leaveAcknowledged = false;
|
|
369
369
|
this.joiningWithResume = false;
|
|
370
|
+
this.desiredAudioMuted = false;
|
|
371
|
+
this.desiredVideoMuted = false;
|
|
370
372
|
this.reconnectTimer = null;
|
|
371
373
|
this.reconnectAttempt = 0;
|
|
372
374
|
this.maxReconnectAttempts = 8;
|
|
@@ -435,6 +437,12 @@ var SFUClient = class {
|
|
|
435
437
|
this.onRecordingStopped = options.onRecordingStopped || (() => {
|
|
436
438
|
});
|
|
437
439
|
this.onError = options.onError || console.error;
|
|
440
|
+
this.onChatMessage = options.onChatMessage || (() => {
|
|
441
|
+
});
|
|
442
|
+
this.onRoomUpdate = options.onRoomUpdate || (() => {
|
|
443
|
+
});
|
|
444
|
+
this.onParticipantMediaState = options.onParticipantMediaState || (() => {
|
|
445
|
+
});
|
|
438
446
|
this.autoSubscribe = options.autoSubscribe !== false;
|
|
439
447
|
}
|
|
440
448
|
startHeartbeat() {
|
|
@@ -557,6 +565,8 @@ var SFUClient = class {
|
|
|
557
565
|
avatarUrl: options.avatarUrl
|
|
558
566
|
};
|
|
559
567
|
if (options.participantId) this.participantId = options.participantId;
|
|
568
|
+
if (typeof options.audioMuted === "boolean") this.desiredAudioMuted = options.audioMuted;
|
|
569
|
+
if (typeof options.videoMuted === "boolean") this.desiredVideoMuted = options.videoMuted;
|
|
560
570
|
if (!this.resumeToken) {
|
|
561
571
|
this.resumeToken = this.loadResumeToken(this.room);
|
|
562
572
|
}
|
|
@@ -623,7 +633,9 @@ var SFUClient = class {
|
|
|
623
633
|
room_code: this.room,
|
|
624
634
|
resume_token: this.resumeToken,
|
|
625
635
|
display_name: options.displayName,
|
|
626
|
-
avatar_url: options.avatarUrl
|
|
636
|
+
avatar_url: options.avatarUrl,
|
|
637
|
+
audio_muted: this.desiredAudioMuted,
|
|
638
|
+
video_muted: this.desiredVideoMuted
|
|
627
639
|
};
|
|
628
640
|
if (this.pendingJoinRequestId) {
|
|
629
641
|
this.send({
|
|
@@ -798,6 +810,16 @@ var SFUClient = class {
|
|
|
798
810
|
this.onParticipantLeft(participantId);
|
|
799
811
|
break;
|
|
800
812
|
}
|
|
813
|
+
case "participant_media_state": {
|
|
814
|
+
const participantId = payload.participant_id;
|
|
815
|
+
if (!participantId) break;
|
|
816
|
+
this.onParticipantMediaState(
|
|
817
|
+
participantId,
|
|
818
|
+
Boolean(payload.audio_muted),
|
|
819
|
+
Boolean(payload.video_muted)
|
|
820
|
+
);
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
801
823
|
case "participant_presence":
|
|
802
824
|
case "participant_presence_changed": {
|
|
803
825
|
const participantId = payload.participant_id;
|
|
@@ -920,6 +942,37 @@ var SFUClient = class {
|
|
|
920
942
|
this.onScreenShareStopped(participantId, trackId);
|
|
921
943
|
break;
|
|
922
944
|
}
|
|
945
|
+
case "room_state": {
|
|
946
|
+
const participants = payload.participants || [];
|
|
947
|
+
this.onRoomStateReconciled(payload);
|
|
948
|
+
this.onRoomUpdate(payload);
|
|
949
|
+
for (const participant of participants) {
|
|
950
|
+
const pid = participant?.participant_id;
|
|
951
|
+
if (!pid) continue;
|
|
952
|
+
if (pid !== this.currentParticipantId) {
|
|
953
|
+
this.participants.set(pid, participant);
|
|
954
|
+
this.onParticipantPresence(pid, String(participant.presence || "connected"));
|
|
955
|
+
this.onParticipantMediaState(pid, Boolean(participant.audio_muted), Boolean(participant.video_muted));
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
for (const [pid] of this.participants) {
|
|
959
|
+
if (!participants.some((p) => p?.participant_id === pid)) {
|
|
960
|
+
this.participants.delete(pid);
|
|
961
|
+
this.removeRemoteParticipant(pid);
|
|
962
|
+
this.onParticipantLeft(pid);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
for (const track of payload.tracks || []) this.rememberTrack(track);
|
|
966
|
+
if (Array.isArray(payload.chat_history)) {
|
|
967
|
+
for (const message2 of payload.chat_history) this.onChatMessage(message2);
|
|
968
|
+
}
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
case "chat_message": {
|
|
972
|
+
const msg = payload.message || payload;
|
|
973
|
+
if (msg?.id) this.onChatMessage(msg);
|
|
974
|
+
break;
|
|
975
|
+
}
|
|
923
976
|
case "error": {
|
|
924
977
|
const message2 = payload.message || "SFU signaling error";
|
|
925
978
|
if (this.state === "reconnecting" && message2.includes("participant session is stale")) {
|
|
@@ -942,6 +995,14 @@ var SFUClient = class {
|
|
|
942
995
|
console.debug("[SFU] Ignoring unknown server message", message);
|
|
943
996
|
}
|
|
944
997
|
}
|
|
998
|
+
onRoomStateReconciled(payload) {
|
|
999
|
+
const participants = payload.participants || [];
|
|
1000
|
+
const local = participants.find((p) => p?.participant_id === this.currentParticipantId);
|
|
1001
|
+
if (local) {
|
|
1002
|
+
this.desiredAudioMuted = Boolean(local.audio_muted);
|
|
1003
|
+
this.desiredVideoMuted = Boolean(local.video_muted);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
945
1006
|
rememberTrack(track) {
|
|
946
1007
|
this.trackMetadata.set(track.track_id, track);
|
|
947
1008
|
this.trackToParticipant.set(track.track_id, track.participant_id);
|
|
@@ -977,8 +1038,21 @@ var SFUClient = class {
|
|
|
977
1038
|
for (const participant of this.participants.values()) {
|
|
978
1039
|
if (participant.participant_id !== this.currentParticipantId) {
|
|
979
1040
|
this.onParticipantJoined(participant);
|
|
1041
|
+
this.onParticipantPresence(
|
|
1042
|
+
participant.participant_id,
|
|
1043
|
+
String(participant.presence || "connected")
|
|
1044
|
+
);
|
|
1045
|
+
this.onParticipantMediaState(
|
|
1046
|
+
participant.participant_id,
|
|
1047
|
+
Boolean(participant.audio_muted),
|
|
1048
|
+
Boolean(participant.video_muted)
|
|
1049
|
+
);
|
|
980
1050
|
}
|
|
981
1051
|
}
|
|
1052
|
+
if (Array.isArray(payload.chat_history)) {
|
|
1053
|
+
for (const message of payload.chat_history) this.onChatMessage(message);
|
|
1054
|
+
}
|
|
1055
|
+
this.onRoomUpdate(payload);
|
|
982
1056
|
if (this.localStream) {
|
|
983
1057
|
await this.publishExistingTracks();
|
|
984
1058
|
}
|
|
@@ -1351,9 +1425,6 @@ var SFUClient = class {
|
|
|
1351
1425
|
}
|
|
1352
1426
|
this.screenStream = screenStream;
|
|
1353
1427
|
try {
|
|
1354
|
-
if (!this.send({ type: "start_screen_share" })) {
|
|
1355
|
-
throw new Error("Failed to signal start_screen_share");
|
|
1356
|
-
}
|
|
1357
1428
|
await this.screenSender.replaceTrack(screenTrack);
|
|
1358
1429
|
this.screenTransceiver.direction = "sendonly";
|
|
1359
1430
|
const offer = await this.publisher.createOffer();
|
|
@@ -1365,6 +1436,7 @@ var SFUClient = class {
|
|
|
1365
1436
|
sdp: offer.sdp
|
|
1366
1437
|
}
|
|
1367
1438
|
});
|
|
1439
|
+
this.send({ type: "start_screen_share" });
|
|
1368
1440
|
screenTrack.onended = () => {
|
|
1369
1441
|
void this.stopScreenShare();
|
|
1370
1442
|
};
|
|
@@ -1425,9 +1497,14 @@ var SFUClient = class {
|
|
|
1425
1497
|
}
|
|
1426
1498
|
}
|
|
1427
1499
|
muteAudio(muted) {
|
|
1500
|
+
this.desiredAudioMuted = muted;
|
|
1428
1501
|
this.localStream?.getAudioTracks().forEach((track) => {
|
|
1429
1502
|
track.enabled = !muted;
|
|
1430
1503
|
});
|
|
1504
|
+
this.send({
|
|
1505
|
+
type: "set_media_state",
|
|
1506
|
+
payload: { audio_muted: muted, video_muted: this.desiredVideoMuted }
|
|
1507
|
+
});
|
|
1431
1508
|
const trackId = this.localTrackIds.get("audio");
|
|
1432
1509
|
if (trackId) {
|
|
1433
1510
|
this.send({
|
|
@@ -1440,9 +1517,14 @@ var SFUClient = class {
|
|
|
1440
1517
|
}
|
|
1441
1518
|
}
|
|
1442
1519
|
muteVideo(muted) {
|
|
1520
|
+
this.desiredVideoMuted = muted;
|
|
1443
1521
|
this.localStream?.getVideoTracks().forEach((track) => {
|
|
1444
1522
|
track.enabled = !muted;
|
|
1445
1523
|
});
|
|
1524
|
+
this.send({
|
|
1525
|
+
type: "set_media_state",
|
|
1526
|
+
payload: { audio_muted: this.desiredAudioMuted, video_muted: muted }
|
|
1527
|
+
});
|
|
1446
1528
|
const trackId = this.localTrackIds.get("camera");
|
|
1447
1529
|
if (trackId) {
|
|
1448
1530
|
this.send({
|
|
@@ -1454,6 +1536,16 @@ var SFUClient = class {
|
|
|
1454
1536
|
});
|
|
1455
1537
|
}
|
|
1456
1538
|
}
|
|
1539
|
+
sendChatMessage(input) {
|
|
1540
|
+
return this.send({
|
|
1541
|
+
type: "send_chat",
|
|
1542
|
+
payload: {
|
|
1543
|
+
message: input.message,
|
|
1544
|
+
reply_to: input.reply_to ?? null,
|
|
1545
|
+
target: input.target ?? null
|
|
1546
|
+
}
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1457
1549
|
async startRecording() {
|
|
1458
1550
|
if (!this.send({ type: "start_recording" })) {
|
|
1459
1551
|
throw new Error("SFU signaling is not connected");
|
|
@@ -1921,6 +2013,41 @@ var VideoSDKCore = class {
|
|
|
1921
2013
|
console.warn(`[SFU] Reconnecting, attempt ${attempt}`);
|
|
1922
2014
|
},
|
|
1923
2015
|
// ADMISSION CONTROL
|
|
2016
|
+
onRoomUpdate: (payload) => {
|
|
2017
|
+
const participants = payload?.participants || [];
|
|
2018
|
+
const local = participants.find((p) => p?.participant_id === this.myId);
|
|
2019
|
+
if (local) {
|
|
2020
|
+
const media = this.state.localParticipant?.media;
|
|
2021
|
+
this.state.updateLocalParticipant({
|
|
2022
|
+
id: this.myId,
|
|
2023
|
+
name: this.participantName,
|
|
2024
|
+
media: {
|
|
2025
|
+
micEnabled: !Boolean(local.audio_muted),
|
|
2026
|
+
camEnabled: !Boolean(local.video_muted),
|
|
2027
|
+
isScreenSharing: Boolean(local.screen_sharing),
|
|
2028
|
+
screenStream: this.screenStream,
|
|
2029
|
+
screenTrack: this.screenStream?.getVideoTracks()[0]
|
|
2030
|
+
}
|
|
2031
|
+
});
|
|
2032
|
+
if (this.localStream) {
|
|
2033
|
+
this.localStream.getAudioTracks().forEach((track) => {
|
|
2034
|
+
track.enabled = !Boolean(local.audio_muted);
|
|
2035
|
+
});
|
|
2036
|
+
this.localStream.getVideoTracks().forEach((track) => {
|
|
2037
|
+
track.enabled = !Boolean(local.video_muted);
|
|
2038
|
+
});
|
|
2039
|
+
}
|
|
2040
|
+
if (local.screen_sharing) this.state.setPresenterId(this.myId);
|
|
2041
|
+
else if (this.state.presenterId === this.myId) this.state.setPresenterId(null);
|
|
2042
|
+
}
|
|
2043
|
+
const presenter = participants.find((p) => p?.screen_sharing);
|
|
2044
|
+
if (presenter) this.state.setPresenterId(presenter.participant_id);
|
|
2045
|
+
else if (!local?.screen_sharing) this.state.setPresenterId(null);
|
|
2046
|
+
for (const message of payload?.chat_history || []) {
|
|
2047
|
+
this.state.addChatMessage(message);
|
|
2048
|
+
}
|
|
2049
|
+
this.events.onRoomUpdate?.(payload);
|
|
2050
|
+
},
|
|
1924
2051
|
onJoinPending: (info) => {
|
|
1925
2052
|
console.log("[SFU] Join request pending", info);
|
|
1926
2053
|
},
|
|
@@ -1955,6 +2082,19 @@ var VideoSDKCore = class {
|
|
|
1955
2082
|
false
|
|
1956
2083
|
);
|
|
1957
2084
|
},
|
|
2085
|
+
onChatMessage: (message) => {
|
|
2086
|
+
const msg = {
|
|
2087
|
+
id: message.id,
|
|
2088
|
+
text: message.text,
|
|
2089
|
+
sender_id: message.sender_id,
|
|
2090
|
+
sender_name: message.sender_name,
|
|
2091
|
+
timestamp: Number(message.timestamp),
|
|
2092
|
+
reply_to: message.reply_to ?? null,
|
|
2093
|
+
target: message.target ?? null
|
|
2094
|
+
};
|
|
2095
|
+
this.state.addChatMessage(msg);
|
|
2096
|
+
this.events.onChatMessage?.(msg);
|
|
2097
|
+
},
|
|
1958
2098
|
onJoinRequested: (request) => {
|
|
1959
2099
|
const requestId = request?.request_id || request?.requestId;
|
|
1960
2100
|
const participantId = request?.user_id || request?.participantId;
|
|
@@ -2023,6 +2163,17 @@ var VideoSDKCore = class {
|
|
|
2023
2163
|
this.events.onUserLeft?.(pid);
|
|
2024
2164
|
},
|
|
2025
2165
|
// TRACKS
|
|
2166
|
+
onParticipantMediaState: (participantId, audioMuted, videoMuted) => {
|
|
2167
|
+
if (participantId === this.myId) return;
|
|
2168
|
+
const participant = this.state.getParticipant(participantId);
|
|
2169
|
+
if (!participant) return;
|
|
2170
|
+
this.state.updateParticipantMedia(participantId, {
|
|
2171
|
+
micEnabled: !audioMuted,
|
|
2172
|
+
camEnabled: !videoMuted
|
|
2173
|
+
});
|
|
2174
|
+
this.events.onMuteStateChanged?.(participantId, "audio", audioMuted);
|
|
2175
|
+
this.events.onMuteStateChanged?.(participantId, "video", videoMuted);
|
|
2176
|
+
},
|
|
2026
2177
|
onTrackPublished: (track) => {
|
|
2027
2178
|
console.log("[SFU] Track published", track);
|
|
2028
2179
|
},
|
|
@@ -2092,6 +2243,9 @@ var VideoSDKCore = class {
|
|
|
2092
2243
|
// SCREEN SHARE
|
|
2093
2244
|
onScreenShareStarted: (participantId, _track) => {
|
|
2094
2245
|
console.log("[SFU] Screen share started", participantId);
|
|
2246
|
+
if (participantId === this.myId && !this.screenStream) {
|
|
2247
|
+
this.screenStream = this.sfuClient?.getScreenStream() ?? null;
|
|
2248
|
+
}
|
|
2095
2249
|
this.state.setPresenterId(participantId);
|
|
2096
2250
|
if (participantId === this.myId) {
|
|
2097
2251
|
this.state.updateLocalParticipant({
|
|
@@ -2372,18 +2526,13 @@ var VideoSDKCore = class {
|
|
|
2372
2526
|
console.warn("SFU Client not connected");
|
|
2373
2527
|
return;
|
|
2374
2528
|
}
|
|
2375
|
-
const
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
sender_name: senderName,
|
|
2380
|
-
text: payload.message.trim(),
|
|
2381
|
-
timestamp: Date.now(),
|
|
2529
|
+
const message = payload.message.trim();
|
|
2530
|
+
if (!message) return;
|
|
2531
|
+
this.sfuClient.sendChatMessage({
|
|
2532
|
+
message,
|
|
2382
2533
|
reply_to: payload.reply_to ?? null,
|
|
2383
2534
|
target: payload.target ?? null
|
|
2384
|
-
};
|
|
2385
|
-
this.state.addChatMessage(msg);
|
|
2386
|
-
this.events.onChatMessage?.(msg);
|
|
2535
|
+
});
|
|
2387
2536
|
}
|
|
2388
2537
|
// CLEANUP
|
|
2389
2538
|
cleanupRemoteParticipant(participantId) {
|