@stream-io/video-client 1.44.2 → 1.44.4
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 +34 -33
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +34 -33
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +34 -33
- package/dist/index.es.js.map +1 -1
- package/dist/src/StreamSfuClient.d.ts +1 -0
- 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/package.json +2 -2
- package/src/StreamSfuClient.ts +15 -9
- 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 +25 -31
- package/src/rpc/retryable.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [1.44.4](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.44.3...@stream-io/video-client-1.44.4) (2026-03-20)
|
|
6
|
+
|
|
7
|
+
- trace device permission state transitions ([#2168](https://github.com/GetStream/stream-video-js/issues/2168)) ([e4203a3](https://github.com/GetStream/stream-video-js/commit/e4203a34cad1c90d1bc5612fc379dd1f0f0ebe5d))
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **react:** remove default broken microphone notification from call controls ([#2158](https://github.com/GetStream/stream-video-js/issues/2158)) ([4a95b9c](https://github.com/GetStream/stream-video-js/commit/4a95b9c29e9d2728ae7eea764f07ec8507aa0f5a))
|
|
12
|
+
|
|
13
|
+
## [1.44.3](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.44.2...@stream-io/video-client-1.44.3) (2026-03-06)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
- **client:** prevent concurrent SFU updateSubscriptions during reconnects ([#2155](https://github.com/GetStream/stream-video-js/issues/2155)) ([1ac32d2](https://github.com/GetStream/stream-video-js/commit/1ac32d261c9a54aa8e3636a60e3c8f3e1407ae16))
|
|
18
|
+
|
|
5
19
|
## [1.44.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.44.1...@stream-io/video-client-1.44.2) (2026-03-06)
|
|
6
20
|
|
|
7
21
|
### Bug Fixes
|
package/dist/index.browser.es.js
CHANGED
|
@@ -4005,6 +4005,8 @@ const retryable = async (rpc, signal, maxRetries = Number.POSITIVE_INFINITY) =>
|
|
|
4005
4005
|
do {
|
|
4006
4006
|
if (attempt > 0)
|
|
4007
4007
|
await sleep(retryInterval(attempt));
|
|
4008
|
+
if (signal?.aborted)
|
|
4009
|
+
throw new Error(signal.reason);
|
|
4008
4010
|
try {
|
|
4009
4011
|
result = await rpc({ attempt });
|
|
4010
4012
|
}
|
|
@@ -6281,7 +6283,7 @@ const getSdkVersion = (sdk) => {
|
|
|
6281
6283
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
6282
6284
|
};
|
|
6283
6285
|
|
|
6284
|
-
const version = "1.44.
|
|
6286
|
+
const version = "1.44.4";
|
|
6285
6287
|
const [major, minor, patch] = version.split('.');
|
|
6286
6288
|
let sdkInfo = {
|
|
6287
6289
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -8582,6 +8584,7 @@ class StreamSfuClient {
|
|
|
8582
8584
|
this.isClosingClean = false;
|
|
8583
8585
|
this.pingIntervalInMs = 5 * 1000;
|
|
8584
8586
|
this.unhealthyTimeoutInMs = 15 * 1000;
|
|
8587
|
+
this.subscriptionsConcurrencyTag = Symbol('subscriptionsConcurrencyTag');
|
|
8585
8588
|
/**
|
|
8586
8589
|
* Promise that resolves when the JoinResponse is received.
|
|
8587
8590
|
* Rejects after a certain threshold if the response is not received.
|
|
@@ -8689,8 +8692,10 @@ class StreamSfuClient {
|
|
|
8689
8692
|
this.close(StreamSfuClient.NORMAL_CLOSURE, reason.substring(0, 115));
|
|
8690
8693
|
};
|
|
8691
8694
|
this.updateSubscriptions = async (tracks) => {
|
|
8692
|
-
|
|
8693
|
-
|
|
8695
|
+
return withoutConcurrency(this.subscriptionsConcurrencyTag, async () => {
|
|
8696
|
+
await this.joinTask;
|
|
8697
|
+
return retryable((invocationMeta) => this.rpc.updateSubscriptions({ sessionId: this.sessionId, tracks }, { invocationMeta }), this.abortController.signal);
|
|
8698
|
+
});
|
|
8694
8699
|
};
|
|
8695
8700
|
this.setPublisher = async (data) => {
|
|
8696
8701
|
await this.joinTask;
|
|
@@ -10293,6 +10298,9 @@ class BrowserPermission {
|
|
|
10293
10298
|
}
|
|
10294
10299
|
setState(state) {
|
|
10295
10300
|
if (this.state !== state) {
|
|
10301
|
+
const { tracer, queryName } = this.permission;
|
|
10302
|
+
const traceKey = `navigator.mediaDevices.${queryName}.permission`;
|
|
10303
|
+
tracer?.trace(traceKey, { previous: this.state, state });
|
|
10296
10304
|
this.state = state;
|
|
10297
10305
|
this.listeners.forEach((listener) => listener(state));
|
|
10298
10306
|
}
|
|
@@ -10363,17 +10371,19 @@ const videoDeviceConstraints = {
|
|
|
10363
10371
|
* Keeps track of the browser permission to use microphone. This permission also
|
|
10364
10372
|
* affects an ability to enumerate audio devices.
|
|
10365
10373
|
*/
|
|
10366
|
-
const getAudioBrowserPermission = lazy(() => new BrowserPermission({
|
|
10374
|
+
const getAudioBrowserPermission = lazy((tracer) => new BrowserPermission({
|
|
10367
10375
|
constraints: audioDeviceConstraints,
|
|
10368
10376
|
queryName: 'microphone',
|
|
10377
|
+
tracer,
|
|
10369
10378
|
}));
|
|
10370
10379
|
/**
|
|
10371
10380
|
* Keeps track of the browser permission to use camera. This permission also
|
|
10372
10381
|
* affects an ability to enumerate video devices.
|
|
10373
10382
|
*/
|
|
10374
|
-
const getVideoBrowserPermission = lazy(() => new BrowserPermission({
|
|
10383
|
+
const getVideoBrowserPermission = lazy((tracer) => new BrowserPermission({
|
|
10375
10384
|
constraints: videoDeviceConstraints,
|
|
10376
10385
|
queryName: 'camera',
|
|
10386
|
+
tracer,
|
|
10377
10387
|
}));
|
|
10378
10388
|
const getDeviceChangeObserver = lazy((tracer) => {
|
|
10379
10389
|
// 'addEventListener' is not available in React Native, returning
|
|
@@ -10389,7 +10399,7 @@ const getDeviceChangeObserver = lazy((tracer) => {
|
|
|
10389
10399
|
* the observable errors.
|
|
10390
10400
|
*/
|
|
10391
10401
|
const getAudioDevices = lazy((tracer) => {
|
|
10392
|
-
return merge(getDeviceChangeObserver(tracer), getAudioBrowserPermission().asObservable()).pipe(startWith([]), concatMap(() => getDevices(getAudioBrowserPermission(), 'audioinput', tracer)), shareReplay(1));
|
|
10402
|
+
return merge(getDeviceChangeObserver(tracer), getAudioBrowserPermission(tracer).asObservable()).pipe(startWith([]), concatMap(() => getDevices(getAudioBrowserPermission(tracer), 'audioinput', tracer)), shareReplay(1));
|
|
10393
10403
|
});
|
|
10394
10404
|
/**
|
|
10395
10405
|
* Prompts the user for a permission to use video devices (if not already granted
|
|
@@ -10398,7 +10408,7 @@ const getAudioDevices = lazy((tracer) => {
|
|
|
10398
10408
|
* the observable errors.
|
|
10399
10409
|
*/
|
|
10400
10410
|
const getVideoDevices = lazy((tracer) => {
|
|
10401
|
-
return merge(getDeviceChangeObserver(tracer), getVideoBrowserPermission().asObservable()).pipe(startWith([]), concatMap(() => getDevices(getVideoBrowserPermission(), 'videoinput', tracer)), shareReplay(1));
|
|
10411
|
+
return merge(getDeviceChangeObserver(tracer), getVideoBrowserPermission(tracer).asObservable()).pipe(startWith([]), concatMap(() => getDevices(getVideoBrowserPermission(tracer), 'videoinput', tracer)), shareReplay(1));
|
|
10402
10412
|
});
|
|
10403
10413
|
/**
|
|
10404
10414
|
* Prompts the user for a permission to use video devices (if not already granted
|
|
@@ -10407,7 +10417,7 @@ const getVideoDevices = lazy((tracer) => {
|
|
|
10407
10417
|
* the observable errors.
|
|
10408
10418
|
*/
|
|
10409
10419
|
const getAudioOutputDevices = lazy((tracer) => {
|
|
10410
|
-
return merge(getDeviceChangeObserver(tracer), getAudioBrowserPermission().asObservable()).pipe(startWith([]), concatMap(() => getDevices(getAudioBrowserPermission(), 'audiooutput', tracer)), shareReplay(1));
|
|
10420
|
+
return merge(getDeviceChangeObserver(tracer), getAudioBrowserPermission(tracer).asObservable()).pipe(startWith([]), concatMap(() => getDevices(getAudioBrowserPermission(tracer), 'audiooutput', tracer)), shareReplay(1));
|
|
10411
10421
|
});
|
|
10412
10422
|
let getUserMediaExecId = 0;
|
|
10413
10423
|
const getStream = async (constraints, tracer) => {
|
|
@@ -10473,25 +10483,21 @@ const getAudioStream = async (trackConstraints, tracer) => {
|
|
|
10473
10483
|
},
|
|
10474
10484
|
};
|
|
10475
10485
|
try {
|
|
10476
|
-
await getAudioBrowserPermission().prompt({
|
|
10486
|
+
await getAudioBrowserPermission(tracer).prompt({
|
|
10477
10487
|
throwOnNotAllowed: true,
|
|
10478
10488
|
forcePrompt: true,
|
|
10479
10489
|
});
|
|
10480
10490
|
return await getStream(constraints, tracer);
|
|
10481
10491
|
}
|
|
10482
10492
|
catch (error) {
|
|
10493
|
+
const logger = videoLoggerSystem.getLogger('devices');
|
|
10483
10494
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
10484
10495
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10485
10496
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
10486
|
-
|
|
10487
|
-
.getLogger('devices')
|
|
10488
|
-
.warn('Failed to get audio stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
10497
|
+
logger.warn('Failed to get audio stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
10489
10498
|
return getAudioStream(relaxedConstraints, tracer);
|
|
10490
10499
|
}
|
|
10491
|
-
|
|
10492
|
-
error,
|
|
10493
|
-
constraints,
|
|
10494
|
-
});
|
|
10500
|
+
logger.error('Failed to get audio stream', { error, constraints });
|
|
10495
10501
|
throw error;
|
|
10496
10502
|
}
|
|
10497
10503
|
};
|
|
@@ -10511,25 +10517,21 @@ const getVideoStream = async (trackConstraints, tracer) => {
|
|
|
10511
10517
|
},
|
|
10512
10518
|
};
|
|
10513
10519
|
try {
|
|
10514
|
-
await getVideoBrowserPermission().prompt({
|
|
10520
|
+
await getVideoBrowserPermission(tracer).prompt({
|
|
10515
10521
|
throwOnNotAllowed: true,
|
|
10516
10522
|
forcePrompt: true,
|
|
10517
10523
|
});
|
|
10518
10524
|
return await getStream(constraints, tracer);
|
|
10519
10525
|
}
|
|
10520
10526
|
catch (error) {
|
|
10527
|
+
const logger = videoLoggerSystem.getLogger('devices');
|
|
10521
10528
|
if (isNotFoundOrOverconstrainedError(error) && trackConstraints?.deviceId) {
|
|
10522
10529
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10523
10530
|
const { deviceId, ...relaxedConstraints } = trackConstraints;
|
|
10524
|
-
|
|
10525
|
-
|
|
10526
|
-
.warn('Failed to get video stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
10527
|
-
return getVideoStream(relaxedConstraints);
|
|
10531
|
+
logger.warn('Failed to get video stream, will try again with relaxed constraints', { error, constraints, relaxedConstraints });
|
|
10532
|
+
return getVideoStream(relaxedConstraints, tracer);
|
|
10528
10533
|
}
|
|
10529
|
-
|
|
10530
|
-
error,
|
|
10531
|
-
constraints,
|
|
10532
|
-
});
|
|
10534
|
+
logger.error('Failed to get video stream', { error, constraints });
|
|
10533
10535
|
throw error;
|
|
10534
10536
|
}
|
|
10535
10537
|
};
|
|
@@ -11300,8 +11302,8 @@ class DeviceManagerState {
|
|
|
11300
11302
|
}
|
|
11301
11303
|
|
|
11302
11304
|
class CameraManagerState extends DeviceManagerState {
|
|
11303
|
-
constructor() {
|
|
11304
|
-
super('stop-tracks', getVideoBrowserPermission());
|
|
11305
|
+
constructor(tracer) {
|
|
11306
|
+
super('stop-tracks', getVideoBrowserPermission(tracer));
|
|
11305
11307
|
this.directionSubject = new BehaviorSubject(undefined);
|
|
11306
11308
|
/**
|
|
11307
11309
|
* Observable that emits the preferred camera direction
|
|
@@ -11355,7 +11357,7 @@ class CameraManager extends DeviceManager {
|
|
|
11355
11357
|
* @param devicePersistence the device persistence preferences to use.
|
|
11356
11358
|
*/
|
|
11357
11359
|
constructor(call, devicePersistence) {
|
|
11358
|
-
super(call, new CameraManagerState(), TrackType.VIDEO, devicePersistence);
|
|
11360
|
+
super(call, new CameraManagerState(call.tracer), TrackType.VIDEO, devicePersistence);
|
|
11359
11361
|
this.targetResolution = {
|
|
11360
11362
|
width: 1280,
|
|
11361
11363
|
height: 720,
|
|
@@ -11566,8 +11568,8 @@ class AudioDeviceManagerState extends DeviceManagerState {
|
|
|
11566
11568
|
}
|
|
11567
11569
|
|
|
11568
11570
|
class MicrophoneManagerState extends AudioDeviceManagerState {
|
|
11569
|
-
constructor(disableMode) {
|
|
11570
|
-
super(disableMode, getAudioBrowserPermission(), AudioBitrateProfile.VOICE_STANDARD_UNSPECIFIED);
|
|
11571
|
+
constructor(disableMode, tracer) {
|
|
11572
|
+
super(disableMode, getAudioBrowserPermission(tracer), AudioBitrateProfile.VOICE_STANDARD_UNSPECIFIED);
|
|
11571
11573
|
this.speakingWhileMutedSubject = new BehaviorSubject(false);
|
|
11572
11574
|
/**
|
|
11573
11575
|
* An Observable that emits `true` if the user's microphone is muted, but they're speaking.
|
|
@@ -11907,7 +11909,7 @@ class RNSpeechDetector {
|
|
|
11907
11909
|
|
|
11908
11910
|
class MicrophoneManager extends AudioDeviceManager {
|
|
11909
11911
|
constructor(call, devicePersistence, disableMode = 'stop-tracks') {
|
|
11910
|
-
super(call, new MicrophoneManagerState(disableMode), TrackType.AUDIO, devicePersistence);
|
|
11912
|
+
super(call, new MicrophoneManagerState(disableMode, call.tracer), TrackType.AUDIO, devicePersistence);
|
|
11911
11913
|
this.speakingWhileMutedNotificationEnabled = true;
|
|
11912
11914
|
this.soundDetectorConcurrencyTag = Symbol('soundDetectorConcurrencyTag');
|
|
11913
11915
|
this.silenceThresholdMs = 5000;
|
|
@@ -12009,7 +12011,6 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
12009
12011
|
deviceId,
|
|
12010
12012
|
label,
|
|
12011
12013
|
};
|
|
12012
|
-
console.log(event);
|
|
12013
12014
|
this.call.tracer.trace('mic.capture_report', event);
|
|
12014
12015
|
this.call.streamClient.dispatchEvent(event);
|
|
12015
12016
|
},
|
|
@@ -15885,7 +15886,7 @@ class StreamClient {
|
|
|
15885
15886
|
this.getUserAgent = () => {
|
|
15886
15887
|
if (!this.cachedUserAgent) {
|
|
15887
15888
|
const { clientAppIdentifier = {} } = this.options;
|
|
15888
|
-
const { sdkName = 'js', sdkVersion = "1.44.
|
|
15889
|
+
const { sdkName = 'js', sdkVersion = "1.44.4", ...extras } = clientAppIdentifier;
|
|
15889
15890
|
this.cachedUserAgent = [
|
|
15890
15891
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
15891
15892
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|