@defcomm/meetingsdk 0.6.8 → 0.6.9
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 +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +144 -59
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +144 -59
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -339,6 +339,12 @@ declare class VideoSDKCore {
|
|
|
339
339
|
getMeetingSummary(roomCode: string, sessionId: string): Promise<{
|
|
340
340
|
summary: MeetingSummary | null;
|
|
341
341
|
}>;
|
|
342
|
+
private acquireOptionalLocalMedia;
|
|
343
|
+
/**
|
|
344
|
+
* Wakes the active-speaker Web Audio pipeline. Call this from a user gesture
|
|
345
|
+
* whenever possible (Join, first click inside the meeting, etc.).
|
|
346
|
+
*/
|
|
347
|
+
resumeActiveSpeaker(): Promise<boolean>;
|
|
342
348
|
joinMeeting(config: Omit<MeetingConfig, "participantId">): Promise<void>;
|
|
343
349
|
private connect;
|
|
344
350
|
private createSFUClient;
|
|
@@ -427,6 +433,7 @@ type MeetingContextValue = {
|
|
|
427
433
|
}>;
|
|
428
434
|
toggleMic: () => void;
|
|
429
435
|
toggleCam: () => void;
|
|
436
|
+
resumeActiveSpeaker: () => Promise<boolean>;
|
|
430
437
|
startScreenShare: () => Promise<MediaStream | null>;
|
|
431
438
|
stopScreenShare: () => void;
|
|
432
439
|
sendMessage: (input: ChatInput) => void;
|
|
@@ -524,6 +531,7 @@ declare const useMeeting: (handlers?: {
|
|
|
524
531
|
}>;
|
|
525
532
|
toggleMic: () => void;
|
|
526
533
|
toggleCam: () => void;
|
|
534
|
+
resumeActiveSpeaker: () => Promise<boolean>;
|
|
527
535
|
startScreenShare: () => Promise<MediaStream | null>;
|
|
528
536
|
stopScreenShare: () => void;
|
|
529
537
|
sendMessage: (input: ChatInput) => void;
|
|
@@ -630,6 +638,15 @@ interface ActiveSpeakerDetectorOptions {
|
|
|
630
638
|
releaseMs?: number;
|
|
631
639
|
onActiveSpeakersChanged?: (participantIds: string[]) => void;
|
|
632
640
|
}
|
|
641
|
+
/**
|
|
642
|
+
* Detects currently speaking participants from the actual audio tracks that
|
|
643
|
+
* are being received/published by WebRTC.
|
|
644
|
+
*
|
|
645
|
+
* The AudioContext is explicitly resumable so an application can wake it from
|
|
646
|
+
* a real user gesture (for example, the Join button). This matters in browsers
|
|
647
|
+
* that create Web Audio contexts in the "suspended" state until the page has
|
|
648
|
+
* received user interaction.
|
|
649
|
+
*/
|
|
633
650
|
declare class ActiveSpeakerDetector {
|
|
634
651
|
private audioContext;
|
|
635
652
|
private speakers;
|
|
@@ -642,7 +659,12 @@ declare class ActiveSpeakerDetector {
|
|
|
642
659
|
private lastEmitted;
|
|
643
660
|
constructor(options?: ActiveSpeakerDetectorOptions);
|
|
644
661
|
private ensureAudioContext;
|
|
645
|
-
|
|
662
|
+
/**
|
|
663
|
+
* Create/wake the Web Audio context. Call this from a user gesture when
|
|
664
|
+
* possible. Returns true when the context is running after the call.
|
|
665
|
+
*/
|
|
666
|
+
resume(): Promise<boolean>;
|
|
667
|
+
getAudioContextState(): AudioContextState | "unavailable";
|
|
646
668
|
addTrack(participantId: string, track: MediaStreamTrack): void;
|
|
647
669
|
removeParticipant(participantId: string): void;
|
|
648
670
|
removeTrack(track: MediaStreamTrack): void;
|
|
@@ -650,6 +672,7 @@ declare class ActiveSpeakerDetector {
|
|
|
650
672
|
start(): void;
|
|
651
673
|
stop(): void;
|
|
652
674
|
private sample;
|
|
675
|
+
private getActiveSpeakers;
|
|
653
676
|
private getActiveSpeakerIds;
|
|
654
677
|
private emitIfChanged;
|
|
655
678
|
destroy(): Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -339,6 +339,12 @@ declare class VideoSDKCore {
|
|
|
339
339
|
getMeetingSummary(roomCode: string, sessionId: string): Promise<{
|
|
340
340
|
summary: MeetingSummary | null;
|
|
341
341
|
}>;
|
|
342
|
+
private acquireOptionalLocalMedia;
|
|
343
|
+
/**
|
|
344
|
+
* Wakes the active-speaker Web Audio pipeline. Call this from a user gesture
|
|
345
|
+
* whenever possible (Join, first click inside the meeting, etc.).
|
|
346
|
+
*/
|
|
347
|
+
resumeActiveSpeaker(): Promise<boolean>;
|
|
342
348
|
joinMeeting(config: Omit<MeetingConfig, "participantId">): Promise<void>;
|
|
343
349
|
private connect;
|
|
344
350
|
private createSFUClient;
|
|
@@ -427,6 +433,7 @@ type MeetingContextValue = {
|
|
|
427
433
|
}>;
|
|
428
434
|
toggleMic: () => void;
|
|
429
435
|
toggleCam: () => void;
|
|
436
|
+
resumeActiveSpeaker: () => Promise<boolean>;
|
|
430
437
|
startScreenShare: () => Promise<MediaStream | null>;
|
|
431
438
|
stopScreenShare: () => void;
|
|
432
439
|
sendMessage: (input: ChatInput) => void;
|
|
@@ -524,6 +531,7 @@ declare const useMeeting: (handlers?: {
|
|
|
524
531
|
}>;
|
|
525
532
|
toggleMic: () => void;
|
|
526
533
|
toggleCam: () => void;
|
|
534
|
+
resumeActiveSpeaker: () => Promise<boolean>;
|
|
527
535
|
startScreenShare: () => Promise<MediaStream | null>;
|
|
528
536
|
stopScreenShare: () => void;
|
|
529
537
|
sendMessage: (input: ChatInput) => void;
|
|
@@ -630,6 +638,15 @@ interface ActiveSpeakerDetectorOptions {
|
|
|
630
638
|
releaseMs?: number;
|
|
631
639
|
onActiveSpeakersChanged?: (participantIds: string[]) => void;
|
|
632
640
|
}
|
|
641
|
+
/**
|
|
642
|
+
* Detects currently speaking participants from the actual audio tracks that
|
|
643
|
+
* are being received/published by WebRTC.
|
|
644
|
+
*
|
|
645
|
+
* The AudioContext is explicitly resumable so an application can wake it from
|
|
646
|
+
* a real user gesture (for example, the Join button). This matters in browsers
|
|
647
|
+
* that create Web Audio contexts in the "suspended" state until the page has
|
|
648
|
+
* received user interaction.
|
|
649
|
+
*/
|
|
633
650
|
declare class ActiveSpeakerDetector {
|
|
634
651
|
private audioContext;
|
|
635
652
|
private speakers;
|
|
@@ -642,7 +659,12 @@ declare class ActiveSpeakerDetector {
|
|
|
642
659
|
private lastEmitted;
|
|
643
660
|
constructor(options?: ActiveSpeakerDetectorOptions);
|
|
644
661
|
private ensureAudioContext;
|
|
645
|
-
|
|
662
|
+
/**
|
|
663
|
+
* Create/wake the Web Audio context. Call this from a user gesture when
|
|
664
|
+
* possible. Returns true when the context is running after the call.
|
|
665
|
+
*/
|
|
666
|
+
resume(): Promise<boolean>;
|
|
667
|
+
getAudioContextState(): AudioContextState | "unavailable";
|
|
646
668
|
addTrack(participantId: string, track: MediaStreamTrack): void;
|
|
647
669
|
removeParticipant(participantId: string): void;
|
|
648
670
|
removeTrack(track: MediaStreamTrack): void;
|
|
@@ -650,6 +672,7 @@ declare class ActiveSpeakerDetector {
|
|
|
650
672
|
start(): void;
|
|
651
673
|
stop(): void;
|
|
652
674
|
private sample;
|
|
675
|
+
private getActiveSpeakers;
|
|
653
676
|
private getActiveSpeakerIds;
|
|
654
677
|
private emitIfChanged;
|
|
655
678
|
destroy(): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -63,13 +63,16 @@ var ActiveSpeakerDetector = class {
|
|
|
63
63
|
this.timer = null;
|
|
64
64
|
this.lastEmitted = "";
|
|
65
65
|
this.intervalMs = options.intervalMs ?? 100;
|
|
66
|
-
this.threshold = options.threshold ?? 0.
|
|
67
|
-
this.releaseThreshold = options.releaseThreshold ?? 0.
|
|
68
|
-
this.releaseMs = options.releaseMs ??
|
|
66
|
+
this.threshold = options.threshold ?? 0.02;
|
|
67
|
+
this.releaseThreshold = options.releaseThreshold ?? 0.01;
|
|
68
|
+
this.releaseMs = options.releaseMs ?? 650;
|
|
69
69
|
this.onActiveSpeakersChanged = options.onActiveSpeakersChanged ?? (() => {
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
72
|
ensureAudioContext() {
|
|
73
|
+
if (typeof window === "undefined") {
|
|
74
|
+
throw new Error("AudioContext is only available in the browser");
|
|
75
|
+
}
|
|
73
76
|
if (!this.audioContext) {
|
|
74
77
|
const AudioContextClass = window.AudioContext || window.webkitAudioContext;
|
|
75
78
|
if (!AudioContextClass) {
|
|
@@ -79,28 +82,52 @@ var ActiveSpeakerDetector = class {
|
|
|
79
82
|
}
|
|
80
83
|
return this.audioContext;
|
|
81
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Create/wake the Web Audio context. Call this from a user gesture when
|
|
87
|
+
* possible. Returns true when the context is running after the call.
|
|
88
|
+
*/
|
|
82
89
|
async resume() {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
try {
|
|
91
|
+
const context = this.ensureAudioContext();
|
|
92
|
+
if (context.state === "suspended") {
|
|
93
|
+
try {
|
|
94
|
+
await context.resume();
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.warn("[ActiveSpeaker] AudioContext resume failed", error);
|
|
97
|
+
}
|
|
88
98
|
}
|
|
99
|
+
return context.state === "running";
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.warn("[ActiveSpeaker] AudioContext unavailable", error);
|
|
102
|
+
return false;
|
|
89
103
|
}
|
|
90
104
|
}
|
|
105
|
+
getAudioContextState() {
|
|
106
|
+
if (!this.audioContext) return "unavailable";
|
|
107
|
+
return this.audioContext.state;
|
|
108
|
+
}
|
|
91
109
|
addTrack(participantId, track) {
|
|
92
|
-
if (!participantId) return;
|
|
93
|
-
if (track.kind !== "audio") return;
|
|
110
|
+
if (!participantId || track.kind !== "audio") return;
|
|
94
111
|
this.removeParticipant(participantId);
|
|
95
|
-
|
|
112
|
+
let context;
|
|
113
|
+
try {
|
|
114
|
+
context = this.ensureAudioContext();
|
|
115
|
+
} catch (error) {
|
|
116
|
+
console.warn("[ActiveSpeaker] Could not create AudioContext", error);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
96
119
|
const stream = new MediaStream([track]);
|
|
97
120
|
const source = context.createMediaStreamSource(stream);
|
|
98
121
|
const analyser = context.createAnalyser();
|
|
99
122
|
analyser.fftSize = 512;
|
|
100
|
-
analyser.smoothingTimeConstant = 0.
|
|
123
|
+
analyser.smoothingTimeConstant = 0.35;
|
|
101
124
|
analyser.minDecibels = -90;
|
|
102
125
|
analyser.maxDecibels = -10;
|
|
103
126
|
source.connect(analyser);
|
|
127
|
+
const sink = context.createGain();
|
|
128
|
+
sink.gain.value = 0;
|
|
129
|
+
analyser.connect(sink);
|
|
130
|
+
sink.connect(context.destination);
|
|
104
131
|
const data = new Float32Array(analyser.fftSize);
|
|
105
132
|
const state = {
|
|
106
133
|
participantId,
|
|
@@ -108,15 +135,20 @@ var ActiveSpeakerDetector = class {
|
|
|
108
135
|
stream,
|
|
109
136
|
source,
|
|
110
137
|
analyser,
|
|
138
|
+
sink,
|
|
111
139
|
data,
|
|
112
140
|
active: false,
|
|
141
|
+
level: 0,
|
|
113
142
|
lastActiveAt: 0
|
|
114
143
|
};
|
|
115
144
|
this.speakers.set(participantId, state);
|
|
116
145
|
track.addEventListener(
|
|
117
146
|
"ended",
|
|
118
147
|
() => {
|
|
119
|
-
this.
|
|
148
|
+
const current = this.speakers.get(participantId);
|
|
149
|
+
if (current?.track === track) {
|
|
150
|
+
this.removeParticipant(participantId);
|
|
151
|
+
}
|
|
120
152
|
},
|
|
121
153
|
{ once: true }
|
|
122
154
|
);
|
|
@@ -127,15 +159,19 @@ var ActiveSpeakerDetector = class {
|
|
|
127
159
|
const state = this.speakers.get(participantId);
|
|
128
160
|
if (!state) return;
|
|
129
161
|
state.active = false;
|
|
162
|
+
state.level = 0;
|
|
130
163
|
try {
|
|
131
164
|
state.source.disconnect();
|
|
132
165
|
} catch {
|
|
133
166
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
167
|
+
try {
|
|
168
|
+
state.analyser.disconnect();
|
|
169
|
+
} catch {
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
state.sink.disconnect();
|
|
173
|
+
} catch {
|
|
174
|
+
}
|
|
139
175
|
this.speakers.delete(participantId);
|
|
140
176
|
this.emitIfChanged();
|
|
141
177
|
}
|
|
@@ -147,7 +183,7 @@ var ActiveSpeakerDetector = class {
|
|
|
147
183
|
}
|
|
148
184
|
}
|
|
149
185
|
clear() {
|
|
150
|
-
for (const participantId of this.speakers.keys()) {
|
|
186
|
+
for (const participantId of [...this.speakers.keys()]) {
|
|
151
187
|
this.removeParticipant(participantId);
|
|
152
188
|
}
|
|
153
189
|
this.speakers.clear();
|
|
@@ -167,6 +203,7 @@ var ActiveSpeakerDetector = class {
|
|
|
167
203
|
const now = performance.now();
|
|
168
204
|
for (const state of this.speakers.values()) {
|
|
169
205
|
if (state.track.readyState !== "live" || state.track.muted || !state.track.enabled) {
|
|
206
|
+
state.level = 0;
|
|
170
207
|
if (state.active) {
|
|
171
208
|
state.active = false;
|
|
172
209
|
}
|
|
@@ -179,30 +216,33 @@ var ActiveSpeakerDetector = class {
|
|
|
179
216
|
sumSquares += sample * sample;
|
|
180
217
|
}
|
|
181
218
|
const rms = Math.sqrt(sumSquares / state.data.length);
|
|
219
|
+
state.level = rms;
|
|
182
220
|
if (!state.active) {
|
|
183
221
|
if (rms >= this.threshold) {
|
|
184
222
|
state.active = true;
|
|
185
223
|
state.lastActiveAt = now;
|
|
186
224
|
}
|
|
187
|
-
} else {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
state.active = false;
|
|
192
|
-
}
|
|
225
|
+
} else if (rms >= this.releaseThreshold) {
|
|
226
|
+
state.lastActiveAt = now;
|
|
227
|
+
} else if (now - state.lastActiveAt >= this.releaseMs) {
|
|
228
|
+
state.active = false;
|
|
193
229
|
}
|
|
194
230
|
}
|
|
195
231
|
this.emitIfChanged();
|
|
196
232
|
}
|
|
233
|
+
getActiveSpeakers() {
|
|
234
|
+
return Array.from(this.speakers.values()).filter((speaker) => speaker.active).sort((a, b) => {
|
|
235
|
+
if (b.level !== a.level) return b.level - a.level;
|
|
236
|
+
return a.participantId.localeCompare(b.participantId);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
197
239
|
getActiveSpeakerIds() {
|
|
198
|
-
return
|
|
240
|
+
return this.getActiveSpeakers().map((speaker) => speaker.participantId);
|
|
199
241
|
}
|
|
200
242
|
emitIfChanged(force = false) {
|
|
201
|
-
const ids = this.getActiveSpeakerIds()
|
|
243
|
+
const ids = this.getActiveSpeakerIds();
|
|
202
244
|
const key = ids.join("|");
|
|
203
|
-
if (!force && key === this.lastEmitted)
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
245
|
+
if (!force && key === this.lastEmitted) return;
|
|
206
246
|
this.lastEmitted = key;
|
|
207
247
|
this.onActiveSpeakersChanged(ids);
|
|
208
248
|
}
|
|
@@ -2347,26 +2387,11 @@ var VideoSDKCore = class {
|
|
|
2347
2387
|
async initLocal(video, name) {
|
|
2348
2388
|
this.participantName = name;
|
|
2349
2389
|
try {
|
|
2350
|
-
this.localStream = await
|
|
2351
|
-
video: {
|
|
2352
|
-
width: { ideal: 1280 },
|
|
2353
|
-
height: { ideal: 720 }
|
|
2354
|
-
},
|
|
2355
|
-
audio: {
|
|
2356
|
-
echoCancellation: true,
|
|
2357
|
-
noiseSuppression: true,
|
|
2358
|
-
autoGainControl: true
|
|
2359
|
-
}
|
|
2360
|
-
});
|
|
2390
|
+
this.localStream = await this.acquireOptionalLocalMedia();
|
|
2361
2391
|
const localAudioTrack = this.localStream.getAudioTracks()[0];
|
|
2362
2392
|
if (localAudioTrack) {
|
|
2363
2393
|
this.activeSpeakerDetector.addTrack(this.myId, localAudioTrack);
|
|
2364
2394
|
}
|
|
2365
|
-
const hasVideo = this.localStream.getVideoTracks().some((t) => t.readyState === "live");
|
|
2366
|
-
const hasAudio = this.localStream.getAudioTracks().some((t) => t.readyState === "live");
|
|
2367
|
-
if (!hasVideo || !hasAudio) {
|
|
2368
|
-
throw new Error(`Missing tracks: video=${hasVideo}, audio=${hasAudio}`);
|
|
2369
|
-
}
|
|
2370
2395
|
video.srcObject = this.localStream;
|
|
2371
2396
|
this.updateLocalMedia();
|
|
2372
2397
|
} catch (err) {
|
|
@@ -2383,8 +2408,8 @@ var VideoSDKCore = class {
|
|
|
2383
2408
|
stream: this.localStream,
|
|
2384
2409
|
cameraTrack: this.localStream.getVideoTracks()[0],
|
|
2385
2410
|
audioTrack: this.localStream.getAudioTracks()[0],
|
|
2386
|
-
micEnabled: this.localStream.getAudioTracks()[0]?.enabled ??
|
|
2387
|
-
camEnabled: this.localStream.getVideoTracks()[0]?.enabled ??
|
|
2411
|
+
micEnabled: this.localStream.getAudioTracks()[0]?.enabled ?? false,
|
|
2412
|
+
camEnabled: this.localStream.getVideoTracks()[0]?.enabled ?? false,
|
|
2388
2413
|
isScreenSharing: this.isScreenSharing,
|
|
2389
2414
|
screenStream: this.screenStream,
|
|
2390
2415
|
screenTrack: this.screenStream?.getVideoTracks()[0]
|
|
@@ -2411,6 +2436,70 @@ var VideoSDKCore = class {
|
|
|
2411
2436
|
async getMeetingSummary(roomCode, sessionId) {
|
|
2412
2437
|
return this.sfuClient.getMeetingSummary(roomCode, sessionId);
|
|
2413
2438
|
}
|
|
2439
|
+
async acquireOptionalLocalMedia(cameraDeviceId, microphoneDeviceId) {
|
|
2440
|
+
const combined = new MediaStream();
|
|
2441
|
+
if (!navigator.mediaDevices?.getUserMedia) {
|
|
2442
|
+
console.warn(
|
|
2443
|
+
"[SDK] Camera/microphone access is not supported; joining without local media."
|
|
2444
|
+
);
|
|
2445
|
+
return combined;
|
|
2446
|
+
}
|
|
2447
|
+
const cameraPromise = navigator.mediaDevices.getUserMedia({
|
|
2448
|
+
video: cameraDeviceId ? { deviceId: { exact: cameraDeviceId } } : {
|
|
2449
|
+
width: { ideal: 1280 },
|
|
2450
|
+
height: { ideal: 720 }
|
|
2451
|
+
},
|
|
2452
|
+
audio: false
|
|
2453
|
+
});
|
|
2454
|
+
const microphonePromise = navigator.mediaDevices.getUserMedia({
|
|
2455
|
+
video: false,
|
|
2456
|
+
audio: microphoneDeviceId ? {
|
|
2457
|
+
deviceId: { exact: microphoneDeviceId },
|
|
2458
|
+
echoCancellation: true,
|
|
2459
|
+
noiseSuppression: true,
|
|
2460
|
+
autoGainControl: true
|
|
2461
|
+
} : {
|
|
2462
|
+
echoCancellation: true,
|
|
2463
|
+
noiseSuppression: true,
|
|
2464
|
+
autoGainControl: true
|
|
2465
|
+
}
|
|
2466
|
+
});
|
|
2467
|
+
const [cameraResult, microphoneResult] = await Promise.allSettled([
|
|
2468
|
+
cameraPromise,
|
|
2469
|
+
microphonePromise
|
|
2470
|
+
]);
|
|
2471
|
+
if (cameraResult.status === "fulfilled") {
|
|
2472
|
+
for (const track of cameraResult.value.getVideoTracks()) {
|
|
2473
|
+
combined.addTrack(track);
|
|
2474
|
+
}
|
|
2475
|
+
} else {
|
|
2476
|
+
console.warn("[SDK] Camera unavailable; continuing without video.", {
|
|
2477
|
+
name: cameraResult.reason?.name,
|
|
2478
|
+
message: cameraResult.reason?.message
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
if (microphoneResult.status === "fulfilled") {
|
|
2482
|
+
for (const track of microphoneResult.value.getAudioTracks()) {
|
|
2483
|
+
combined.addTrack(track);
|
|
2484
|
+
}
|
|
2485
|
+
} else {
|
|
2486
|
+
console.warn(
|
|
2487
|
+
"[SDK] Microphone unavailable; continuing without audio.",
|
|
2488
|
+
{
|
|
2489
|
+
name: microphoneResult.reason?.name,
|
|
2490
|
+
message: microphoneResult.reason?.message
|
|
2491
|
+
}
|
|
2492
|
+
);
|
|
2493
|
+
}
|
|
2494
|
+
return combined;
|
|
2495
|
+
}
|
|
2496
|
+
/**
|
|
2497
|
+
* Wakes the active-speaker Web Audio pipeline. Call this from a user gesture
|
|
2498
|
+
* whenever possible (Join, first click inside the meeting, etc.).
|
|
2499
|
+
*/
|
|
2500
|
+
async resumeActiveSpeaker() {
|
|
2501
|
+
return this.activeSpeakerDetector.resume();
|
|
2502
|
+
}
|
|
2414
2503
|
// JOIN
|
|
2415
2504
|
async joinMeeting(config) {
|
|
2416
2505
|
const {
|
|
@@ -2454,15 +2543,10 @@ var VideoSDKCore = class {
|
|
|
2454
2543
|
this.room.id = roomId;
|
|
2455
2544
|
this.room.name = name;
|
|
2456
2545
|
if (!this.localStream) {
|
|
2457
|
-
this.localStream = await
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
echoCancellation: true,
|
|
2462
|
-
noiseSuppression: true,
|
|
2463
|
-
autoGainControl: true
|
|
2464
|
-
} : true
|
|
2465
|
-
});
|
|
2546
|
+
this.localStream = await this.acquireOptionalLocalMedia(
|
|
2547
|
+
cameraDeviceId,
|
|
2548
|
+
microphoneDeviceId
|
|
2549
|
+
);
|
|
2466
2550
|
const localAudioTrack = this.localStream.getAudioTracks()[0];
|
|
2467
2551
|
if (localAudioTrack) {
|
|
2468
2552
|
this.activeSpeakerDetector.addTrack(this.myId, localAudioTrack);
|
|
@@ -2507,8 +2591,8 @@ var VideoSDKCore = class {
|
|
|
2507
2591
|
await this.sfuClient.getToken(roomId, {
|
|
2508
2592
|
displayName: name,
|
|
2509
2593
|
participantId: this.myId,
|
|
2510
|
-
audioMuted: !(this.localStream?.getAudioTracks()[0]?.enabled ??
|
|
2511
|
-
videoMuted: !(this.localStream?.getVideoTracks()[0]?.enabled ??
|
|
2594
|
+
audioMuted: !(this.localStream?.getAudioTracks()[0]?.enabled ?? false),
|
|
2595
|
+
videoMuted: !(this.localStream?.getVideoTracks()[0]?.enabled ?? false)
|
|
2512
2596
|
});
|
|
2513
2597
|
}
|
|
2514
2598
|
createSFUClient(token) {
|
|
@@ -3568,6 +3652,7 @@ var MeetingProvider = ({
|
|
|
3568
3652
|
getMeetingSummary: sdk.getMeetingSummary.bind(sdk),
|
|
3569
3653
|
toggleMic: sdk.toggleMic.bind(sdk),
|
|
3570
3654
|
toggleCam: sdk.toggleCam.bind(sdk),
|
|
3655
|
+
resumeActiveSpeaker: sdk.resumeActiveSpeaker.bind(sdk),
|
|
3571
3656
|
startScreenShare: sdk.startScreenShare.bind(sdk),
|
|
3572
3657
|
stopScreenShare: sdk.stopScreenShare.bind(sdk),
|
|
3573
3658
|
sendMessage: sdk.sendChatMessage.bind(sdk),
|