@defcomm/meetingsdk 0.2.3 → 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 +6 -11
- package/dist/index.d.ts +6 -11
- package/dist/index.js +151 -144
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +151 -144
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -259,6 +259,7 @@ interface SFUClientOptions {
|
|
|
259
259
|
onParticipantJoined?: (participant: ParticipantInfo) => void;
|
|
260
260
|
onParticipantLeft?: (participant: string | ParticipantInfo) => void;
|
|
261
261
|
onParticipantPresence?: (participantId: string, presence: string) => void;
|
|
262
|
+
onParticipantMediaState?: (participantId: string, audioMuted: boolean, videoMuted: boolean) => void;
|
|
262
263
|
onTrackPublished?: (track: TrackInfo) => void;
|
|
263
264
|
onTrackUnpublished?: (track: TrackInfo) => void;
|
|
264
265
|
onRemoteTrack?: (track: MediaStreamTrack, stream: MediaStream, metadata: TrackInfo) => void;
|
|
@@ -280,8 +281,6 @@ interface SFUClientOptions {
|
|
|
280
281
|
recording_id: string;
|
|
281
282
|
stopped_at: string;
|
|
282
283
|
}) => void;
|
|
283
|
-
/** Authoritative room snapshot received after join/reconnect/resync. */
|
|
284
|
-
onRoomState?: (state: any) => void;
|
|
285
284
|
onError?: (error: any) => void;
|
|
286
285
|
autoSubscribe?: boolean;
|
|
287
286
|
}
|
|
@@ -335,12 +334,11 @@ declare class SFUClient {
|
|
|
335
334
|
private trackToSource;
|
|
336
335
|
private localTrackIds;
|
|
337
336
|
private subscriberStatsTimer;
|
|
338
|
-
private roomSyncTimer;
|
|
339
|
-
private roomSyncInFlight;
|
|
340
337
|
private onStateChange;
|
|
341
338
|
private onParticipantJoined;
|
|
342
339
|
private onParticipantLeft;
|
|
343
340
|
private onParticipantPresence;
|
|
341
|
+
private onParticipantMediaState;
|
|
344
342
|
private onTrackPublished;
|
|
345
343
|
private onTrackUnpublished;
|
|
346
344
|
private onRemoteTrack;
|
|
@@ -356,16 +354,13 @@ declare class SFUClient {
|
|
|
356
354
|
private onTrackStateChanged;
|
|
357
355
|
private onRecordingStarted;
|
|
358
356
|
private onRecordingStopped;
|
|
359
|
-
private
|
|
357
|
+
private lastRecordingId;
|
|
360
358
|
private onError;
|
|
361
359
|
private autoSubscribe;
|
|
362
360
|
constructor(options?: SFUClientOptions);
|
|
363
361
|
private heartbeatTimer;
|
|
364
362
|
private startHeartbeat;
|
|
365
363
|
private stopHeartbeat;
|
|
366
|
-
private startRoomStateSync;
|
|
367
|
-
private stopRoomStateSync;
|
|
368
|
-
private syncRoomState;
|
|
369
364
|
private createId;
|
|
370
365
|
private resumeStorageKey;
|
|
371
366
|
private loadResumeToken;
|
|
@@ -392,6 +387,8 @@ declare class SFUClient {
|
|
|
392
387
|
displayName?: string;
|
|
393
388
|
avatarUrl?: string;
|
|
394
389
|
participantId?: string;
|
|
390
|
+
audioMuted?: boolean;
|
|
391
|
+
videoMuted?: boolean;
|
|
395
392
|
}): Promise<void>;
|
|
396
393
|
private refreshAccessToken;
|
|
397
394
|
private connect;
|
|
@@ -400,7 +397,7 @@ declare class SFUClient {
|
|
|
400
397
|
private failJoin;
|
|
401
398
|
private resolveJoin;
|
|
402
399
|
private handleServerMessage;
|
|
403
|
-
private
|
|
400
|
+
private reconcileRoomState;
|
|
404
401
|
private rememberTrack;
|
|
405
402
|
private handleJoined;
|
|
406
403
|
private initializePeerConnections;
|
|
@@ -478,7 +475,6 @@ type MeetingContextValue = {
|
|
|
478
475
|
onEntryRequested: (cb: (req: any) => void) => () => void;
|
|
479
476
|
onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;
|
|
480
477
|
onMeetingLeft: (cb: () => void) => () => void;
|
|
481
|
-
onRoomUpdate: (cb: (data: any) => void) => () => void;
|
|
482
478
|
onTrackStateChanged: (cb: (track: any) => void) => () => void;
|
|
483
479
|
onRecordingStarted: (cb: (recording: Recording) => void) => () => void;
|
|
484
480
|
onRecordingStopped: (cb: (recording: any) => void) => () => void;
|
|
@@ -537,7 +533,6 @@ declare const useMeeting: (handlers?: {
|
|
|
537
533
|
onEntryRequested: (cb: (req: any) => void) => () => void;
|
|
538
534
|
onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;
|
|
539
535
|
onMeetingLeft: (cb: () => void) => () => void;
|
|
540
|
-
onRoomUpdate: (cb: (data: any) => void) => () => void;
|
|
541
536
|
onTrackStateChanged: (cb: (track: any) => void) => () => void;
|
|
542
537
|
onRecordingStarted: (cb: (recording: Recording) => void) => () => void;
|
|
543
538
|
onRecordingStopped: (cb: (recording: any) => void) => () => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -259,6 +259,7 @@ interface SFUClientOptions {
|
|
|
259
259
|
onParticipantJoined?: (participant: ParticipantInfo) => void;
|
|
260
260
|
onParticipantLeft?: (participant: string | ParticipantInfo) => void;
|
|
261
261
|
onParticipantPresence?: (participantId: string, presence: string) => void;
|
|
262
|
+
onParticipantMediaState?: (participantId: string, audioMuted: boolean, videoMuted: boolean) => void;
|
|
262
263
|
onTrackPublished?: (track: TrackInfo) => void;
|
|
263
264
|
onTrackUnpublished?: (track: TrackInfo) => void;
|
|
264
265
|
onRemoteTrack?: (track: MediaStreamTrack, stream: MediaStream, metadata: TrackInfo) => void;
|
|
@@ -280,8 +281,6 @@ interface SFUClientOptions {
|
|
|
280
281
|
recording_id: string;
|
|
281
282
|
stopped_at: string;
|
|
282
283
|
}) => void;
|
|
283
|
-
/** Authoritative room snapshot received after join/reconnect/resync. */
|
|
284
|
-
onRoomState?: (state: any) => void;
|
|
285
284
|
onError?: (error: any) => void;
|
|
286
285
|
autoSubscribe?: boolean;
|
|
287
286
|
}
|
|
@@ -335,12 +334,11 @@ declare class SFUClient {
|
|
|
335
334
|
private trackToSource;
|
|
336
335
|
private localTrackIds;
|
|
337
336
|
private subscriberStatsTimer;
|
|
338
|
-
private roomSyncTimer;
|
|
339
|
-
private roomSyncInFlight;
|
|
340
337
|
private onStateChange;
|
|
341
338
|
private onParticipantJoined;
|
|
342
339
|
private onParticipantLeft;
|
|
343
340
|
private onParticipantPresence;
|
|
341
|
+
private onParticipantMediaState;
|
|
344
342
|
private onTrackPublished;
|
|
345
343
|
private onTrackUnpublished;
|
|
346
344
|
private onRemoteTrack;
|
|
@@ -356,16 +354,13 @@ declare class SFUClient {
|
|
|
356
354
|
private onTrackStateChanged;
|
|
357
355
|
private onRecordingStarted;
|
|
358
356
|
private onRecordingStopped;
|
|
359
|
-
private
|
|
357
|
+
private lastRecordingId;
|
|
360
358
|
private onError;
|
|
361
359
|
private autoSubscribe;
|
|
362
360
|
constructor(options?: SFUClientOptions);
|
|
363
361
|
private heartbeatTimer;
|
|
364
362
|
private startHeartbeat;
|
|
365
363
|
private stopHeartbeat;
|
|
366
|
-
private startRoomStateSync;
|
|
367
|
-
private stopRoomStateSync;
|
|
368
|
-
private syncRoomState;
|
|
369
364
|
private createId;
|
|
370
365
|
private resumeStorageKey;
|
|
371
366
|
private loadResumeToken;
|
|
@@ -392,6 +387,8 @@ declare class SFUClient {
|
|
|
392
387
|
displayName?: string;
|
|
393
388
|
avatarUrl?: string;
|
|
394
389
|
participantId?: string;
|
|
390
|
+
audioMuted?: boolean;
|
|
391
|
+
videoMuted?: boolean;
|
|
395
392
|
}): Promise<void>;
|
|
396
393
|
private refreshAccessToken;
|
|
397
394
|
private connect;
|
|
@@ -400,7 +397,7 @@ declare class SFUClient {
|
|
|
400
397
|
private failJoin;
|
|
401
398
|
private resolveJoin;
|
|
402
399
|
private handleServerMessage;
|
|
403
|
-
private
|
|
400
|
+
private reconcileRoomState;
|
|
404
401
|
private rememberTrack;
|
|
405
402
|
private handleJoined;
|
|
406
403
|
private initializePeerConnections;
|
|
@@ -478,7 +475,6 @@ type MeetingContextValue = {
|
|
|
478
475
|
onEntryRequested: (cb: (req: any) => void) => () => void;
|
|
479
476
|
onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;
|
|
480
477
|
onMeetingLeft: (cb: () => void) => () => void;
|
|
481
|
-
onRoomUpdate: (cb: (data: any) => void) => () => void;
|
|
482
478
|
onTrackStateChanged: (cb: (track: any) => void) => () => void;
|
|
483
479
|
onRecordingStarted: (cb: (recording: Recording) => void) => () => void;
|
|
484
480
|
onRecordingStopped: (cb: (recording: any) => void) => () => void;
|
|
@@ -537,7 +533,6 @@ declare const useMeeting: (handlers?: {
|
|
|
537
533
|
onEntryRequested: (cb: (req: any) => void) => () => void;
|
|
538
534
|
onEntryResponded: (cb: (payload: any, decision?: any) => void) => () => void;
|
|
539
535
|
onMeetingLeft: (cb: () => void) => () => void;
|
|
540
|
-
onRoomUpdate: (cb: (data: any) => void) => () => void;
|
|
541
536
|
onTrackStateChanged: (cb: (track: any) => void) => () => void;
|
|
542
537
|
onRecordingStarted: (cb: (recording: Recording) => void) => () => void;
|
|
543
538
|
onRecordingStopped: (cb: (recording: any) => void) => () => void;
|
package/dist/index.js
CHANGED
|
@@ -428,8 +428,7 @@ var SFUClient = class {
|
|
|
428
428
|
this.trackToSource = /* @__PURE__ */ new Map();
|
|
429
429
|
this.localTrackIds = /* @__PURE__ */ new Map();
|
|
430
430
|
this.subscriberStatsTimer = null;
|
|
431
|
-
this.
|
|
432
|
-
this.roomSyncInFlight = false;
|
|
431
|
+
this.lastRecordingId = null;
|
|
433
432
|
this.heartbeatTimer = null;
|
|
434
433
|
this.apiBase = options.apiBase || "https://api.example.com/api";
|
|
435
434
|
this.wsBase = options.wsBase || "wss://api.example.com/ws";
|
|
@@ -442,6 +441,8 @@ var SFUClient = class {
|
|
|
442
441
|
});
|
|
443
442
|
this.onParticipantPresence = options.onParticipantPresence || (() => {
|
|
444
443
|
});
|
|
444
|
+
this.onParticipantMediaState = options.onParticipantMediaState || (() => {
|
|
445
|
+
});
|
|
445
446
|
this.onTrackPublished = options.onTrackPublished || (() => {
|
|
446
447
|
});
|
|
447
448
|
this.onTrackUnpublished = options.onTrackUnpublished || (() => {
|
|
@@ -472,8 +473,6 @@ var SFUClient = class {
|
|
|
472
473
|
});
|
|
473
474
|
this.onRecordingStopped = options.onRecordingStopped || (() => {
|
|
474
475
|
});
|
|
475
|
-
this.onRoomState = options.onRoomState || (() => {
|
|
476
|
-
});
|
|
477
476
|
this.onError = options.onError || console.error;
|
|
478
477
|
this.autoSubscribe = options.autoSubscribe !== false;
|
|
479
478
|
}
|
|
@@ -495,29 +494,6 @@ var SFUClient = class {
|
|
|
495
494
|
this.heartbeatTimer = null;
|
|
496
495
|
}
|
|
497
496
|
}
|
|
498
|
-
startRoomStateSync() {
|
|
499
|
-
this.stopRoomStateSync();
|
|
500
|
-
this.roomSyncTimer = setInterval(() => {
|
|
501
|
-
if (this.state !== "connected") return;
|
|
502
|
-
void this.syncRoomState();
|
|
503
|
-
}, 5e3);
|
|
504
|
-
}
|
|
505
|
-
stopRoomStateSync() {
|
|
506
|
-
if (this.roomSyncTimer) {
|
|
507
|
-
clearInterval(this.roomSyncTimer);
|
|
508
|
-
this.roomSyncTimer = null;
|
|
509
|
-
}
|
|
510
|
-
this.roomSyncInFlight = false;
|
|
511
|
-
}
|
|
512
|
-
async syncRoomState() {
|
|
513
|
-
if (this.roomSyncInFlight || !this.isSocketOpen()) return;
|
|
514
|
-
this.roomSyncInFlight = true;
|
|
515
|
-
try {
|
|
516
|
-
this.send({ type: "sync_room_state" });
|
|
517
|
-
} finally {
|
|
518
|
-
this.roomSyncInFlight = false;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
497
|
createId() {
|
|
522
498
|
return typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `id_${Math.random().toString(36).slice(2)}_${Date.now()}`;
|
|
523
499
|
}
|
|
@@ -617,7 +593,9 @@ var SFUClient = class {
|
|
|
617
593
|
this.room = nextRoom;
|
|
618
594
|
this.joinOptions = {
|
|
619
595
|
displayName: options.displayName,
|
|
620
|
-
avatarUrl: options.avatarUrl
|
|
596
|
+
avatarUrl: options.avatarUrl,
|
|
597
|
+
audioMuted: options.audioMuted,
|
|
598
|
+
videoMuted: options.videoMuted
|
|
621
599
|
};
|
|
622
600
|
if (options.participantId) this.participantId = options.participantId;
|
|
623
601
|
if (!this.resumeToken) {
|
|
@@ -686,7 +664,9 @@ var SFUClient = class {
|
|
|
686
664
|
room_code: this.room,
|
|
687
665
|
resume_token: this.resumeToken,
|
|
688
666
|
display_name: options.displayName,
|
|
689
|
-
avatar_url: options.avatarUrl
|
|
667
|
+
avatar_url: options.avatarUrl,
|
|
668
|
+
audio_muted: options.audioMuted ?? this.joinOptions.audioMuted ?? false,
|
|
669
|
+
video_muted: options.videoMuted ?? this.joinOptions.videoMuted ?? false
|
|
690
670
|
};
|
|
691
671
|
if (this.pendingJoinRequestId) {
|
|
692
672
|
this.send({
|
|
@@ -800,7 +780,9 @@ var SFUClient = class {
|
|
|
800
780
|
room_code: this.room,
|
|
801
781
|
resume_token: this.resumeToken,
|
|
802
782
|
display_name: this.joinOptions.displayName,
|
|
803
|
-
avatar_url: this.joinOptions.avatarUrl
|
|
783
|
+
avatar_url: this.joinOptions.avatarUrl,
|
|
784
|
+
audio_muted: this.joinOptions.audioMuted ?? false,
|
|
785
|
+
video_muted: this.joinOptions.videoMuted ?? false
|
|
804
786
|
}
|
|
805
787
|
});
|
|
806
788
|
}
|
|
@@ -940,11 +922,8 @@ var SFUClient = class {
|
|
|
940
922
|
case "subscription_updated": {
|
|
941
923
|
break;
|
|
942
924
|
}
|
|
943
|
-
case "room_state": {
|
|
944
|
-
await this.applyRoomState(payload);
|
|
945
|
-
break;
|
|
946
|
-
}
|
|
947
925
|
case "recording_started": {
|
|
926
|
+
this.lastRecordingId = payload.recording_id || this.lastRecordingId;
|
|
948
927
|
this.onRecordingStarted({
|
|
949
928
|
recording_id: payload.recording_id,
|
|
950
929
|
started_at: payload.started_at
|
|
@@ -952,6 +931,7 @@ var SFUClient = class {
|
|
|
952
931
|
break;
|
|
953
932
|
}
|
|
954
933
|
case "recording_stopped": {
|
|
934
|
+
this.lastRecordingId = null;
|
|
955
935
|
this.onRecordingStopped({
|
|
956
936
|
recording_id: payload.recording_id,
|
|
957
937
|
stopped_at: payload.stopped_at
|
|
@@ -987,6 +967,29 @@ var SFUClient = class {
|
|
|
987
967
|
this.onScreenShareStopped(participantId, trackId);
|
|
988
968
|
break;
|
|
989
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
|
+
}
|
|
990
993
|
case "error": {
|
|
991
994
|
const message2 = payload.message || "SFU signaling error";
|
|
992
995
|
if (this.state === "reconnecting" && message2.includes("participant session is stale")) {
|
|
@@ -1009,71 +1012,89 @@ var SFUClient = class {
|
|
|
1009
1012
|
console.debug("[SFU] Ignoring unknown server message", message);
|
|
1010
1013
|
}
|
|
1011
1014
|
}
|
|
1012
|
-
async
|
|
1015
|
+
async reconcileRoomState(payload) {
|
|
1013
1016
|
const nextParticipants = /* @__PURE__ */ new Map();
|
|
1014
1017
|
for (const participant of payload.participants || []) {
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
}
|
|
1019
|
-
for (const
|
|
1020
|
-
if (
|
|
1021
|
-
|
|
1022
|
-
this.
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
const
|
|
1030
|
-
this.participants.set(
|
|
1031
|
-
if (!
|
|
1018
|
+
if (participant?.participant_id) {
|
|
1019
|
+
nextParticipants.set(participant.participant_id, participant);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
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);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
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) {
|
|
1032
1035
|
this.onParticipantJoined(participant);
|
|
1033
1036
|
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
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
|
+
);
|
|
1045
1055
|
}
|
|
1046
1056
|
}
|
|
1047
1057
|
const nextTracks = /* @__PURE__ */ new Map();
|
|
1048
1058
|
for (const track of payload.tracks || []) {
|
|
1049
|
-
if (track?.track_id)
|
|
1059
|
+
if (track?.track_id) {
|
|
1060
|
+
nextTracks.set(track.track_id, track);
|
|
1061
|
+
this.rememberTrack(track);
|
|
1062
|
+
}
|
|
1050
1063
|
}
|
|
1051
|
-
for (const [trackId,
|
|
1064
|
+
for (const [trackId, oldTrack] of [...this.trackMetadata.entries()]) {
|
|
1052
1065
|
if (!nextTracks.has(trackId)) {
|
|
1053
1066
|
this.trackMetadata.delete(trackId);
|
|
1054
1067
|
this.trackToParticipant.delete(trackId);
|
|
1055
1068
|
this.trackToSource.delete(trackId);
|
|
1056
1069
|
this.subscribedTracks.delete(trackId);
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
}
|
|
1060
|
-
if (existing.participant_id !== this.currentParticipantId) {
|
|
1061
|
-
this.onTrackUnpublished(existing);
|
|
1070
|
+
if (oldTrack.participant_id !== this.currentParticipantId) {
|
|
1071
|
+
this.onTrackUnpublished(oldTrack);
|
|
1062
1072
|
}
|
|
1063
1073
|
}
|
|
1064
1074
|
}
|
|
1065
|
-
for (const track of nextTracks.values()) {
|
|
1066
|
-
this.rememberTrack(track);
|
|
1067
|
-
}
|
|
1068
1075
|
if (this.autoSubscribe) {
|
|
1069
1076
|
const missing = [...nextTracks.values()].filter(
|
|
1070
1077
|
(track) => track.participant_id !== this.currentParticipantId && !this.subscribedTracks.has(track.track_id)
|
|
1071
1078
|
).map((track) => track.track_id);
|
|
1072
|
-
if (missing.length)
|
|
1073
|
-
|
|
1079
|
+
if (missing.length) await this.subscribeMultiple(missing);
|
|
1080
|
+
}
|
|
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
|
+
});
|
|
1074
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
|
+
});
|
|
1075
1097
|
}
|
|
1076
|
-
this.onRoomState(payload);
|
|
1077
1098
|
}
|
|
1078
1099
|
rememberTrack(track) {
|
|
1079
1100
|
this.trackMetadata.set(track.track_id, track);
|
|
@@ -1104,15 +1125,8 @@ var SFUClient = class {
|
|
|
1104
1125
|
for (const track of payload.tracks || []) {
|
|
1105
1126
|
if (track?.track_id) this.rememberTrack(track);
|
|
1106
1127
|
}
|
|
1107
|
-
if (payload.recording) {
|
|
1108
|
-
this.onRecordingStarted({
|
|
1109
|
-
recording_id: payload.recording.recording_id,
|
|
1110
|
-
started_at: payload.recording.started_at
|
|
1111
|
-
});
|
|
1112
|
-
}
|
|
1113
1128
|
await this.initializePeerConnections();
|
|
1114
1129
|
this.setState("connected");
|
|
1115
|
-
this.startRoomStateSync();
|
|
1116
1130
|
this.onConnected(payload, resumed);
|
|
1117
1131
|
for (const participant of this.participants.values()) {
|
|
1118
1132
|
if (participant.participant_id !== this.currentParticipantId) {
|
|
@@ -1568,31 +1582,25 @@ var SFUClient = class {
|
|
|
1568
1582
|
this.localStream?.getAudioTracks().forEach((track) => {
|
|
1569
1583
|
track.enabled = !muted;
|
|
1570
1584
|
});
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
}
|
|
1579
|
-
});
|
|
1580
|
-
}
|
|
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
|
+
});
|
|
1581
1592
|
}
|
|
1582
1593
|
muteVideo(muted) {
|
|
1583
1594
|
this.localStream?.getVideoTracks().forEach((track) => {
|
|
1584
1595
|
track.enabled = !muted;
|
|
1585
1596
|
});
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
}
|
|
1594
|
-
});
|
|
1595
|
-
}
|
|
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
|
+
});
|
|
1596
1604
|
}
|
|
1597
1605
|
async startRecording() {
|
|
1598
1606
|
if (!this.send({ type: "start_recording" })) {
|
|
@@ -1667,7 +1675,6 @@ var SFUClient = class {
|
|
|
1667
1675
|
}
|
|
1668
1676
|
async leave() {
|
|
1669
1677
|
this.stopHeartbeat();
|
|
1670
|
-
this.stopRoomStateSync();
|
|
1671
1678
|
this.intentionalClose = true;
|
|
1672
1679
|
this.setState("leaving");
|
|
1673
1680
|
if (this.reconnectTimer) {
|
|
@@ -2052,32 +2059,12 @@ var VideoSDKCore = class {
|
|
|
2052
2059
|
console.log(`[SFU] ${resumed ? "Resumed" : "Joined"} room`, payload);
|
|
2053
2060
|
this.state.updateLocalParticipant({
|
|
2054
2061
|
id: this.myId,
|
|
2055
|
-
name: this.participantName
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
for (const participant of roomState?.participants || []) {
|
|
2060
|
-
const pid = participant?.participant_id;
|
|
2061
|
-
if (!pid || pid === this.myId) continue;
|
|
2062
|
-
const current = this.state.getParticipant(pid);
|
|
2063
|
-
if (!current) continue;
|
|
2064
|
-
if (participant.screen_sharing) {
|
|
2065
|
-
this.state.updateParticipantMedia(pid, {
|
|
2066
|
-
isScreenSharing: true,
|
|
2067
|
-
screenStream: current.media?.screenStream ?? null
|
|
2068
|
-
});
|
|
2069
|
-
} else if (current.media?.isScreenSharing) {
|
|
2070
|
-
const screen = this.remoteScreenStreams.get(pid);
|
|
2071
|
-
screen?.getTracks().forEach((track) => track.stop());
|
|
2072
|
-
this.remoteScreenStreams.delete(pid);
|
|
2073
|
-
this.state.updateParticipantMedia(pid, {
|
|
2074
|
-
isScreenSharing: false,
|
|
2075
|
-
screenStream: null,
|
|
2076
|
-
screenTrack: void 0
|
|
2077
|
-
});
|
|
2062
|
+
name: this.participantName,
|
|
2063
|
+
media: {
|
|
2064
|
+
micEnabled: this.localStream?.getAudioTracks()[0]?.enabled ?? true,
|
|
2065
|
+
camEnabled: this.localStream?.getVideoTracks()[0]?.enabled ?? true
|
|
2078
2066
|
}
|
|
2079
|
-
}
|
|
2080
|
-
this.events.onRoomUpdate?.(roomState);
|
|
2067
|
+
});
|
|
2081
2068
|
},
|
|
2082
2069
|
onDisconnected: () => {
|
|
2083
2070
|
console.log("[SFU] Signaling WebSocket disconnected; reconnecting");
|
|
@@ -2145,22 +2132,44 @@ var VideoSDKCore = class {
|
|
|
2145
2132
|
return;
|
|
2146
2133
|
}
|
|
2147
2134
|
const pname = participant.user_metadata?.name || participant.display_name || "Participant";
|
|
2148
|
-
|
|
2135
|
+
const participantMedia = participant.media || {};
|
|
2136
|
+
const participantState = {
|
|
2149
2137
|
id: pid,
|
|
2150
2138
|
name: pname,
|
|
2151
|
-
connectionState: "connected",
|
|
2139
|
+
connectionState: participant.presence === "reconnecting" ? "reconnecting" : "connected",
|
|
2152
2140
|
media: {
|
|
2153
|
-
micEnabled:
|
|
2154
|
-
camEnabled:
|
|
2155
|
-
isScreenSharing:
|
|
2141
|
+
micEnabled: !Boolean(participant.audio_muted),
|
|
2142
|
+
camEnabled: !Boolean(participant.video_muted),
|
|
2143
|
+
isScreenSharing: Boolean(participant.screen_sharing),
|
|
2144
|
+
screenStream: participantMedia.screenStream ?? null,
|
|
2156
2145
|
stream: null
|
|
2157
2146
|
}
|
|
2158
|
-
}
|
|
2147
|
+
};
|
|
2148
|
+
if (!this.state.addParticipant(participantState)) {
|
|
2149
|
+
this.state.updateParticipantMedia(pid, participantState.media);
|
|
2150
|
+
}
|
|
2159
2151
|
this.events.onUserJoined?.({
|
|
2160
2152
|
id: pid,
|
|
2161
2153
|
name: pname
|
|
2162
2154
|
});
|
|
2163
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
|
+
},
|
|
2164
2173
|
onParticipantPresence: (participantId, presence) => {
|
|
2165
2174
|
if (participantId === this.myId) {
|
|
2166
2175
|
return;
|
|
@@ -2324,7 +2333,9 @@ var VideoSDKCore = class {
|
|
|
2324
2333
|
client.setLocalStream(this.localStream);
|
|
2325
2334
|
await client.getToken(roomId, {
|
|
2326
2335
|
displayName: name,
|
|
2327
|
-
participantId: this.myId
|
|
2336
|
+
participantId: this.myId,
|
|
2337
|
+
audioMuted: !this.localStream?.getAudioTracks()[0]?.enabled,
|
|
2338
|
+
videoMuted: !this.localStream?.getVideoTracks()[0]?.enabled
|
|
2328
2339
|
});
|
|
2329
2340
|
}
|
|
2330
2341
|
// SFU STATE
|
|
@@ -2488,6 +2499,7 @@ var VideoSDKCore = class {
|
|
|
2488
2499
|
screenTrack: this.screenStream.getVideoTracks()[0]
|
|
2489
2500
|
}
|
|
2490
2501
|
});
|
|
2502
|
+
this.state.setPresenterId(this.myId);
|
|
2491
2503
|
return this.screenStream;
|
|
2492
2504
|
} catch (err) {
|
|
2493
2505
|
this.emitError(
|
|
@@ -2509,6 +2521,9 @@ var VideoSDKCore = class {
|
|
|
2509
2521
|
this.screenStream.getTracks().forEach((track) => track.stop());
|
|
2510
2522
|
this.screenStream = null;
|
|
2511
2523
|
this.isScreenSharing = false;
|
|
2524
|
+
if (this.state.presenterId === this.myId) {
|
|
2525
|
+
this.state.setPresenterId(null);
|
|
2526
|
+
}
|
|
2512
2527
|
this.state.updateLocalParticipant({
|
|
2513
2528
|
media: {
|
|
2514
2529
|
isScreenSharing: false,
|
|
@@ -2638,7 +2653,6 @@ var MeetingProvider = ({
|
|
|
2638
2653
|
/* @__PURE__ */ new Set()
|
|
2639
2654
|
);
|
|
2640
2655
|
const meetingLeftListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
2641
|
-
const roomUpdateListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
2642
2656
|
const trackStateListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
2643
2657
|
const recordingStartedListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
2644
2658
|
const recordingStoppedListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
|
|
@@ -2663,9 +2677,6 @@ var MeetingProvider = ({
|
|
|
2663
2677
|
onMeetingLeft: () => {
|
|
2664
2678
|
meetingLeftListeners.current.forEach((fn) => fn());
|
|
2665
2679
|
},
|
|
2666
|
-
onRoomUpdate: (data) => {
|
|
2667
|
-
roomUpdateListeners.current.forEach((fn) => fn(data));
|
|
2668
|
-
},
|
|
2669
2680
|
onTrackStateChanged: (track) => {
|
|
2670
2681
|
trackStateListeners.current.forEach((fn) => fn(track));
|
|
2671
2682
|
},
|
|
@@ -2764,10 +2775,6 @@ var MeetingProvider = ({
|
|
|
2764
2775
|
meetingLeftListeners.current.delete(cb);
|
|
2765
2776
|
};
|
|
2766
2777
|
},
|
|
2767
|
-
onRoomUpdate: (cb) => {
|
|
2768
|
-
roomUpdateListeners.current.add(cb);
|
|
2769
|
-
return () => roomUpdateListeners.current.delete(cb);
|
|
2770
|
-
},
|
|
2771
2778
|
onTrackStateChanged: (cb) => {
|
|
2772
2779
|
trackStateListeners.current.add(cb);
|
|
2773
2780
|
return () => trackStateListeners.current.delete(cb);
|