@stream-io/video-client 1.44.3 → 1.44.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/CHANGELOG.md +14 -0
- package/dist/index.browser.es.js +134 -45
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +134 -45
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +134 -45
- package/dist/index.es.js.map +1 -1
- package/dist/src/devices/BrowserPermission.d.ts +2 -0
- package/dist/src/devices/CameraManagerState.d.ts +2 -1
- package/dist/src/devices/MicrophoneManagerState.d.ts +2 -1
- package/dist/src/devices/devices.d.ts +2 -2
- package/dist/src/helpers/AudioBindingsWatchdog.d.ts +37 -0
- package/dist/src/helpers/DynascaleManager.d.ts +3 -1
- package/package.json +2 -2
- package/src/devices/BrowserPermission.ts +5 -0
- package/src/devices/CameraManager.ts +6 -1
- package/src/devices/CameraManagerState.ts +3 -2
- package/src/devices/MicrophoneManager.ts +1 -2
- package/src/devices/MicrophoneManagerState.ts +3 -2
- package/src/devices/devices.ts +26 -34
- package/src/helpers/AudioBindingsWatchdog.ts +118 -0
- package/src/helpers/DynascaleManager.ts +22 -24
- package/src/helpers/__tests__/AudioBindingsWatchdog.test.ts +325 -0
- package/src/helpers/__tests__/DynascaleManager.test.ts +64 -0
package/dist/index.es.js
CHANGED
|
@@ -6284,7 +6284,7 @@ const getSdkVersion = (sdk) => {
|
|
|
6284
6284
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
6285
6285
|
};
|
|
6286
6286
|
|
|
6287
|
-
const version = "1.44.
|
|
6287
|
+
const version = "1.44.5";
|
|
6288
6288
|
const [major, minor, patch] = version.split('.');
|
|
6289
6289
|
let sdkInfo = {
|
|
6290
6290
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -9492,6 +9492,96 @@ class ViewportTracker {
|
|
|
9492
9492
|
}
|
|
9493
9493
|
}
|
|
9494
9494
|
|
|
9495
|
+
const toBindingKey = (sessionId, trackType = 'audioTrack') => `${sessionId}/${trackType}`;
|
|
9496
|
+
/**
|
|
9497
|
+
* Tracks audio element bindings and periodically warns about
|
|
9498
|
+
* remote participants whose audio streams have no bound element.
|
|
9499
|
+
*/
|
|
9500
|
+
class AudioBindingsWatchdog {
|
|
9501
|
+
constructor(state, tracer) {
|
|
9502
|
+
this.state = state;
|
|
9503
|
+
this.tracer = tracer;
|
|
9504
|
+
this.bindings = new Map();
|
|
9505
|
+
this.enabled = true;
|
|
9506
|
+
this.logger = videoLoggerSystem.getLogger('AudioBindingsWatchdog');
|
|
9507
|
+
/**
|
|
9508
|
+
* Registers an audio element binding for the given session and track type.
|
|
9509
|
+
* Warns if a different element is already bound to the same key.
|
|
9510
|
+
*/
|
|
9511
|
+
this.register = (audioElement, sessionId, trackType) => {
|
|
9512
|
+
const key = toBindingKey(sessionId, trackType);
|
|
9513
|
+
const existing = this.bindings.get(key);
|
|
9514
|
+
if (existing && existing !== audioElement) {
|
|
9515
|
+
this.logger.warn(`Audio element already bound to ${sessionId} and ${trackType}`);
|
|
9516
|
+
this.tracer.trace('audioBinding.alreadyBoundWarning', trackType);
|
|
9517
|
+
}
|
|
9518
|
+
this.bindings.set(key, audioElement);
|
|
9519
|
+
};
|
|
9520
|
+
/**
|
|
9521
|
+
* Removes the audio element binding for the given session and track type.
|
|
9522
|
+
*/
|
|
9523
|
+
this.unregister = (sessionId, trackType) => {
|
|
9524
|
+
this.bindings.delete(toBindingKey(sessionId, trackType));
|
|
9525
|
+
};
|
|
9526
|
+
/**
|
|
9527
|
+
* Enables or disables the watchdog.
|
|
9528
|
+
* When disabled, the periodic check stops but bindings are still tracked.
|
|
9529
|
+
*/
|
|
9530
|
+
this.setEnabled = (enabled) => {
|
|
9531
|
+
this.enabled = enabled;
|
|
9532
|
+
if (enabled) {
|
|
9533
|
+
this.start();
|
|
9534
|
+
}
|
|
9535
|
+
else {
|
|
9536
|
+
this.stop();
|
|
9537
|
+
}
|
|
9538
|
+
};
|
|
9539
|
+
/**
|
|
9540
|
+
* Stops the watchdog and unsubscribes from callingState changes.
|
|
9541
|
+
*/
|
|
9542
|
+
this.dispose = () => {
|
|
9543
|
+
this.stop();
|
|
9544
|
+
this.unsubscribeCallingState();
|
|
9545
|
+
};
|
|
9546
|
+
this.start = () => {
|
|
9547
|
+
clearInterval(this.watchdogInterval);
|
|
9548
|
+
this.watchdogInterval = setInterval(() => {
|
|
9549
|
+
const danglingUserIds = [];
|
|
9550
|
+
for (const p of this.state.participants) {
|
|
9551
|
+
if (p.isLocalParticipant)
|
|
9552
|
+
continue;
|
|
9553
|
+
const { audioStream, screenShareAudioStream, sessionId, userId } = p;
|
|
9554
|
+
if (audioStream && !this.bindings.has(toBindingKey(sessionId))) {
|
|
9555
|
+
danglingUserIds.push(userId);
|
|
9556
|
+
}
|
|
9557
|
+
if (screenShareAudioStream &&
|
|
9558
|
+
!this.bindings.has(toBindingKey(sessionId, 'screenShareAudioTrack'))) {
|
|
9559
|
+
danglingUserIds.push(userId);
|
|
9560
|
+
}
|
|
9561
|
+
}
|
|
9562
|
+
if (danglingUserIds.length > 0) {
|
|
9563
|
+
const key = 'audioBinding.danglingWarning';
|
|
9564
|
+
this.tracer.traceOnce(key, key, danglingUserIds);
|
|
9565
|
+
this.logger.warn(`Dangling audio bindings detected. Did you forget to bind the audio element? user_ids: ${danglingUserIds}.`);
|
|
9566
|
+
}
|
|
9567
|
+
}, 3000);
|
|
9568
|
+
};
|
|
9569
|
+
this.stop = () => {
|
|
9570
|
+
clearInterval(this.watchdogInterval);
|
|
9571
|
+
};
|
|
9572
|
+
this.unsubscribeCallingState = createSubscription(state.callingState$, (callingState) => {
|
|
9573
|
+
if (!this.enabled)
|
|
9574
|
+
return;
|
|
9575
|
+
if (callingState !== CallingState.JOINED) {
|
|
9576
|
+
this.stop();
|
|
9577
|
+
}
|
|
9578
|
+
else {
|
|
9579
|
+
this.start();
|
|
9580
|
+
}
|
|
9581
|
+
});
|
|
9582
|
+
}
|
|
9583
|
+
}
|
|
9584
|
+
|
|
9495
9585
|
const DEFAULT_VIEWPORT_VISIBILITY_STATE = {
|
|
9496
9586
|
videoTrack: VisibilityState.UNKNOWN,
|
|
9497
9587
|
screenShareTrack: VisibilityState.UNKNOWN,
|
|
@@ -9517,7 +9607,7 @@ class DynascaleManager {
|
|
|
9517
9607
|
*/
|
|
9518
9608
|
this.viewportTracker = new ViewportTracker();
|
|
9519
9609
|
this.logger = videoLoggerSystem.getLogger('DynascaleManager');
|
|
9520
|
-
this.useWebAudio =
|
|
9610
|
+
this.useWebAudio = false;
|
|
9521
9611
|
this.pendingSubscriptionsUpdate = null;
|
|
9522
9612
|
this.videoTrackSubscriptionOverridesSubject = new BehaviorSubject({});
|
|
9523
9613
|
this.videoTrackSubscriptionOverrides$ = this.videoTrackSubscriptionOverridesSubject.asObservable();
|
|
@@ -9549,7 +9639,8 @@ class DynascaleManager {
|
|
|
9549
9639
|
if (this.pendingSubscriptionsUpdate) {
|
|
9550
9640
|
clearTimeout(this.pendingSubscriptionsUpdate);
|
|
9551
9641
|
}
|
|
9552
|
-
|
|
9642
|
+
this.audioBindingsWatchdog?.dispose();
|
|
9643
|
+
const context = this.audioContext;
|
|
9553
9644
|
if (context && context.state !== 'closed') {
|
|
9554
9645
|
document.removeEventListener('click', this.resumeAudioContext);
|
|
9555
9646
|
await context.close();
|
|
@@ -9748,12 +9839,13 @@ class DynascaleManager {
|
|
|
9748
9839
|
lastDimensions = currentDimensions;
|
|
9749
9840
|
});
|
|
9750
9841
|
resizeObserver?.observe(videoElement);
|
|
9842
|
+
const isVideoTrack = trackType === 'videoTrack';
|
|
9751
9843
|
// element renders and gets bound - track subscription gets
|
|
9752
9844
|
// triggered first other ones get skipped on initial subscriptions
|
|
9753
9845
|
const publishedTracksSubscription = boundParticipant.isLocalParticipant
|
|
9754
9846
|
? null
|
|
9755
9847
|
: participant$
|
|
9756
|
-
.pipe(distinctUntilKeyChanged('publishedTracks'), map((p) =>
|
|
9848
|
+
.pipe(distinctUntilKeyChanged('publishedTracks'), map((p) => (isVideoTrack ? hasVideo(p) : hasScreenShare(p))), distinctUntilChanged())
|
|
9757
9849
|
.subscribe((isPublishing) => {
|
|
9758
9850
|
if (isPublishing) {
|
|
9759
9851
|
// the participant just started to publish a track
|
|
@@ -9773,10 +9865,11 @@ class DynascaleManager {
|
|
|
9773
9865
|
// without prior user interaction:
|
|
9774
9866
|
// https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide
|
|
9775
9867
|
videoElement.muted = true;
|
|
9868
|
+
const trackKey = isVideoTrack ? 'videoStream' : 'screenShareStream';
|
|
9776
9869
|
const streamSubscription = participant$
|
|
9777
|
-
.pipe(distinctUntilKeyChanged(
|
|
9870
|
+
.pipe(distinctUntilKeyChanged(trackKey))
|
|
9778
9871
|
.subscribe((p) => {
|
|
9779
|
-
const source =
|
|
9872
|
+
const source = isVideoTrack ? p.videoStream : p.screenShareStream;
|
|
9780
9873
|
if (videoElement.srcObject === source)
|
|
9781
9874
|
return;
|
|
9782
9875
|
videoElement.srcObject = source ?? null;
|
|
@@ -9815,6 +9908,7 @@ class DynascaleManager {
|
|
|
9815
9908
|
const participant = this.callState.findParticipantBySessionId(sessionId);
|
|
9816
9909
|
if (!participant || participant.isLocalParticipant)
|
|
9817
9910
|
return;
|
|
9911
|
+
this.audioBindingsWatchdog?.register(audioElement, sessionId, trackType);
|
|
9818
9912
|
const participant$ = this.callState.participants$.pipe(map((ps) => ps.find((p) => p.sessionId === sessionId)), takeWhile((p) => !!p), distinctUntilChanged(), shareReplay({ bufferSize: 1, refCount: true }));
|
|
9819
9913
|
const updateSinkId = (deviceId, audioContext) => {
|
|
9820
9914
|
if (!deviceId)
|
|
@@ -9833,14 +9927,12 @@ class DynascaleManager {
|
|
|
9833
9927
|
};
|
|
9834
9928
|
let sourceNode = undefined;
|
|
9835
9929
|
let gainNode = undefined;
|
|
9930
|
+
const isAudioTrack = trackType === 'audioTrack';
|
|
9931
|
+
const trackKey = isAudioTrack ? 'audioStream' : 'screenShareAudioStream';
|
|
9836
9932
|
const updateMediaStreamSubscription = participant$
|
|
9837
|
-
.pipe(distinctUntilKeyChanged(
|
|
9838
|
-
? 'screenShareAudioStream'
|
|
9839
|
-
: 'audioStream'))
|
|
9933
|
+
.pipe(distinctUntilKeyChanged(trackKey))
|
|
9840
9934
|
.subscribe((p) => {
|
|
9841
|
-
const source =
|
|
9842
|
-
? p.screenShareAudioStream
|
|
9843
|
-
: p.audioStream;
|
|
9935
|
+
const source = isAudioTrack ? p.audioStream : p.screenShareAudioStream;
|
|
9844
9936
|
if (audioElement.srcObject === source)
|
|
9845
9937
|
return;
|
|
9846
9938
|
setTimeout(() => {
|
|
@@ -9895,6 +9987,7 @@ class DynascaleManager {
|
|
|
9895
9987
|
});
|
|
9896
9988
|
audioElement.autoplay = true;
|
|
9897
9989
|
return () => {
|
|
9990
|
+
this.audioBindingsWatchdog?.unregister(sessionId, trackType);
|
|
9898
9991
|
sinkIdSubscription?.unsubscribe();
|
|
9899
9992
|
volumeSubscription.unsubscribe();
|
|
9900
9993
|
updateMediaStreamSubscription.unsubscribe();
|
|
@@ -9955,6 +10048,9 @@ class DynascaleManager {
|
|
|
9955
10048
|
this.callState = callState;
|
|
9956
10049
|
this.speaker = speaker;
|
|
9957
10050
|
this.tracer = tracer;
|
|
10051
|
+
if (!isReactNative()) {
|
|
10052
|
+
this.audioBindingsWatchdog = new AudioBindingsWatchdog(callState, tracer);
|
|
10053
|
+
}
|
|
9958
10054
|
}
|
|
9959
10055
|
setSfuClient(sfuClient) {
|
|
9960
10056
|
this.sfuClient = sfuClient;
|
|
@@ -10299,6 +10395,9 @@ class BrowserPermission {
|
|
|
10299
10395
|
}
|
|
10300
10396
|
setState(state) {
|
|
10301
10397
|
if (this.state !== state) {
|
|
10398
|
+
const { tracer, queryName } = this.permission;
|
|
10399
|
+
const traceKey = `navigator.mediaDevices.${queryName}.permission`;
|
|
10400
|
+
tracer?.trace(traceKey, { previous: this.state, state });
|
|
10302
10401
|
this.state = state;
|
|
10303
10402
|
this.listeners.forEach((listener) => listener(state));
|
|
10304
10403
|
}
|
|
@@ -10340,9 +10439,6 @@ const getDevices = (permission, kind, tracer) => {
|
|
|
10340
10439
|
const checkIfAudioOutputChangeSupported = () => {
|
|
10341
10440
|
if (typeof document === 'undefined')
|
|
10342
10441
|
return false;
|
|
10343
|
-
// Safari uses WebAudio API for playing audio, so we check the AudioContext prototype
|
|
10344
|
-
if (isSafari())
|
|
10345
|
-
return 'setSinkId' in AudioContext.prototype;
|
|
10346
10442
|
const element = document.createElement('audio');
|
|
10347
10443
|
return 'setSinkId' in element;
|
|
10348
10444
|
};
|
|
@@ -10369,17 +10465,19 @@ const videoDeviceConstraints = {
|
|
|
10369
10465
|
* Keeps track of the browser permission to use microphone. This permission also
|
|
10370
10466
|
* affects an ability to enumerate audio devices.
|
|
10371
10467
|
*/
|
|
10372
|
-
const getAudioBrowserPermission = lazy(() => new BrowserPermission({
|
|
10468
|
+
const getAudioBrowserPermission = lazy((tracer) => new BrowserPermission({
|
|
10373
10469
|
constraints: audioDeviceConstraints,
|
|
10374
10470
|
queryName: 'microphone',
|
|
10471
|
+
tracer,
|
|
10375
10472
|
}));
|
|
10376
10473
|
/**
|
|
10377
10474
|
* Keeps track of the browser permission to use camera. This permission also
|
|
10378
10475
|
* affects an ability to enumerate video devices.
|
|
10379
10476
|
*/
|
|
10380
|
-
const getVideoBrowserPermission = lazy(() => new BrowserPermission({
|
|
10477
|
+
const getVideoBrowserPermission = lazy((tracer) => new BrowserPermission({
|
|
10381
10478
|
constraints: videoDeviceConstraints,
|
|
10382
10479
|
queryName: 'camera',
|
|
10480
|
+
tracer,
|
|
10383
10481
|
}));
|
|
10384
10482
|
const getDeviceChangeObserver = lazy((tracer) => {
|
|
10385
10483
|
// 'addEventListener' is not available in React Native, returning
|
|
@@ -10395,7 +10493,7 @@ const getDeviceChangeObserver = lazy((tracer) => {
|
|
|
10395
10493
|
* the observable errors.
|
|
10396
10494
|
*/
|
|
10397
10495
|
const getAudioDevices = lazy((tracer) => {
|
|
10398
|
-
return merge(getDeviceChangeObserver(tracer), getAudioBrowserPermission().asObservable()).pipe(startWith([]), concatMap(() => getDevices(getAudioBrowserPermission(), 'audioinput', tracer)), shareReplay(1));
|
|
10496
|
+
return merge(getDeviceChangeObserver(tracer), getAudioBrowserPermission(tracer).asObservable()).pipe(startWith([]), concatMap(() => getDevices(getAudioBrowserPermission(tracer), 'audioinput', tracer)), shareReplay(1));
|
|
10399
10497
|
});
|
|
10400
10498
|
/**
|
|
10401
10499
|
* Prompts the user for a permission to use video devices (if not already granted
|
|
@@ -10404,7 +10502,7 @@ const getAudioDevices = lazy((tracer) => {
|
|
|
10404
10502
|
* the observable errors.
|
|
10405
10503
|
*/
|
|
10406
10504
|
const getVideoDevices = lazy((tracer) => {
|
|
10407
|
-
return merge(getDeviceChangeObserver(tracer), getVideoBrowserPermission().asObservable()).pipe(startWith([]), concatMap(() => getDevices(getVideoBrowserPermission(), 'videoinput', tracer)), shareReplay(1));
|
|
10505
|
+
return merge(getDeviceChangeObserver(tracer), getVideoBrowserPermission(tracer).asObservable()).pipe(startWith([]), concatMap(() => getDevices(getVideoBrowserPermission(tracer), 'videoinput', tracer)), shareReplay(1));
|
|
10408
10506
|
});
|
|
10409
10507
|
/**
|
|
10410
10508
|
* Prompts the user for a permission to use video devices (if not already granted
|
|
@@ -10413,7 +10511,7 @@ const getVideoDevices = lazy((tracer) => {
|
|
|
10413
10511
|
* the observable errors.
|
|
10414
10512
|
*/
|
|
10415
10513
|
const getAudioOutputDevices = lazy((tracer) => {
|
|
10416
|
-
return merge(getDeviceChangeObserver(tracer), getAudioBrowserPermission().asObservable()).pipe(startWith([]), concatMap(() => getDevices(getAudioBrowserPermission(), 'audiooutput', tracer)), shareReplay(1));
|
|
10514
|
+
return merge(getDeviceChangeObserver(tracer), getAudioBrowserPermission(tracer).asObservable()).pipe(startWith([]), concatMap(() => getDevices(getAudioBrowserPermission(tracer), 'audiooutput', tracer)), shareReplay(1));
|
|
10417
10515
|
});
|
|
10418
10516
|
let getUserMediaExecId = 0;
|
|
10419
10517
|
const getStream = async (constraints, tracer) => {
|
|
@@ -10479,25 +10577,21 @@ const getAudioStream = async (trackConstraints, tracer) => {
|
|
|
10479
10577
|
},
|
|
10480
10578
|
};
|
|
10481
10579
|
try {
|
|
10482
|
-
await getAudioBrowserPermission().prompt({
|
|
10580
|
+
await getAudioBrowserPermission(tracer).prompt({
|
|
10483
10581
|
throwOnNotAllowed: true,
|
|
10484
10582
|
forcePrompt: true,
|
|
10485
10583
|
});
|
|
10486
10584
|
return await getStream(constraints, tracer);
|
|
10487
10585
|
}
|
|
10488
10586
|
catch (error) {
|
|
10587
|
+
const logger = videoLoggerSystem.getLogger('devices');
|
|
10489
10588
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
10490
10589
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10491
10590
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
10492
|
-
|
|
10493
|
-
.getLogger('devices')
|
|
10494
|
-
.warn('Failed to get audio stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
10591
|
+
logger.warn('Failed to get audio stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
10495
10592
|
return getAudioStream(relaxedConstraints, tracer);
|
|
10496
10593
|
}
|
|
10497
|
-
|
|
10498
|
-
error,
|
|
10499
|
-
constraints,
|
|
10500
|
-
});
|
|
10594
|
+
logger.error('Failed to get audio stream', { error, constraints });
|
|
10501
10595
|
throw error;
|
|
10502
10596
|
}
|
|
10503
10597
|
};
|
|
@@ -10517,25 +10611,21 @@ const getVideoStream = async (trackConstraints, tracer) => {
|
|
|
10517
10611
|
},
|
|
10518
10612
|
};
|
|
10519
10613
|
try {
|
|
10520
|
-
await getVideoBrowserPermission().prompt({
|
|
10614
|
+
await getVideoBrowserPermission(tracer).prompt({
|
|
10521
10615
|
throwOnNotAllowed: true,
|
|
10522
10616
|
forcePrompt: true,
|
|
10523
10617
|
});
|
|
10524
10618
|
return await getStream(constraints, tracer);
|
|
10525
10619
|
}
|
|
10526
10620
|
catch (error) {
|
|
10621
|
+
const logger = videoLoggerSystem.getLogger('devices');
|
|
10527
10622
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
10528
10623
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10529
10624
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
10530
|
-
|
|
10531
|
-
|
|
10532
|
-
.warn('Failed to get video stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
10533
|
-
return getVideoStream(relaxedConstraints);
|
|
10625
|
+
logger.warn('Failed to get video stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
10626
|
+
return getVideoStream(relaxedConstraints, tracer);
|
|
10534
10627
|
}
|
|
10535
|
-
|
|
10536
|
-
error,
|
|
10537
|
-
constraints,
|
|
10538
|
-
});
|
|
10628
|
+
logger.error('Failed to get video stream', { error, constraints });
|
|
10539
10629
|
throw error;
|
|
10540
10630
|
}
|
|
10541
10631
|
};
|
|
@@ -11306,8 +11396,8 @@ class DeviceManagerState {
|
|
|
11306
11396
|
}
|
|
11307
11397
|
|
|
11308
11398
|
class CameraManagerState extends DeviceManagerState {
|
|
11309
|
-
constructor() {
|
|
11310
|
-
super('stop-tracks', getVideoBrowserPermission());
|
|
11399
|
+
constructor(tracer) {
|
|
11400
|
+
super('stop-tracks', getVideoBrowserPermission(tracer));
|
|
11311
11401
|
this.directionSubject = new BehaviorSubject(undefined);
|
|
11312
11402
|
/**
|
|
11313
11403
|
* Observable that emits the preferred camera direction
|
|
@@ -11361,7 +11451,7 @@ class CameraManager extends DeviceManager {
|
|
|
11361
11451
|
* @param devicePersistence the device persistence preferences to use.
|
|
11362
11452
|
*/
|
|
11363
11453
|
constructor(call, devicePersistence) {
|
|
11364
|
-
super(call, new CameraManagerState(), TrackType.VIDEO, devicePersistence);
|
|
11454
|
+
super(call, new CameraManagerState(call.tracer), TrackType.VIDEO, devicePersistence);
|
|
11365
11455
|
this.targetResolution = {
|
|
11366
11456
|
width: 1280,
|
|
11367
11457
|
height: 720,
|
|
@@ -11572,8 +11662,8 @@ class AudioDeviceManagerState extends DeviceManagerState {
|
|
|
11572
11662
|
}
|
|
11573
11663
|
|
|
11574
11664
|
class MicrophoneManagerState extends AudioDeviceManagerState {
|
|
11575
|
-
constructor(disableMode) {
|
|
11576
|
-
super(disableMode, getAudioBrowserPermission(), AudioBitrateProfile.VOICE_STANDARD_UNSPECIFIED);
|
|
11665
|
+
constructor(disableMode, tracer) {
|
|
11666
|
+
super(disableMode, getAudioBrowserPermission(tracer), AudioBitrateProfile.VOICE_STANDARD_UNSPECIFIED);
|
|
11577
11667
|
this.speakingWhileMutedSubject = new BehaviorSubject(false);
|
|
11578
11668
|
/**
|
|
11579
11669
|
* An Observable that emits `true` if the user's microphone is muted, but they're speaking.
|
|
@@ -11913,7 +12003,7 @@ class RNSpeechDetector {
|
|
|
11913
12003
|
|
|
11914
12004
|
class MicrophoneManager extends AudioDeviceManager {
|
|
11915
12005
|
constructor(call, devicePersistence, disableMode = 'stop-tracks') {
|
|
11916
|
-
super(call, new MicrophoneManagerState(disableMode), TrackType.AUDIO, devicePersistence);
|
|
12006
|
+
super(call, new MicrophoneManagerState(disableMode, call.tracer), TrackType.AUDIO, devicePersistence);
|
|
11917
12007
|
this.speakingWhileMutedNotificationEnabled = true;
|
|
11918
12008
|
this.soundDetectorConcurrencyTag = Symbol('soundDetectorConcurrencyTag');
|
|
11919
12009
|
this.silenceThresholdMs = 5000;
|
|
@@ -12015,7 +12105,6 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
12015
12105
|
deviceId,
|
|
12016
12106
|
label,
|
|
12017
12107
|
};
|
|
12018
|
-
console.log(event);
|
|
12019
12108
|
this.call.tracer.trace('mic.capture_report', event);
|
|
12020
12109
|
this.call.streamClient.dispatchEvent(event);
|
|
12021
12110
|
},
|
|
@@ -15889,7 +15978,7 @@ class StreamClient {
|
|
|
15889
15978
|
this.getUserAgent = () => {
|
|
15890
15979
|
if (!this.cachedUserAgent) {
|
|
15891
15980
|
const { clientAppIdentifier = {} } = this.options;
|
|
15892
|
-
const { sdkName = 'js', sdkVersion = "1.44.
|
|
15981
|
+
const { sdkName = 'js', sdkVersion = "1.44.5", ...extras } = clientAppIdentifier;
|
|
15893
15982
|
this.cachedUserAgent = [
|
|
15894
15983
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
15895
15984
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|