@stream-io/video-client 1.46.0 → 1.47.0
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 +18 -0
- package/dist/index.browser.es.js +65 -21
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +65 -21
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +65 -21
- package/dist/index.es.js.map +1 -1
- package/dist/src/gen/coordinator/index.d.ts +6 -0
- package/dist/src/helpers/RNSpeechDetector.d.ts +4 -2
- package/package.json +1 -1
- package/src/devices/CameraManager.ts +9 -2
- package/src/devices/DeviceManager.ts +13 -3
- package/src/devices/MicrophoneManager.ts +8 -1
- package/src/devices/SpeakerManager.ts +16 -4
- package/src/devices/__tests__/CameraManager.test.ts +32 -0
- package/src/devices/__tests__/DeviceManager.test.ts +71 -0
- package/src/devices/__tests__/MicrophoneManager.test.ts +23 -0
- package/src/devices/__tests__/SpeakerManager.test.ts +28 -0
- package/src/gen/coordinator/index.ts +6 -0
- package/src/helpers/RNSpeechDetector.ts +52 -16
- package/src/helpers/__tests__/RNSpeechDetector.test.ts +52 -0
package/dist/index.cjs.js
CHANGED
|
@@ -6304,7 +6304,7 @@ const getSdkVersion = (sdk) => {
|
|
|
6304
6304
|
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
6305
6305
|
};
|
|
6306
6306
|
|
|
6307
|
-
const version = "1.
|
|
6307
|
+
const version = "1.47.0";
|
|
6308
6308
|
const [major, minor, patch] = version.split('.');
|
|
6309
6309
|
let sdkInfo = {
|
|
6310
6310
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -10885,8 +10885,14 @@ class DeviceManager {
|
|
|
10885
10885
|
this.handleDisconnectedOrReplacedDevices();
|
|
10886
10886
|
}
|
|
10887
10887
|
if (this.devicePersistence.enabled) {
|
|
10888
|
-
this.subscriptions.push(createSubscription(rxjs.combineLatest([
|
|
10889
|
-
|
|
10888
|
+
this.subscriptions.push(createSubscription(rxjs.combineLatest([
|
|
10889
|
+
this.state.selectedDevice$,
|
|
10890
|
+
this.state.status$,
|
|
10891
|
+
this.state.browserPermissionState$,
|
|
10892
|
+
]), ([selectedDevice, status, browserPermissionState]) => {
|
|
10893
|
+
if (!status ||
|
|
10894
|
+
(this.isTrackStoppedDueToTrackEnd && status === 'disabled') ||
|
|
10895
|
+
browserPermissionState !== 'granted')
|
|
10890
10896
|
return;
|
|
10891
10897
|
this.persistPreference(selectedDevice, status);
|
|
10892
10898
|
}));
|
|
@@ -11651,7 +11657,10 @@ class CameraManager extends DeviceManager {
|
|
|
11651
11657
|
const shouldApplyDefaults = this.state.status === undefined &&
|
|
11652
11658
|
this.state.optimisticStatus === undefined;
|
|
11653
11659
|
let persistedPreferencesApplied = false;
|
|
11654
|
-
|
|
11660
|
+
const permissionState = await rxjs.firstValueFrom(this.state.browserPermissionState$);
|
|
11661
|
+
if (shouldApplyDefaults &&
|
|
11662
|
+
this.devicePersistence.enabled &&
|
|
11663
|
+
permissionState === 'granted') {
|
|
11655
11664
|
persistedPreferencesApplied =
|
|
11656
11665
|
await this.applyPersistedPreferences(enabledInCallType);
|
|
11657
11666
|
}
|
|
@@ -11947,35 +11956,43 @@ class RNSpeechDetector {
|
|
|
11947
11956
|
constructor(externalAudioStream) {
|
|
11948
11957
|
this.pc1 = new RTCPeerConnection({});
|
|
11949
11958
|
this.pc2 = new RTCPeerConnection({});
|
|
11959
|
+
this.isStopped = false;
|
|
11950
11960
|
this.externalAudioStream = externalAudioStream;
|
|
11951
11961
|
}
|
|
11952
11962
|
/**
|
|
11953
11963
|
* Starts the speech detection.
|
|
11954
11964
|
*/
|
|
11955
11965
|
async start(onSoundDetectedStateChanged) {
|
|
11966
|
+
let detachListeners;
|
|
11967
|
+
let unsubscribe;
|
|
11956
11968
|
try {
|
|
11969
|
+
this.isStopped = false;
|
|
11957
11970
|
const audioStream = this.externalAudioStream != null
|
|
11958
11971
|
? this.externalAudioStream
|
|
11959
11972
|
: await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
11960
11973
|
this.audioStream = audioStream;
|
|
11961
|
-
|
|
11962
|
-
this.pc2
|
|
11963
|
-
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
// do nothing
|
|
11969
|
-
});
|
|
11970
|
-
});
|
|
11971
|
-
this.pc2.addEventListener('track', (e) => {
|
|
11974
|
+
const onPc1IceCandidate = (e) => {
|
|
11975
|
+
this.forwardIceCandidate(this.pc2, e.candidate);
|
|
11976
|
+
};
|
|
11977
|
+
const onPc2IceCandidate = (e) => {
|
|
11978
|
+
this.forwardIceCandidate(this.pc1, e.candidate);
|
|
11979
|
+
};
|
|
11980
|
+
const onTrackPc2 = (e) => {
|
|
11972
11981
|
e.streams[0].getTracks().forEach((track) => {
|
|
11973
11982
|
// In RN, the remote track is automatically added to the audio output device
|
|
11974
11983
|
// so we need to mute it to avoid hearing the audio back
|
|
11975
11984
|
// @ts-expect-error _setVolume is a private method in react-native-webrtc
|
|
11976
11985
|
track._setVolume(0);
|
|
11977
11986
|
});
|
|
11978
|
-
}
|
|
11987
|
+
};
|
|
11988
|
+
this.pc1.addEventListener('icecandidate', onPc1IceCandidate);
|
|
11989
|
+
this.pc2.addEventListener('icecandidate', onPc2IceCandidate);
|
|
11990
|
+
this.pc2.addEventListener('track', onTrackPc2);
|
|
11991
|
+
detachListeners = () => {
|
|
11992
|
+
this.pc1.removeEventListener('icecandidate', onPc1IceCandidate);
|
|
11993
|
+
this.pc2.removeEventListener('icecandidate', onPc2IceCandidate);
|
|
11994
|
+
this.pc2.removeEventListener('track', onTrackPc2);
|
|
11995
|
+
};
|
|
11979
11996
|
audioStream
|
|
11980
11997
|
.getTracks()
|
|
11981
11998
|
.forEach((track) => this.pc1.addTrack(track, audioStream));
|
|
@@ -11985,13 +12002,17 @@ class RNSpeechDetector {
|
|
|
11985
12002
|
const answer = await this.pc2.createAnswer();
|
|
11986
12003
|
await this.pc1.setRemoteDescription(answer);
|
|
11987
12004
|
await this.pc2.setLocalDescription(answer);
|
|
11988
|
-
|
|
12005
|
+
unsubscribe = this.onSpeakingDetectedStateChange(onSoundDetectedStateChanged);
|
|
11989
12006
|
return () => {
|
|
11990
|
-
|
|
12007
|
+
detachListeners?.();
|
|
12008
|
+
unsubscribe?.();
|
|
11991
12009
|
this.stop();
|
|
11992
12010
|
};
|
|
11993
12011
|
}
|
|
11994
12012
|
catch (error) {
|
|
12013
|
+
detachListeners?.();
|
|
12014
|
+
unsubscribe?.();
|
|
12015
|
+
this.stop();
|
|
11995
12016
|
const logger = videoLoggerSystem.getLogger('RNSpeechDetector');
|
|
11996
12017
|
logger.error('error handling permissions: ', error);
|
|
11997
12018
|
return () => { };
|
|
@@ -12001,6 +12022,9 @@ class RNSpeechDetector {
|
|
|
12001
12022
|
* Stops the speech detection and releases all allocated resources.
|
|
12002
12023
|
*/
|
|
12003
12024
|
stop() {
|
|
12025
|
+
if (this.isStopped)
|
|
12026
|
+
return;
|
|
12027
|
+
this.isStopped = true;
|
|
12004
12028
|
this.pc1.close();
|
|
12005
12029
|
this.pc2.close();
|
|
12006
12030
|
if (this.externalAudioStream != null) {
|
|
@@ -12100,6 +12124,18 @@ class RNSpeechDetector {
|
|
|
12100
12124
|
this.audioStream.release();
|
|
12101
12125
|
}
|
|
12102
12126
|
}
|
|
12127
|
+
forwardIceCandidate(destination, candidate) {
|
|
12128
|
+
if (this.isStopped ||
|
|
12129
|
+
!candidate ||
|
|
12130
|
+
destination.signalingState === 'closed') {
|
|
12131
|
+
return;
|
|
12132
|
+
}
|
|
12133
|
+
destination.addIceCandidate(candidate).catch(() => {
|
|
12134
|
+
// silently ignore the error
|
|
12135
|
+
const logger = videoLoggerSystem.getLogger('RNSpeechDetector');
|
|
12136
|
+
logger.info('cannot add ice candidate - ignoring');
|
|
12137
|
+
});
|
|
12138
|
+
}
|
|
12103
12139
|
}
|
|
12104
12140
|
|
|
12105
12141
|
class MicrophoneManager extends AudioDeviceManager {
|
|
@@ -12366,7 +12402,10 @@ class MicrophoneManager extends AudioDeviceManager {
|
|
|
12366
12402
|
const shouldApplyDefaults = this.state.status === undefined &&
|
|
12367
12403
|
this.state.optimisticStatus === undefined;
|
|
12368
12404
|
let persistedPreferencesApplied = false;
|
|
12369
|
-
|
|
12405
|
+
const permissionState = await rxjs.firstValueFrom(this.state.browserPermissionState$);
|
|
12406
|
+
if (shouldApplyDefaults &&
|
|
12407
|
+
this.devicePersistence.enabled &&
|
|
12408
|
+
permissionState === 'granted') {
|
|
12370
12409
|
persistedPreferencesApplied = await this.applyPersistedPreferences(true);
|
|
12371
12410
|
}
|
|
12372
12411
|
const canPublish = this.call.permissionsContext.canPublish(this.trackType);
|
|
@@ -12750,7 +12789,12 @@ class SpeakerManager {
|
|
|
12750
12789
|
}));
|
|
12751
12790
|
}
|
|
12752
12791
|
if (!isReactNative() && this.devicePersistence.enabled) {
|
|
12753
|
-
this.subscriptions.push(createSubscription(
|
|
12792
|
+
this.subscriptions.push(createSubscription(rxjs.combineLatest([
|
|
12793
|
+
this.state.selectedDevice$,
|
|
12794
|
+
getAudioBrowserPermission(this.call.tracer).asStateObservable(),
|
|
12795
|
+
]), ([selectedDevice, browserPermissionState]) => {
|
|
12796
|
+
if (!selectedDevice || browserPermissionState !== 'granted')
|
|
12797
|
+
return;
|
|
12754
12798
|
this.persistSpeakerDevicePreference(selectedDevice);
|
|
12755
12799
|
}));
|
|
12756
12800
|
}
|
|
@@ -16125,7 +16169,7 @@ class StreamClient {
|
|
|
16125
16169
|
this.getUserAgent = () => {
|
|
16126
16170
|
if (!this.cachedUserAgent) {
|
|
16127
16171
|
const { clientAppIdentifier = {} } = this.options;
|
|
16128
|
-
const { sdkName = 'js', sdkVersion = "1.
|
|
16172
|
+
const { sdkName = 'js', sdkVersion = "1.47.0", ...extras } = clientAppIdentifier;
|
|
16129
16173
|
this.cachedUserAgent = [
|
|
16130
16174
|
`stream-video-${sdkName}-v${sdkVersion}`,
|
|
16131
16175
|
...Object.entries(extras).map(([key, value]) => `${key}=${value}`),
|