@defcomm/meetingsdk 0.1.5 → 0.1.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/README.md +1 -1
- package/dist/index.d.mts +21 -11
- package/dist/index.d.ts +21 -11
- package/dist/index.js +87 -72
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +87 -72
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -83,7 +83,7 @@ type ChatInput = {
|
|
|
83
83
|
};
|
|
84
84
|
type MeetingConfig = {
|
|
85
85
|
roomId: string;
|
|
86
|
-
|
|
86
|
+
participantId: string;
|
|
87
87
|
name: string;
|
|
88
88
|
audioMuted?: boolean;
|
|
89
89
|
videoMuted?: boolean;
|
|
@@ -101,14 +101,14 @@ type SDKError = {
|
|
|
101
101
|
code: string;
|
|
102
102
|
message: string;
|
|
103
103
|
roomId?: string | null;
|
|
104
|
-
|
|
104
|
+
participantId?: string;
|
|
105
105
|
raw?: any;
|
|
106
106
|
recoverable?: boolean;
|
|
107
107
|
};
|
|
108
108
|
type EntryDecision = "approved" | "rejected";
|
|
109
109
|
type EntryRequest = {
|
|
110
110
|
requestId: string;
|
|
111
|
-
|
|
111
|
+
participantId: string;
|
|
112
112
|
name: string;
|
|
113
113
|
};
|
|
114
114
|
interface TrackDescriptor {
|
|
@@ -121,6 +121,16 @@ interface Recording {
|
|
|
121
121
|
started_at?: string;
|
|
122
122
|
recording_id?: string;
|
|
123
123
|
}
|
|
124
|
+
interface VideoSDKCoreOptions {
|
|
125
|
+
participantId: string;
|
|
126
|
+
onError?: (error: any) => void;
|
|
127
|
+
onEntryRequested?: (request: any) => void;
|
|
128
|
+
onEntryResponded?: (payload: any, decision?: any) => void;
|
|
129
|
+
onMeetingLeft?: () => void;
|
|
130
|
+
onTrackStateChanged?: (track: any) => void;
|
|
131
|
+
onRecordingStarted?: (recording: any) => void;
|
|
132
|
+
onRecordingStopped?: (recording: any) => void;
|
|
133
|
+
}
|
|
124
134
|
|
|
125
135
|
declare const useLocalParticipant: () => {
|
|
126
136
|
participant: Participant | null;
|
|
@@ -175,7 +185,7 @@ declare class VideoSDKCore {
|
|
|
175
185
|
private joinPromise;
|
|
176
186
|
private disconnectPromise;
|
|
177
187
|
private emitError;
|
|
178
|
-
constructor(events?: Events, apiBase?: string, wsBase?: string);
|
|
188
|
+
constructor(options: VideoSDKCoreOptions, events?: Events, apiBase?: string, wsBase?: string);
|
|
179
189
|
initLocal(video: HTMLVideoElement, name: string): Promise<void>;
|
|
180
190
|
private updateLocalMedia;
|
|
181
191
|
createRoom(input: {
|
|
@@ -186,7 +196,7 @@ declare class VideoSDKCore {
|
|
|
186
196
|
}): Promise<any>;
|
|
187
197
|
getRoom(roomCode: string): Promise<any>;
|
|
188
198
|
deleteRoom(roomCode: string): Promise<any>;
|
|
189
|
-
joinMeeting(config: MeetingConfig): Promise<void>;
|
|
199
|
+
joinMeeting(config: Omit<MeetingConfig, "participantId">): Promise<void>;
|
|
190
200
|
private connect;
|
|
191
201
|
private handleSFUState;
|
|
192
202
|
private handleRemoteTrack;
|
|
@@ -244,7 +254,7 @@ interface JoinPendingInfo {
|
|
|
244
254
|
interface SFUClientOptions {
|
|
245
255
|
apiBase?: string;
|
|
246
256
|
wsBase?: string;
|
|
247
|
-
|
|
257
|
+
participantId?: string;
|
|
248
258
|
onStateChange?: (state: SFUConnectionState) => void;
|
|
249
259
|
onParticipantJoined?: (participant: ParticipantInfo) => void;
|
|
250
260
|
onParticipantLeft?: (participant: string | ParticipantInfo) => void;
|
|
@@ -276,7 +286,7 @@ interface SFUClientOptions {
|
|
|
276
286
|
declare class SFUClient {
|
|
277
287
|
private apiBase;
|
|
278
288
|
private wsBase;
|
|
279
|
-
private
|
|
289
|
+
private participantId;
|
|
280
290
|
private ws;
|
|
281
291
|
private publisher;
|
|
282
292
|
private subscriber;
|
|
@@ -368,7 +378,7 @@ declare class SFUClient {
|
|
|
368
378
|
getToken(roomCode: string, options?: {
|
|
369
379
|
displayName?: string;
|
|
370
380
|
avatarUrl?: string;
|
|
371
|
-
|
|
381
|
+
participantId?: string;
|
|
372
382
|
}): Promise<void>;
|
|
373
383
|
private refreshAccessToken;
|
|
374
384
|
private connect;
|
|
@@ -419,7 +429,7 @@ type PubSubHandle = {
|
|
|
419
429
|
};
|
|
420
430
|
type MeetingContextValue = {
|
|
421
431
|
sdk: VideoSDKCore;
|
|
422
|
-
join: (config?: MeetingConfig) => Promise<void>;
|
|
432
|
+
join: (config?: Omit<MeetingConfig, "participantId">) => Promise<void>;
|
|
423
433
|
leave: () => void;
|
|
424
434
|
createRoom: (input: {
|
|
425
435
|
name: string;
|
|
@@ -474,7 +484,7 @@ declare const useMeeting: (handlers?: {
|
|
|
474
484
|
onRecordingStopped?: (recording: any) => void;
|
|
475
485
|
onActiveSpeakersChanged?: (participantIds: string[]) => void;
|
|
476
486
|
}) => {
|
|
477
|
-
join: (config?: MeetingConfig) => Promise<void>;
|
|
487
|
+
join: (config?: Omit<MeetingConfig, "participantId">) => Promise<void>;
|
|
478
488
|
leave: () => void;
|
|
479
489
|
createRoom: (input: {
|
|
480
490
|
name: string;
|
|
@@ -554,7 +564,7 @@ type LiveRoomState = {
|
|
|
554
564
|
* Preview therefore uses the authoritative REST room endpoint and polls it.
|
|
555
565
|
* Live participant/media state begins after JOIN over the SFU WebSocket.
|
|
556
566
|
*/
|
|
557
|
-
declare function useMeetingPreview(roomId: string,
|
|
567
|
+
declare function useMeetingPreview(roomId: string, participantId: string): {
|
|
558
568
|
room: LiveRoomState | null;
|
|
559
569
|
isConnected: boolean;
|
|
560
570
|
isLoading: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -83,7 +83,7 @@ type ChatInput = {
|
|
|
83
83
|
};
|
|
84
84
|
type MeetingConfig = {
|
|
85
85
|
roomId: string;
|
|
86
|
-
|
|
86
|
+
participantId: string;
|
|
87
87
|
name: string;
|
|
88
88
|
audioMuted?: boolean;
|
|
89
89
|
videoMuted?: boolean;
|
|
@@ -101,14 +101,14 @@ type SDKError = {
|
|
|
101
101
|
code: string;
|
|
102
102
|
message: string;
|
|
103
103
|
roomId?: string | null;
|
|
104
|
-
|
|
104
|
+
participantId?: string;
|
|
105
105
|
raw?: any;
|
|
106
106
|
recoverable?: boolean;
|
|
107
107
|
};
|
|
108
108
|
type EntryDecision = "approved" | "rejected";
|
|
109
109
|
type EntryRequest = {
|
|
110
110
|
requestId: string;
|
|
111
|
-
|
|
111
|
+
participantId: string;
|
|
112
112
|
name: string;
|
|
113
113
|
};
|
|
114
114
|
interface TrackDescriptor {
|
|
@@ -121,6 +121,16 @@ interface Recording {
|
|
|
121
121
|
started_at?: string;
|
|
122
122
|
recording_id?: string;
|
|
123
123
|
}
|
|
124
|
+
interface VideoSDKCoreOptions {
|
|
125
|
+
participantId: string;
|
|
126
|
+
onError?: (error: any) => void;
|
|
127
|
+
onEntryRequested?: (request: any) => void;
|
|
128
|
+
onEntryResponded?: (payload: any, decision?: any) => void;
|
|
129
|
+
onMeetingLeft?: () => void;
|
|
130
|
+
onTrackStateChanged?: (track: any) => void;
|
|
131
|
+
onRecordingStarted?: (recording: any) => void;
|
|
132
|
+
onRecordingStopped?: (recording: any) => void;
|
|
133
|
+
}
|
|
124
134
|
|
|
125
135
|
declare const useLocalParticipant: () => {
|
|
126
136
|
participant: Participant | null;
|
|
@@ -175,7 +185,7 @@ declare class VideoSDKCore {
|
|
|
175
185
|
private joinPromise;
|
|
176
186
|
private disconnectPromise;
|
|
177
187
|
private emitError;
|
|
178
|
-
constructor(events?: Events, apiBase?: string, wsBase?: string);
|
|
188
|
+
constructor(options: VideoSDKCoreOptions, events?: Events, apiBase?: string, wsBase?: string);
|
|
179
189
|
initLocal(video: HTMLVideoElement, name: string): Promise<void>;
|
|
180
190
|
private updateLocalMedia;
|
|
181
191
|
createRoom(input: {
|
|
@@ -186,7 +196,7 @@ declare class VideoSDKCore {
|
|
|
186
196
|
}): Promise<any>;
|
|
187
197
|
getRoom(roomCode: string): Promise<any>;
|
|
188
198
|
deleteRoom(roomCode: string): Promise<any>;
|
|
189
|
-
joinMeeting(config: MeetingConfig): Promise<void>;
|
|
199
|
+
joinMeeting(config: Omit<MeetingConfig, "participantId">): Promise<void>;
|
|
190
200
|
private connect;
|
|
191
201
|
private handleSFUState;
|
|
192
202
|
private handleRemoteTrack;
|
|
@@ -244,7 +254,7 @@ interface JoinPendingInfo {
|
|
|
244
254
|
interface SFUClientOptions {
|
|
245
255
|
apiBase?: string;
|
|
246
256
|
wsBase?: string;
|
|
247
|
-
|
|
257
|
+
participantId?: string;
|
|
248
258
|
onStateChange?: (state: SFUConnectionState) => void;
|
|
249
259
|
onParticipantJoined?: (participant: ParticipantInfo) => void;
|
|
250
260
|
onParticipantLeft?: (participant: string | ParticipantInfo) => void;
|
|
@@ -276,7 +286,7 @@ interface SFUClientOptions {
|
|
|
276
286
|
declare class SFUClient {
|
|
277
287
|
private apiBase;
|
|
278
288
|
private wsBase;
|
|
279
|
-
private
|
|
289
|
+
private participantId;
|
|
280
290
|
private ws;
|
|
281
291
|
private publisher;
|
|
282
292
|
private subscriber;
|
|
@@ -368,7 +378,7 @@ declare class SFUClient {
|
|
|
368
378
|
getToken(roomCode: string, options?: {
|
|
369
379
|
displayName?: string;
|
|
370
380
|
avatarUrl?: string;
|
|
371
|
-
|
|
381
|
+
participantId?: string;
|
|
372
382
|
}): Promise<void>;
|
|
373
383
|
private refreshAccessToken;
|
|
374
384
|
private connect;
|
|
@@ -419,7 +429,7 @@ type PubSubHandle = {
|
|
|
419
429
|
};
|
|
420
430
|
type MeetingContextValue = {
|
|
421
431
|
sdk: VideoSDKCore;
|
|
422
|
-
join: (config?: MeetingConfig) => Promise<void>;
|
|
432
|
+
join: (config?: Omit<MeetingConfig, "participantId">) => Promise<void>;
|
|
423
433
|
leave: () => void;
|
|
424
434
|
createRoom: (input: {
|
|
425
435
|
name: string;
|
|
@@ -474,7 +484,7 @@ declare const useMeeting: (handlers?: {
|
|
|
474
484
|
onRecordingStopped?: (recording: any) => void;
|
|
475
485
|
onActiveSpeakersChanged?: (participantIds: string[]) => void;
|
|
476
486
|
}) => {
|
|
477
|
-
join: (config?: MeetingConfig) => Promise<void>;
|
|
487
|
+
join: (config?: Omit<MeetingConfig, "participantId">) => Promise<void>;
|
|
478
488
|
leave: () => void;
|
|
479
489
|
createRoom: (input: {
|
|
480
490
|
name: string;
|
|
@@ -554,7 +564,7 @@ type LiveRoomState = {
|
|
|
554
564
|
* Preview therefore uses the authoritative REST room endpoint and polls it.
|
|
555
565
|
* Live participant/media state begins after JOIN over the SFU WebSocket.
|
|
556
566
|
*/
|
|
557
|
-
declare function useMeetingPreview(roomId: string,
|
|
567
|
+
declare function useMeetingPreview(roomId: string, participantId: string): {
|
|
558
568
|
room: LiveRoomState | null;
|
|
559
569
|
isConnected: boolean;
|
|
560
570
|
isLoading: boolean;
|
package/dist/index.js
CHANGED
|
@@ -428,7 +428,7 @@ var SFUClient = class {
|
|
|
428
428
|
this.subscriberStatsTimer = null;
|
|
429
429
|
this.apiBase = options.apiBase || "https://api.example.com/api";
|
|
430
430
|
this.wsBase = options.wsBase || "wss://api.example.com/ws";
|
|
431
|
-
this.
|
|
431
|
+
this.participantId = options.participantId || this.createId();
|
|
432
432
|
this.onStateChange = options.onStateChange || (() => {
|
|
433
433
|
});
|
|
434
434
|
this.onParticipantJoined = options.onParticipantJoined || (() => {
|
|
@@ -549,12 +549,17 @@ var SFUClient = class {
|
|
|
549
549
|
});
|
|
550
550
|
}
|
|
551
551
|
async getRoom(roomCode) {
|
|
552
|
-
return this.request(
|
|
552
|
+
return this.request(
|
|
553
|
+
`${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`
|
|
554
|
+
);
|
|
553
555
|
}
|
|
554
556
|
async deleteRoom(roomCode) {
|
|
555
|
-
return this.request(
|
|
556
|
-
|
|
557
|
-
|
|
557
|
+
return this.request(
|
|
558
|
+
`${this.apiBase}/rooms/${encodeURIComponent(roomCode)}`,
|
|
559
|
+
{
|
|
560
|
+
method: "DELETE"
|
|
561
|
+
}
|
|
562
|
+
);
|
|
558
563
|
}
|
|
559
564
|
async getToken(roomCode, options = {}) {
|
|
560
565
|
const nextRoom = roomCode.trim();
|
|
@@ -566,7 +571,7 @@ var SFUClient = class {
|
|
|
566
571
|
displayName: options.displayName,
|
|
567
572
|
avatarUrl: options.avatarUrl
|
|
568
573
|
};
|
|
569
|
-
if (options.
|
|
574
|
+
if (options.participantId) this.participantId = options.participantId;
|
|
570
575
|
if (!this.resumeToken) {
|
|
571
576
|
this.resumeToken = this.loadResumeToken(this.room);
|
|
572
577
|
}
|
|
@@ -574,7 +579,7 @@ var SFUClient = class {
|
|
|
574
579
|
method: "POST",
|
|
575
580
|
body: JSON.stringify({
|
|
576
581
|
room_code: this.room,
|
|
577
|
-
user_id: this.
|
|
582
|
+
user_id: this.participantId,
|
|
578
583
|
display_name: options.displayName,
|
|
579
584
|
avatar_url: options.avatarUrl
|
|
580
585
|
})
|
|
@@ -589,7 +594,7 @@ var SFUClient = class {
|
|
|
589
594
|
method: "POST",
|
|
590
595
|
body: JSON.stringify({
|
|
591
596
|
room_code: this.room,
|
|
592
|
-
user_id: this.
|
|
597
|
+
user_id: this.participantId,
|
|
593
598
|
display_name: this.joinOptions.displayName,
|
|
594
599
|
avatar_url: this.joinOptions.avatarUrl
|
|
595
600
|
})
|
|
@@ -792,7 +797,8 @@ var SFUClient = class {
|
|
|
792
797
|
case "participant_joined": {
|
|
793
798
|
const participant = payload.participant || payload;
|
|
794
799
|
const participantId = participant?.participant_id || payload.participant_id;
|
|
795
|
-
if (!participantId || participantId === this.currentParticipantId)
|
|
800
|
+
if (!participantId || participantId === this.currentParticipantId)
|
|
801
|
+
break;
|
|
796
802
|
if (participant) this.participants.set(participantId, participant);
|
|
797
803
|
this.onParticipantJoined(participant);
|
|
798
804
|
break;
|
|
@@ -822,14 +828,21 @@ var SFUClient = class {
|
|
|
822
828
|
if (track.source === "audio") {
|
|
823
829
|
this.localTrackIds.set("audio", track.track_id);
|
|
824
830
|
const muted = !(this.localStream?.getAudioTracks()[0]?.enabled ?? true);
|
|
825
|
-
this.send({
|
|
831
|
+
this.send({
|
|
832
|
+
type: "track_state",
|
|
833
|
+
payload: { track_id: track.track_id, muted }
|
|
834
|
+
});
|
|
826
835
|
}
|
|
827
836
|
if (track.source === "camera") {
|
|
828
837
|
this.localTrackIds.set("camera", track.track_id);
|
|
829
838
|
const muted = !(this.localStream?.getVideoTracks()[0]?.enabled ?? true);
|
|
830
|
-
this.send({
|
|
839
|
+
this.send({
|
|
840
|
+
type: "track_state",
|
|
841
|
+
payload: { track_id: track.track_id, muted }
|
|
842
|
+
});
|
|
831
843
|
}
|
|
832
|
-
if (track.source === "screen")
|
|
844
|
+
if (track.source === "screen")
|
|
845
|
+
this.localTrackIds.set("screen", track.track_id);
|
|
833
846
|
break;
|
|
834
847
|
}
|
|
835
848
|
this.onTrackPublished(track);
|
|
@@ -1060,10 +1073,7 @@ var SFUClient = class {
|
|
|
1060
1073
|
}
|
|
1061
1074
|
if (screenStream?.getTracks().length === 0) {
|
|
1062
1075
|
this.remoteScreenStreams.delete(participantId);
|
|
1063
|
-
this.onScreenShareStopped(
|
|
1064
|
-
participantId,
|
|
1065
|
-
metadata.track_id
|
|
1066
|
-
);
|
|
1076
|
+
this.onScreenShareStopped(participantId, metadata.track_id);
|
|
1067
1077
|
}
|
|
1068
1078
|
};
|
|
1069
1079
|
this.onScreenShareStarted(participantId, metadata);
|
|
@@ -1150,7 +1160,9 @@ var SFUClient = class {
|
|
|
1150
1160
|
try {
|
|
1151
1161
|
await pc.addIceCandidate(candidate);
|
|
1152
1162
|
} catch (error) {
|
|
1153
|
-
this.onError(
|
|
1163
|
+
this.onError(
|
|
1164
|
+
new Error(`Failed to add ${peer} ICE candidate: ${String(error)}`)
|
|
1165
|
+
);
|
|
1154
1166
|
}
|
|
1155
1167
|
}
|
|
1156
1168
|
async flushPendingIce(peer) {
|
|
@@ -1162,7 +1174,11 @@ var SFUClient = class {
|
|
|
1162
1174
|
try {
|
|
1163
1175
|
await pc.addIceCandidate(candidate);
|
|
1164
1176
|
} catch (error) {
|
|
1165
|
-
this.onError(
|
|
1177
|
+
this.onError(
|
|
1178
|
+
new Error(
|
|
1179
|
+
`Failed to add queued ${peer} ICE candidate: ${String(error)}`
|
|
1180
|
+
)
|
|
1181
|
+
);
|
|
1166
1182
|
}
|
|
1167
1183
|
}
|
|
1168
1184
|
}
|
|
@@ -1192,7 +1208,9 @@ var SFUClient = class {
|
|
|
1192
1208
|
} catch (error) {
|
|
1193
1209
|
const waiters = this.subscriptionWaiters.splice(0);
|
|
1194
1210
|
waiters.forEach((w) => w.reject(error));
|
|
1195
|
-
this.onError(
|
|
1211
|
+
this.onError(
|
|
1212
|
+
new Error(`Failed to process subscriber offer: ${String(error)}`)
|
|
1213
|
+
);
|
|
1196
1214
|
} finally {
|
|
1197
1215
|
this.subscriberNegotiating = false;
|
|
1198
1216
|
}
|
|
@@ -1240,9 +1258,13 @@ var SFUClient = class {
|
|
|
1240
1258
|
}
|
|
1241
1259
|
}
|
|
1242
1260
|
async publish({ audio = true, video = true } = {}) {
|
|
1243
|
-
if (!this.publisher)
|
|
1261
|
+
if (!this.publisher)
|
|
1262
|
+
throw new Error("Publisher PeerConnection is not initialized");
|
|
1244
1263
|
if (!this.localStream) {
|
|
1245
|
-
this.localStream = await navigator.mediaDevices.getUserMedia({
|
|
1264
|
+
this.localStream = await navigator.mediaDevices.getUserMedia({
|
|
1265
|
+
audio,
|
|
1266
|
+
video
|
|
1267
|
+
});
|
|
1246
1268
|
}
|
|
1247
1269
|
await this.publishExistingTracks(audio, video);
|
|
1248
1270
|
return this.localStream;
|
|
@@ -1255,9 +1277,13 @@ var SFUClient = class {
|
|
|
1255
1277
|
const audioTrack = this.localStream.getAudioTracks().find((track) => track.readyState === "live");
|
|
1256
1278
|
const cameraTrack = this.localStream.getVideoTracks().find((track) => track.readyState === "live");
|
|
1257
1279
|
const screenTrack = this.screenStream?.getVideoTracks().find((track) => track.readyState === "live");
|
|
1258
|
-
await this.audioSender?.replaceTrack(
|
|
1280
|
+
await this.audioSender?.replaceTrack(
|
|
1281
|
+
audio && audioTrack ? audioTrack : null
|
|
1282
|
+
);
|
|
1259
1283
|
this.audioTransceiver.direction = audio && audioTrack ? "sendonly" : "inactive";
|
|
1260
|
-
await this.videoSender?.replaceTrack(
|
|
1284
|
+
await this.videoSender?.replaceTrack(
|
|
1285
|
+
video && cameraTrack ? cameraTrack : null
|
|
1286
|
+
);
|
|
1261
1287
|
this.cameraTransceiver.direction = video && cameraTrack ? "sendonly" : "inactive";
|
|
1262
1288
|
await this.screenSender?.replaceTrack(screenTrack || null);
|
|
1263
1289
|
this.screenTransceiver.direction = screenTrack ? "sendonly" : "inactive";
|
|
@@ -1430,7 +1456,10 @@ var SFUClient = class {
|
|
|
1430
1456
|
}
|
|
1431
1457
|
async rejectJoinRequest(requestId, reason) {
|
|
1432
1458
|
if (!requestId) throw new Error("requestId is required");
|
|
1433
|
-
if (!this.send({
|
|
1459
|
+
if (!this.send({
|
|
1460
|
+
type: "reject_join",
|
|
1461
|
+
payload: { request_id: requestId, reason }
|
|
1462
|
+
})) {
|
|
1434
1463
|
throw new Error("SFU signaling is not connected");
|
|
1435
1464
|
}
|
|
1436
1465
|
}
|
|
@@ -1499,10 +1528,14 @@ var SFUClient = class {
|
|
|
1499
1528
|
}
|
|
1500
1529
|
setTimeout(check, 25);
|
|
1501
1530
|
};
|
|
1502
|
-
ws.addEventListener(
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1531
|
+
ws.addEventListener(
|
|
1532
|
+
"close",
|
|
1533
|
+
() => {
|
|
1534
|
+
clearTimeout(timeout);
|
|
1535
|
+
finish();
|
|
1536
|
+
},
|
|
1537
|
+
{ once: true }
|
|
1538
|
+
);
|
|
1506
1539
|
this.send({ type: "leave" });
|
|
1507
1540
|
check();
|
|
1508
1541
|
});
|
|
@@ -1581,7 +1614,8 @@ var SFUClient = class {
|
|
|
1581
1614
|
}
|
|
1582
1615
|
}
|
|
1583
1616
|
async logSubscriberVideoStats() {
|
|
1584
|
-
if (!this.subscriber || this.subscriber.connectionState === "closed")
|
|
1617
|
+
if (!this.subscriber || this.subscriber.connectionState === "closed")
|
|
1618
|
+
return;
|
|
1585
1619
|
try {
|
|
1586
1620
|
const stats = await this.subscriber.getStats();
|
|
1587
1621
|
stats.forEach((report) => {
|
|
@@ -1602,7 +1636,7 @@ var SFUClient = class {
|
|
|
1602
1636
|
|
|
1603
1637
|
// src/core/VideoCore.ts
|
|
1604
1638
|
var VideoSDKCore = class {
|
|
1605
|
-
constructor(events = {}, apiBase = SDK_CONFIG.apiBase, wsBase = SDK_CONFIG.wsBase) {
|
|
1639
|
+
constructor(options, events = {}, apiBase = SDK_CONFIG.apiBase, wsBase = SDK_CONFIG.wsBase) {
|
|
1606
1640
|
this.events = events;
|
|
1607
1641
|
this.apiBase = apiBase;
|
|
1608
1642
|
this.wsBase = wsBase;
|
|
@@ -1628,18 +1662,7 @@ var VideoSDKCore = class {
|
|
|
1628
1662
|
this.events.onActiveSpeakersChanged?.(participantIds);
|
|
1629
1663
|
}
|
|
1630
1664
|
});
|
|
1631
|
-
|
|
1632
|
-
try {
|
|
1633
|
-
storedId = typeof localStorage !== "undefined" ? localStorage.getItem("defcomm:participant_id") : null;
|
|
1634
|
-
} catch {
|
|
1635
|
-
}
|
|
1636
|
-
this.myId = storedId || (typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : `user_${Date.now()}`);
|
|
1637
|
-
try {
|
|
1638
|
-
if (typeof localStorage !== "undefined") {
|
|
1639
|
-
localStorage.setItem("defcomm:participant_id", this.myId);
|
|
1640
|
-
}
|
|
1641
|
-
} catch {
|
|
1642
|
-
}
|
|
1665
|
+
this.myId = options.participantId;
|
|
1643
1666
|
}
|
|
1644
1667
|
emitError(code, message, raw, recoverable = true) {
|
|
1645
1668
|
const err = {
|
|
@@ -1647,7 +1670,7 @@ var VideoSDKCore = class {
|
|
|
1647
1670
|
message,
|
|
1648
1671
|
raw,
|
|
1649
1672
|
roomId: this.room.id,
|
|
1650
|
-
|
|
1673
|
+
participantId: this.myId,
|
|
1651
1674
|
recoverable
|
|
1652
1675
|
};
|
|
1653
1676
|
this.events.onError?.(err);
|
|
@@ -1707,7 +1730,7 @@ var VideoSDKCore = class {
|
|
|
1707
1730
|
const client = this.sfuClient ?? new SFUClient({
|
|
1708
1731
|
apiBase: this.apiBase,
|
|
1709
1732
|
wsBase: this.wsBase,
|
|
1710
|
-
|
|
1733
|
+
participantId: this.myId
|
|
1711
1734
|
});
|
|
1712
1735
|
return client.createRoom(input);
|
|
1713
1736
|
}
|
|
@@ -1715,7 +1738,7 @@ var VideoSDKCore = class {
|
|
|
1715
1738
|
const client = this.sfuClient ?? new SFUClient({
|
|
1716
1739
|
apiBase: this.apiBase,
|
|
1717
1740
|
wsBase: this.wsBase,
|
|
1718
|
-
|
|
1741
|
+
participantId: this.myId
|
|
1719
1742
|
});
|
|
1720
1743
|
return client.getRoom(roomCode);
|
|
1721
1744
|
}
|
|
@@ -1723,29 +1746,23 @@ var VideoSDKCore = class {
|
|
|
1723
1746
|
const client = this.sfuClient ?? new SFUClient({
|
|
1724
1747
|
apiBase: this.apiBase,
|
|
1725
1748
|
wsBase: this.wsBase,
|
|
1726
|
-
|
|
1749
|
+
participantId: this.myId
|
|
1727
1750
|
});
|
|
1728
1751
|
return client.deleteRoom(roomCode);
|
|
1729
1752
|
}
|
|
1730
1753
|
// JOIN
|
|
1731
1754
|
async joinMeeting(config) {
|
|
1732
|
-
const {
|
|
1733
|
-
roomId,
|
|
1734
|
-
name,
|
|
1735
|
-
audioMuted = false,
|
|
1736
|
-
videoMuted = false,
|
|
1737
|
-
userId
|
|
1738
|
-
} = config;
|
|
1755
|
+
const { roomId, name, audioMuted = false, videoMuted = false } = config;
|
|
1739
1756
|
if (!roomId || !name) {
|
|
1740
1757
|
throw new Error("roomId and name are required to join meeting");
|
|
1741
1758
|
}
|
|
1742
|
-
if (
|
|
1743
|
-
|
|
1759
|
+
if (!this.myId) {
|
|
1760
|
+
throw new Error("participantId is required");
|
|
1744
1761
|
}
|
|
1745
1762
|
if (this.sfuClient && this.room.id === roomId && this.sfuClient.getConnectionState() === "connected") {
|
|
1746
1763
|
console.info("[SDK] Already connected; duplicate join ignored", {
|
|
1747
1764
|
roomId,
|
|
1748
|
-
|
|
1765
|
+
participantId: this.myId
|
|
1749
1766
|
});
|
|
1750
1767
|
return;
|
|
1751
1768
|
}
|
|
@@ -1754,7 +1771,7 @@ var VideoSDKCore = class {
|
|
|
1754
1771
|
"[SDK] Join already in progress; waiting for existing join",
|
|
1755
1772
|
{
|
|
1756
1773
|
roomId,
|
|
1757
|
-
|
|
1774
|
+
participantId: this.myId
|
|
1758
1775
|
}
|
|
1759
1776
|
);
|
|
1760
1777
|
return this.joinPromise;
|
|
@@ -1816,7 +1833,7 @@ var VideoSDKCore = class {
|
|
|
1816
1833
|
const client = new SFUClient({
|
|
1817
1834
|
apiBase: this.apiBase,
|
|
1818
1835
|
wsBase: this.wsBase,
|
|
1819
|
-
|
|
1836
|
+
participantId: this.myId,
|
|
1820
1837
|
autoSubscribe: true,
|
|
1821
1838
|
// CONNECTION STATE
|
|
1822
1839
|
onStateChange: (state) => {
|
|
@@ -1840,7 +1857,7 @@ var VideoSDKCore = class {
|
|
|
1840
1857
|
console.log("[SFU] Join request pending", info);
|
|
1841
1858
|
this.events.onEntryRequested?.({
|
|
1842
1859
|
requestId: info.request_id,
|
|
1843
|
-
|
|
1860
|
+
participantId: this.myId,
|
|
1844
1861
|
name: this.participantName
|
|
1845
1862
|
});
|
|
1846
1863
|
},
|
|
@@ -1877,14 +1894,14 @@ var VideoSDKCore = class {
|
|
|
1877
1894
|
},
|
|
1878
1895
|
onJoinRequested: (request) => {
|
|
1879
1896
|
const requestId = request?.request_id || request?.requestId;
|
|
1880
|
-
const
|
|
1897
|
+
const participantId = request?.user_id || request?.participantId;
|
|
1881
1898
|
const nameValue = request?.user_metadata?.name || request?.display_name || request?.name || "Participant";
|
|
1882
|
-
if (!requestId || !
|
|
1899
|
+
if (!requestId || !participantId) {
|
|
1883
1900
|
return;
|
|
1884
1901
|
}
|
|
1885
1902
|
this.events.onEntryRequested?.({
|
|
1886
1903
|
requestId,
|
|
1887
|
-
|
|
1904
|
+
participantId,
|
|
1888
1905
|
name: nameValue
|
|
1889
1906
|
});
|
|
1890
1907
|
},
|
|
@@ -2058,6 +2075,10 @@ var VideoSDKCore = class {
|
|
|
2058
2075
|
// ERROR
|
|
2059
2076
|
onError: (error) => {
|
|
2060
2077
|
console.error("[SFU] Error:", error);
|
|
2078
|
+
if (error?.code === "request_failed" || error?.code === "authorization") {
|
|
2079
|
+
this.emitError("PERMISSION_DENIED", error.message, error, false);
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2061
2082
|
this.emitError(
|
|
2062
2083
|
"SFU_ERROR",
|
|
2063
2084
|
error?.message || String(error),
|
|
@@ -2070,7 +2091,7 @@ var VideoSDKCore = class {
|
|
|
2070
2091
|
client.setLocalStream(this.localStream);
|
|
2071
2092
|
await client.getToken(roomId, {
|
|
2072
2093
|
displayName: name,
|
|
2073
|
-
|
|
2094
|
+
participantId: this.myId
|
|
2074
2095
|
});
|
|
2075
2096
|
}
|
|
2076
2097
|
// SFU STATE
|
|
@@ -2392,6 +2413,7 @@ var MeetingProvider = ({
|
|
|
2392
2413
|
);
|
|
2393
2414
|
if (!sdkRef.current) {
|
|
2394
2415
|
sdkRef.current = new VideoSDKCore({
|
|
2416
|
+
participantId: config.participantId,
|
|
2395
2417
|
onError: (err) => errorListeners.current.forEach((fn) => fn(err)),
|
|
2396
2418
|
onEntryRequested: (req) => entryRequestListeners.current.forEach((fn) => fn(req)),
|
|
2397
2419
|
onEntryResponded: (p, d) => entryResponseListeners.current.forEach((fn) => fn(p, d)),
|
|
@@ -2428,13 +2450,6 @@ var MeetingProvider = ({
|
|
|
2428
2450
|
(s) => s.getChatMessages()
|
|
2429
2451
|
);
|
|
2430
2452
|
const value = (0, import_react2.useMemo)(() => {
|
|
2431
|
-
if (!sdkRef.current) {
|
|
2432
|
-
sdkRef.current = new VideoSDKCore({
|
|
2433
|
-
onError: (err) => {
|
|
2434
|
-
errorListeners.current.forEach((fn) => fn(err));
|
|
2435
|
-
}
|
|
2436
|
-
});
|
|
2437
|
-
}
|
|
2438
2453
|
return {
|
|
2439
2454
|
sdk,
|
|
2440
2455
|
join: (joinConfig) => sdk.joinMeeting({
|
|
@@ -2666,7 +2681,7 @@ var useRemoteMedia = (participantId) => {
|
|
|
2666
2681
|
|
|
2667
2682
|
// src/react/useMeetingPreview.ts
|
|
2668
2683
|
var import_react7 = require("react");
|
|
2669
|
-
function useMeetingPreview(roomId,
|
|
2684
|
+
function useMeetingPreview(roomId, participantId) {
|
|
2670
2685
|
const [room, setRoom] = (0, import_react7.useState)(null);
|
|
2671
2686
|
const [error, setError] = (0, import_react7.useState)(null);
|
|
2672
2687
|
const [isConnected, setIsConnected] = (0, import_react7.useState)(false);
|
|
@@ -2725,7 +2740,7 @@ function useMeetingPreview(roomId, userId) {
|
|
|
2725
2740
|
stopped = true;
|
|
2726
2741
|
if (timer) clearTimeout(timer);
|
|
2727
2742
|
};
|
|
2728
|
-
}, [roomId,
|
|
2743
|
+
}, [roomId, participantId]);
|
|
2729
2744
|
return {
|
|
2730
2745
|
room,
|
|
2731
2746
|
isConnected,
|