@defcomm/meetingsdk 0.6.9 → 0.7.2
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 +20 -3
- package/dist/index.d.mts +15 -4
- package/dist/index.d.ts +15 -4
- package/dist/index.js +203 -73
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +203 -73
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -386,7 +386,7 @@ var MeetingState = class {
|
|
|
386
386
|
const nextMedia = {
|
|
387
387
|
stream: patch.media?.stream ?? prevMedia.stream,
|
|
388
388
|
screenStream: patch.media?.screenStream ?? prevMedia.screenStream,
|
|
389
|
-
cameraTrack: patch.media
|
|
389
|
+
cameraTrack: patch.media && Object.prototype.hasOwnProperty.call(patch.media, "cameraTrack") ? patch.media.cameraTrack ?? void 0 : prevMedia.cameraTrack,
|
|
390
390
|
screenTrack: patch.media?.screenTrack ?? prevMedia.screenTrack,
|
|
391
391
|
audioTrack: patch.media?.audioTrack ?? prevMedia.audioTrack,
|
|
392
392
|
micEnabled: patch.media?.micEnabled ?? prevMedia.micEnabled,
|
|
@@ -473,9 +473,9 @@ var SFUClient = class {
|
|
|
473
473
|
this.publisherRevision = 0;
|
|
474
474
|
this.screenShareGeneration = 0;
|
|
475
475
|
this.currentParticipantId = null;
|
|
476
|
-
//
|
|
476
|
+
// Token supplied by the application for REST and SFU authentication.
|
|
477
477
|
this.authToken = null;
|
|
478
|
-
//
|
|
478
|
+
// Token used for the current WebSocket session.
|
|
479
479
|
this.token = null;
|
|
480
480
|
this.room = null;
|
|
481
481
|
this.resumeToken = null;
|
|
@@ -647,6 +647,71 @@ var SFUClient = class {
|
|
|
647
647
|
setLocalStream(stream) {
|
|
648
648
|
this.localStream = stream;
|
|
649
649
|
}
|
|
650
|
+
/**
|
|
651
|
+
* Attach or detach the local camera track without replacing the publisher
|
|
652
|
+
* PeerConnection. Detaching with replaceTrack(null) stops media transmission;
|
|
653
|
+
* VideoSDKCore separately calls MediaStreamTrack.stop() to release hardware.
|
|
654
|
+
*/
|
|
655
|
+
async setCameraTrack(track) {
|
|
656
|
+
if (!this.localStream) this.localStream = new MediaStream();
|
|
657
|
+
const currentTrack = this.localStream.getVideoTracks().find((item) => item !== track);
|
|
658
|
+
if (currentTrack) this.localStream.removeTrack(currentTrack);
|
|
659
|
+
if (track && !this.localStream.getTracks().includes(track)) {
|
|
660
|
+
this.localStream.addTrack(track);
|
|
661
|
+
}
|
|
662
|
+
if (!this.videoSender || !this.publisher || !this.cameraTransceiver) {
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
const needsCameraNegotiation = Boolean(
|
|
666
|
+
track && this.cameraTransceiver.direction === "inactive"
|
|
667
|
+
);
|
|
668
|
+
if (needsCameraNegotiation && this.ws?.readyState !== WebSocket.OPEN) {
|
|
669
|
+
throw new Error("Cannot enable the camera while signaling is disconnected");
|
|
670
|
+
}
|
|
671
|
+
await this.videoSender.replaceTrack(track);
|
|
672
|
+
if (needsCameraNegotiation) {
|
|
673
|
+
await this.waitForPublisherStable();
|
|
674
|
+
this.cameraTransceiver.direction = "sendonly";
|
|
675
|
+
await this.sendPublisherOffer();
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
async waitForPublisherStable(timeoutMs = 5e3) {
|
|
679
|
+
const publisher = this.publisher;
|
|
680
|
+
if (!publisher) throw new Error("Publisher PeerConnection is not initialized");
|
|
681
|
+
const startedAt = Date.now();
|
|
682
|
+
while (publisher.signalingState !== "stable") {
|
|
683
|
+
if (publisher.signalingState === "closed") {
|
|
684
|
+
throw new Error("Publisher PeerConnection is closed");
|
|
685
|
+
}
|
|
686
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
687
|
+
throw new Error("Publisher negotiation did not become stable in time");
|
|
688
|
+
}
|
|
689
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
async sendPublisherOffer() {
|
|
693
|
+
if (!this.publisher) throw new Error("Publisher PeerConnection is not initialized");
|
|
694
|
+
const offer = await this.publisher.createOffer();
|
|
695
|
+
await this.publisher.setLocalDescription(offer);
|
|
696
|
+
const sent = this.send({
|
|
697
|
+
type: "publish_offer",
|
|
698
|
+
payload: {
|
|
699
|
+
revision: ++this.publisherRevision,
|
|
700
|
+
sdp: offer.sdp
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
if (!sent) {
|
|
704
|
+
try {
|
|
705
|
+
await this.publisher.setLocalDescription({ type: "rollback" });
|
|
706
|
+
} catch {
|
|
707
|
+
}
|
|
708
|
+
if (this.cameraTransceiver) {
|
|
709
|
+
this.cameraTransceiver.direction = "inactive";
|
|
710
|
+
}
|
|
711
|
+
await this.videoSender?.replaceTrack(null);
|
|
712
|
+
throw new Error("Unable to negotiate camera publishing: signaling is disconnected");
|
|
713
|
+
}
|
|
714
|
+
}
|
|
650
715
|
nextRequestId() {
|
|
651
716
|
return (++this.requestId).toString();
|
|
652
717
|
}
|
|
@@ -701,7 +766,8 @@ var SFUClient = class {
|
|
|
701
766
|
}
|
|
702
767
|
);
|
|
703
768
|
}
|
|
704
|
-
async
|
|
769
|
+
async join(roomCode, options = {}) {
|
|
770
|
+
if (!this.authToken) throw new Error("Authentication token is required");
|
|
705
771
|
const nextRoom = roomCode.trim();
|
|
706
772
|
if (this.room && this.room !== nextRoom) {
|
|
707
773
|
this.resumeToken = null;
|
|
@@ -719,33 +785,7 @@ var SFUClient = class {
|
|
|
719
785
|
if (!this.resumeToken) {
|
|
720
786
|
this.resumeToken = this.loadResumeToken(this.room);
|
|
721
787
|
}
|
|
722
|
-
|
|
723
|
-
method: "POST",
|
|
724
|
-
body: JSON.stringify({
|
|
725
|
-
room_code: this.room,
|
|
726
|
-
user_id: this.participantId,
|
|
727
|
-
display_name: options.displayName,
|
|
728
|
-
avatar_url: options.avatarUrl
|
|
729
|
-
})
|
|
730
|
-
});
|
|
731
|
-
this.token = data?.token;
|
|
732
|
-
if (!this.token) throw new Error("Token endpoint returned no token");
|
|
733
|
-
return this.connect(this.token, this.joinOptions);
|
|
734
|
-
}
|
|
735
|
-
async refreshAccessToken() {
|
|
736
|
-
if (!this.room) throw new Error("Cannot refresh token without a room");
|
|
737
|
-
const data = await this.request(`${this.apiBase}/token`, {
|
|
738
|
-
method: "POST",
|
|
739
|
-
body: JSON.stringify({
|
|
740
|
-
room_code: this.room,
|
|
741
|
-
user_id: this.participantId,
|
|
742
|
-
display_name: this.joinOptions.displayName,
|
|
743
|
-
avatar_url: this.joinOptions.avatarUrl
|
|
744
|
-
})
|
|
745
|
-
});
|
|
746
|
-
if (!data?.token) throw new Error("Token refresh returned no token");
|
|
747
|
-
this.token = data.token;
|
|
748
|
-
return this.token;
|
|
788
|
+
return this.connect(this.authToken, this.joinOptions);
|
|
749
789
|
}
|
|
750
790
|
connect(token, options = {}) {
|
|
751
791
|
this.token = token;
|
|
@@ -835,15 +875,9 @@ var SFUClient = class {
|
|
|
835
875
|
this.reconnectBaseMs * Math.pow(2, this.reconnectAttempt - 1)
|
|
836
876
|
);
|
|
837
877
|
this.onReconnecting(this.reconnectAttempt);
|
|
838
|
-
this.reconnectTimer = setTimeout(
|
|
878
|
+
this.reconnectTimer = setTimeout(() => {
|
|
839
879
|
this.reconnectTimer = null;
|
|
840
|
-
|
|
841
|
-
await this.refreshAccessToken();
|
|
842
|
-
this.openWebSocket(this.joinOptions);
|
|
843
|
-
} catch (error) {
|
|
844
|
-
this.onError(error);
|
|
845
|
-
this.scheduleReconnect();
|
|
846
|
-
}
|
|
880
|
+
this.openWebSocket(this.joinOptions);
|
|
847
881
|
}, delay);
|
|
848
882
|
}
|
|
849
883
|
failJoin(error) {
|
|
@@ -2324,6 +2358,8 @@ var VideoSDKCore = class {
|
|
|
2324
2358
|
this.screenStream = null;
|
|
2325
2359
|
this.isScreenSharing = false;
|
|
2326
2360
|
this.participantName = "";
|
|
2361
|
+
this.cameraEnabled = false;
|
|
2362
|
+
this.cameraToggleInProgress = false;
|
|
2327
2363
|
this.intentionalDisconnect = false;
|
|
2328
2364
|
this.remoteStreams = /* @__PURE__ */ new Map();
|
|
2329
2365
|
this.remoteScreenStreams = /* @__PURE__ */ new Map();
|
|
@@ -2357,6 +2393,7 @@ var VideoSDKCore = class {
|
|
|
2357
2393
|
this.participantName = name;
|
|
2358
2394
|
try {
|
|
2359
2395
|
this.localStream = await this.acquireOptionalLocalMedia();
|
|
2396
|
+
this.cameraEnabled = this.hasLiveCameraTrack();
|
|
2360
2397
|
const localAudioTrack = this.localStream.getAudioTracks()[0];
|
|
2361
2398
|
if (localAudioTrack) {
|
|
2362
2399
|
this.activeSpeakerDetector.addTrack(this.myId, localAudioTrack);
|
|
@@ -2368,17 +2405,47 @@ var VideoSDKCore = class {
|
|
|
2368
2405
|
throw err;
|
|
2369
2406
|
}
|
|
2370
2407
|
}
|
|
2371
|
-
|
|
2408
|
+
hasLiveCameraTrack() {
|
|
2409
|
+
return Boolean(
|
|
2410
|
+
this.localStream?.getVideoTracks().some((track) => track.readyState === "live")
|
|
2411
|
+
);
|
|
2412
|
+
}
|
|
2413
|
+
getLiveCameraTrack() {
|
|
2414
|
+
return this.localStream?.getVideoTracks().find((track) => track.readyState === "live") ?? null;
|
|
2415
|
+
}
|
|
2416
|
+
/**
|
|
2417
|
+
* Stop every locally captured camera track and remove it from the stream.
|
|
2418
|
+
* Track.enabled=false only emits black frames; stop() releases camera capture.
|
|
2419
|
+
*/
|
|
2420
|
+
stopCameraCapture() {
|
|
2421
|
+
if (!this.localStream) {
|
|
2422
|
+
this.cameraEnabled = false;
|
|
2423
|
+
return;
|
|
2424
|
+
}
|
|
2425
|
+
for (const track of this.localStream.getVideoTracks()) {
|
|
2426
|
+
this.localStream.removeTrack(track);
|
|
2427
|
+
try {
|
|
2428
|
+
track.stop();
|
|
2429
|
+
} catch {
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
this.cameraEnabled = false;
|
|
2433
|
+
}
|
|
2434
|
+
updateLocalMedia() {
|
|
2372
2435
|
if (!this.localStream) return;
|
|
2436
|
+
const cameraTrack = this.getLiveCameraTrack();
|
|
2437
|
+
const audioTrack = this.localStream.getAudioTracks().find((track) => track.readyState === "live");
|
|
2438
|
+
this.cameraEnabled = Boolean(cameraTrack && cameraTrack.enabled);
|
|
2373
2439
|
this.state.updateLocalParticipant({
|
|
2374
2440
|
id: this.myId,
|
|
2375
2441
|
name: this.participantName,
|
|
2376
2442
|
media: {
|
|
2377
2443
|
stream: this.localStream,
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2444
|
+
// Explicit null clears a previously published track from React state.
|
|
2445
|
+
cameraTrack,
|
|
2446
|
+
audioTrack: audioTrack ?? void 0,
|
|
2447
|
+
micEnabled: audioTrack?.enabled ?? false,
|
|
2448
|
+
camEnabled: this.cameraEnabled,
|
|
2382
2449
|
isScreenSharing: this.isScreenSharing,
|
|
2383
2450
|
screenStream: this.screenStream,
|
|
2384
2451
|
screenTrack: this.screenStream?.getVideoTracks()[0]
|
|
@@ -2405,7 +2472,7 @@ var VideoSDKCore = class {
|
|
|
2405
2472
|
async getMeetingSummary(roomCode, sessionId) {
|
|
2406
2473
|
return this.sfuClient.getMeetingSummary(roomCode, sessionId);
|
|
2407
2474
|
}
|
|
2408
|
-
async acquireOptionalLocalMedia(cameraDeviceId, microphoneDeviceId) {
|
|
2475
|
+
async acquireOptionalLocalMedia(cameraDeviceId, microphoneDeviceId, includeVideo = true) {
|
|
2409
2476
|
const combined = new MediaStream();
|
|
2410
2477
|
if (!navigator.mediaDevices?.getUserMedia) {
|
|
2411
2478
|
console.warn(
|
|
@@ -2413,13 +2480,13 @@ var VideoSDKCore = class {
|
|
|
2413
2480
|
);
|
|
2414
2481
|
return combined;
|
|
2415
2482
|
}
|
|
2416
|
-
const cameraPromise = navigator.mediaDevices.getUserMedia({
|
|
2483
|
+
const cameraPromise = includeVideo ? navigator.mediaDevices.getUserMedia({
|
|
2417
2484
|
video: cameraDeviceId ? { deviceId: { exact: cameraDeviceId } } : {
|
|
2418
2485
|
width: { ideal: 1280 },
|
|
2419
2486
|
height: { ideal: 720 }
|
|
2420
2487
|
},
|
|
2421
2488
|
audio: false
|
|
2422
|
-
});
|
|
2489
|
+
}) : Promise.resolve(null);
|
|
2423
2490
|
const microphonePromise = navigator.mediaDevices.getUserMedia({
|
|
2424
2491
|
video: false,
|
|
2425
2492
|
audio: microphoneDeviceId ? {
|
|
@@ -2437,11 +2504,11 @@ var VideoSDKCore = class {
|
|
|
2437
2504
|
cameraPromise,
|
|
2438
2505
|
microphonePromise
|
|
2439
2506
|
]);
|
|
2440
|
-
if (cameraResult.status === "fulfilled") {
|
|
2507
|
+
if (cameraResult.status === "fulfilled" && cameraResult.value) {
|
|
2441
2508
|
for (const track of cameraResult.value.getVideoTracks()) {
|
|
2442
2509
|
combined.addTrack(track);
|
|
2443
2510
|
}
|
|
2444
|
-
} else {
|
|
2511
|
+
} else if (cameraResult.status === "rejected") {
|
|
2445
2512
|
console.warn("[SDK] Camera unavailable; continuing without video.", {
|
|
2446
2513
|
name: cameraResult.reason?.name,
|
|
2447
2514
|
message: cameraResult.reason?.message
|
|
@@ -2462,6 +2529,25 @@ var VideoSDKCore = class {
|
|
|
2462
2529
|
}
|
|
2463
2530
|
return combined;
|
|
2464
2531
|
}
|
|
2532
|
+
async acquireCameraTrack() {
|
|
2533
|
+
if (!navigator.mediaDevices?.getUserMedia) {
|
|
2534
|
+
throw new Error("Camera access is not supported on this device");
|
|
2535
|
+
}
|
|
2536
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
2537
|
+
video: this.cameraDeviceId ? { deviceId: { exact: this.cameraDeviceId } } : {
|
|
2538
|
+
width: { ideal: 1280 },
|
|
2539
|
+
height: { ideal: 720 }
|
|
2540
|
+
},
|
|
2541
|
+
audio: false
|
|
2542
|
+
});
|
|
2543
|
+
const track = stream.getVideoTracks()[0];
|
|
2544
|
+
if (!track) {
|
|
2545
|
+
stream.getTracks().forEach((item) => item.stop());
|
|
2546
|
+
throw new Error("The selected camera did not provide a video track");
|
|
2547
|
+
}
|
|
2548
|
+
this.cameraDeviceId = track.getSettings().deviceId || this.cameraDeviceId;
|
|
2549
|
+
return track;
|
|
2550
|
+
}
|
|
2465
2551
|
/**
|
|
2466
2552
|
* Wakes the active-speaker Web Audio pipeline. Call this from a user gesture
|
|
2467
2553
|
* whenever possible (Join, first click inside the meeting, etc.).
|
|
@@ -2511,10 +2597,12 @@ var VideoSDKCore = class {
|
|
|
2511
2597
|
this.participantName = name;
|
|
2512
2598
|
this.room.id = roomId;
|
|
2513
2599
|
this.room.name = name;
|
|
2600
|
+
this.cameraDeviceId = cameraDeviceId ?? this.cameraDeviceId;
|
|
2514
2601
|
if (!this.localStream) {
|
|
2515
2602
|
this.localStream = await this.acquireOptionalLocalMedia(
|
|
2516
|
-
cameraDeviceId,
|
|
2517
|
-
microphoneDeviceId
|
|
2603
|
+
this.cameraDeviceId,
|
|
2604
|
+
microphoneDeviceId,
|
|
2605
|
+
!videoMuted
|
|
2518
2606
|
);
|
|
2519
2607
|
const localAudioTrack = this.localStream.getAudioTracks()[0];
|
|
2520
2608
|
if (localAudioTrack) {
|
|
@@ -2524,10 +2612,17 @@ var VideoSDKCore = class {
|
|
|
2524
2612
|
this.localStream.getAudioTracks().forEach((track) => {
|
|
2525
2613
|
track.enabled = !audioMuted;
|
|
2526
2614
|
});
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
}
|
|
2530
|
-
|
|
2615
|
+
if (videoMuted) {
|
|
2616
|
+
this.stopCameraCapture();
|
|
2617
|
+
} else {
|
|
2618
|
+
const initialCameraTrack = this.getLiveCameraTrack();
|
|
2619
|
+
this.cameraEnabled = Boolean(initialCameraTrack);
|
|
2620
|
+
if (initialCameraTrack) {
|
|
2621
|
+
this.cameraDeviceId = initialCameraTrack.getSettings().deviceId || this.cameraDeviceId;
|
|
2622
|
+
initialCameraTrack.enabled = true;
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
this.updateLocalMedia();
|
|
2531
2626
|
const promise = this.connect(roomId, name);
|
|
2532
2627
|
this.joinPromise = promise;
|
|
2533
2628
|
try {
|
|
@@ -2557,7 +2652,7 @@ var VideoSDKCore = class {
|
|
|
2557
2652
|
);
|
|
2558
2653
|
}
|
|
2559
2654
|
this.sfuClient.setLocalStream(this.localStream);
|
|
2560
|
-
await this.sfuClient.
|
|
2655
|
+
await this.sfuClient.join(roomId, {
|
|
2561
2656
|
displayName: name,
|
|
2562
2657
|
participantId: this.myId,
|
|
2563
2658
|
audioMuted: !(this.localStream?.getAudioTracks()[0]?.enabled ?? false),
|
|
@@ -3154,7 +3249,12 @@ var VideoSDKCore = class {
|
|
|
3154
3249
|
if (!this.sfuClient) {
|
|
3155
3250
|
throw new Error("SFU client is not initialized");
|
|
3156
3251
|
}
|
|
3252
|
+
if (!this.cameraEnabled) {
|
|
3253
|
+
throw new Error("Your camera is off. Turn it on before switching devices.");
|
|
3254
|
+
}
|
|
3157
3255
|
const track = await this.sfuClient.selectCamera(deviceId);
|
|
3256
|
+
this.cameraDeviceId = deviceId;
|
|
3257
|
+
this.cameraEnabled = true;
|
|
3158
3258
|
if (this.localStream) {
|
|
3159
3259
|
this.state.localStream = this.localStream;
|
|
3160
3260
|
this.updateLocalMedia();
|
|
@@ -3196,24 +3296,52 @@ var VideoSDKCore = class {
|
|
|
3196
3296
|
this.sfuClient?.muteAudio(!nextEnabled);
|
|
3197
3297
|
this.events.onMicToggled?.(this.myId, nextEnabled);
|
|
3198
3298
|
}
|
|
3199
|
-
toggleCam() {
|
|
3200
|
-
|
|
3201
|
-
if (
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
camEnabled: nextEnabled
|
|
3299
|
+
async toggleCam() {
|
|
3300
|
+
if (!this.state.localParticipant?.media || !this.localStream) return;
|
|
3301
|
+
if (this.cameraToggleInProgress) return;
|
|
3302
|
+
this.cameraToggleInProgress = true;
|
|
3303
|
+
const nextEnabled = !this.cameraEnabled;
|
|
3304
|
+
try {
|
|
3305
|
+
if (!nextEnabled) {
|
|
3306
|
+
this.sfuClient?.muteVideo(true);
|
|
3307
|
+
this.stopCameraCapture();
|
|
3308
|
+
await this.sfuClient?.setCameraTrack(null);
|
|
3309
|
+
this.updateLocalMedia();
|
|
3310
|
+
this.events.onCamToggled?.(this.myId, false);
|
|
3311
|
+
return;
|
|
3213
3312
|
}
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3313
|
+
const track = await this.acquireCameraTrack();
|
|
3314
|
+
if (!this.localStream) this.localStream = new MediaStream();
|
|
3315
|
+
this.localStream.addTrack(track);
|
|
3316
|
+
try {
|
|
3317
|
+
await this.sfuClient?.setCameraTrack(track);
|
|
3318
|
+
this.cameraEnabled = true;
|
|
3319
|
+
this.sfuClient?.muteVideo(false);
|
|
3320
|
+
this.updateLocalMedia();
|
|
3321
|
+
this.events.onCamToggled?.(this.myId, true);
|
|
3322
|
+
} catch (error) {
|
|
3323
|
+
this.localStream.removeTrack(track);
|
|
3324
|
+
try {
|
|
3325
|
+
track.stop();
|
|
3326
|
+
} catch {
|
|
3327
|
+
}
|
|
3328
|
+
this.cameraEnabled = false;
|
|
3329
|
+
this.updateLocalMedia();
|
|
3330
|
+
throw error;
|
|
3331
|
+
}
|
|
3332
|
+
} catch (error) {
|
|
3333
|
+
this.cameraEnabled = false;
|
|
3334
|
+
this.updateLocalMedia();
|
|
3335
|
+
this.emitError(
|
|
3336
|
+
"CAMERA_TOGGLE_FAILED",
|
|
3337
|
+
error?.message || "Unable to change camera state",
|
|
3338
|
+
error,
|
|
3339
|
+
true
|
|
3340
|
+
);
|
|
3341
|
+
throw error;
|
|
3342
|
+
} finally {
|
|
3343
|
+
this.cameraToggleInProgress = false;
|
|
3344
|
+
}
|
|
3217
3345
|
}
|
|
3218
3346
|
// SCREEN SHARING
|
|
3219
3347
|
async startScreenShare() {
|
|
@@ -3371,6 +3499,8 @@ var VideoSDKCore = class {
|
|
|
3371
3499
|
this.localStream.getTracks().forEach((track) => track.stop());
|
|
3372
3500
|
this.localStream = null;
|
|
3373
3501
|
}
|
|
3502
|
+
this.cameraEnabled = false;
|
|
3503
|
+
this.cameraToggleInProgress = false;
|
|
3374
3504
|
if (this.screenStream) {
|
|
3375
3505
|
this.screenStream.getTracks().forEach((track) => track.stop());
|
|
3376
3506
|
this.screenStream = null;
|