@stream-io/video-client 0.7.10 → 0.7.11
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 +7 -0
- package/dist/index.browser.es.js +58 -41
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +58 -41
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +58 -41
- package/dist/index.es.js.map +1 -1
- package/dist/src/devices/CameraManagerState.d.ts +1 -1
- package/dist/src/devices/InputMediaDeviceManagerState.d.ts +8 -3
- package/dist/src/devices/MicrophoneManager.d.ts +11 -1
- package/dist/src/devices/MicrophoneManagerState.d.ts +2 -2
- package/package.json +1 -1
- package/src/devices/CameraManagerState.ts +7 -5
- package/src/devices/InputMediaDeviceManager.ts +7 -3
- package/src/devices/InputMediaDeviceManagerState.ts +12 -6
- package/src/devices/MicrophoneManager.ts +56 -28
- package/src/devices/MicrophoneManagerState.ts +8 -6
- package/src/devices/__tests__/MicrophoneManager.test.ts +66 -42
- package/src/helpers/RNSpeechDetector.ts +1 -13
package/dist/index.es.js
CHANGED
|
@@ -9514,7 +9514,7 @@ const toRtcConfiguration = (config) => {
|
|
|
9514
9514
|
*
|
|
9515
9515
|
* @param report the report to flatten.
|
|
9516
9516
|
*/
|
|
9517
|
-
const flatten
|
|
9517
|
+
const flatten = (report) => {
|
|
9518
9518
|
const stats = [];
|
|
9519
9519
|
report.forEach((s) => {
|
|
9520
9520
|
stats.push(s);
|
|
@@ -9668,7 +9668,7 @@ const createStatsReporter = ({ subscriber, publisher, state, pollingIntervalInMs
|
|
|
9668
9668
|
const transform = (report, opts) => {
|
|
9669
9669
|
const { trackKind, kind } = opts;
|
|
9670
9670
|
const direction = kind === 'subscriber' ? 'inbound-rtp' : 'outbound-rtp';
|
|
9671
|
-
const stats = flatten
|
|
9671
|
+
const stats = flatten(report);
|
|
9672
9672
|
const streams = stats
|
|
9673
9673
|
.filter((stat) => stat.type === direction &&
|
|
9674
9674
|
stat.kind === trackKind)
|
|
@@ -9764,8 +9764,8 @@ class SfuStatsReporter {
|
|
|
9764
9764
|
this.logger = getLogger(['SfuStatsReporter']);
|
|
9765
9765
|
this.run = async () => {
|
|
9766
9766
|
const [subscriberStats, publisherStats] = await Promise.all([
|
|
9767
|
-
this.subscriber.getStats().then(flatten
|
|
9768
|
-
this.publisher.getStats().then(flatten
|
|
9767
|
+
this.subscriber.getStats().then(flatten).then(JSON.stringify),
|
|
9768
|
+
this.publisher.getStats().then(flatten).then(JSON.stringify),
|
|
9769
9769
|
]);
|
|
9770
9770
|
await this.sfuClient.sendStats({
|
|
9771
9771
|
sdk: this.sdkName,
|
|
@@ -10738,7 +10738,7 @@ class InputMediaDeviceManager {
|
|
|
10738
10738
|
// @ts-expect-error called to dispose the stream in RN
|
|
10739
10739
|
this.state.mediaStream.release();
|
|
10740
10740
|
}
|
|
10741
|
-
this.state.setMediaStream(undefined);
|
|
10741
|
+
this.state.setMediaStream(undefined, undefined);
|
|
10742
10742
|
}
|
|
10743
10743
|
}
|
|
10744
10744
|
muteTracks() {
|
|
@@ -10773,6 +10773,7 @@ class InputMediaDeviceManager {
|
|
|
10773
10773
|
async unmuteStream() {
|
|
10774
10774
|
this.logger('debug', 'Starting stream');
|
|
10775
10775
|
let stream;
|
|
10776
|
+
let rootStream;
|
|
10776
10777
|
if (this.state.mediaStream &&
|
|
10777
10778
|
this.getTracks().every((t) => t.readyState === 'live')) {
|
|
10778
10779
|
stream = this.state.mediaStream;
|
|
@@ -10838,14 +10839,17 @@ class InputMediaDeviceManager {
|
|
|
10838
10839
|
});
|
|
10839
10840
|
return filterStream;
|
|
10840
10841
|
};
|
|
10842
|
+
// the rootStream represents the stream coming from the actual device
|
|
10843
|
+
// e.g. camera or microphone stream
|
|
10844
|
+
rootStream = this.getStream(constraints);
|
|
10841
10845
|
// we publish the last MediaStream of the chain
|
|
10842
|
-
stream = await this.filters.reduce((parent, filter) => parent.then(filter).then(chainWith(parent)),
|
|
10846
|
+
stream = await this.filters.reduce((parent, filter) => parent.then(filter).then(chainWith(parent)), rootStream);
|
|
10843
10847
|
}
|
|
10844
10848
|
if (this.call.state.callingState === CallingState.JOINED) {
|
|
10845
10849
|
await this.publishStream(stream);
|
|
10846
10850
|
}
|
|
10847
10851
|
if (this.state.mediaStream !== stream) {
|
|
10848
|
-
this.state.setMediaStream(stream);
|
|
10852
|
+
this.state.setMediaStream(stream, await rootStream);
|
|
10849
10853
|
this.getTracks().forEach((track) => {
|
|
10850
10854
|
track.addEventListener('ended', async () => {
|
|
10851
10855
|
if (this.enablePromise) {
|
|
@@ -11039,13 +11043,17 @@ class InputMediaDeviceManagerState {
|
|
|
11039
11043
|
this.setCurrentValue(this.statusSubject, status);
|
|
11040
11044
|
}
|
|
11041
11045
|
/**
|
|
11046
|
+
* Updates the `mediaStream` state variable.
|
|
11047
|
+
*
|
|
11042
11048
|
* @internal
|
|
11043
11049
|
* @param stream the stream to set.
|
|
11050
|
+
* @param rootStream the root stream, applicable when filters are used
|
|
11051
|
+
* as this is the stream that holds the actual deviceId information.
|
|
11044
11052
|
*/
|
|
11045
|
-
setMediaStream(stream) {
|
|
11053
|
+
setMediaStream(stream, rootStream) {
|
|
11046
11054
|
this.setCurrentValue(this.mediaStreamSubject, stream);
|
|
11047
|
-
if (
|
|
11048
|
-
this.setDevice(this.getDeviceIdFromStream(
|
|
11055
|
+
if (rootStream) {
|
|
11056
|
+
this.setDevice(this.getDeviceIdFromStream(rootStream));
|
|
11049
11057
|
}
|
|
11050
11058
|
}
|
|
11051
11059
|
/**
|
|
@@ -11100,8 +11108,8 @@ class CameraManagerState extends InputMediaDeviceManagerState {
|
|
|
11100
11108
|
/**
|
|
11101
11109
|
* @internal
|
|
11102
11110
|
*/
|
|
11103
|
-
setMediaStream(stream) {
|
|
11104
|
-
super.setMediaStream(stream);
|
|
11111
|
+
setMediaStream(stream, rootStream) {
|
|
11112
|
+
super.setMediaStream(stream, rootStream);
|
|
11105
11113
|
if (stream) {
|
|
11106
11114
|
// RN getSettings() doesn't return facingMode, so we don't verify camera direction
|
|
11107
11115
|
const direction = isReactNative()
|
|
@@ -11113,7 +11121,8 @@ class CameraManagerState extends InputMediaDeviceManagerState {
|
|
|
11113
11121
|
}
|
|
11114
11122
|
}
|
|
11115
11123
|
getDeviceIdFromStream(stream) {
|
|
11116
|
-
|
|
11124
|
+
const [track] = stream.getVideoTracks();
|
|
11125
|
+
return track?.getSettings().deviceId;
|
|
11117
11126
|
}
|
|
11118
11127
|
}
|
|
11119
11128
|
|
|
@@ -11206,8 +11215,8 @@ class CameraManager extends InputMediaDeviceManager {
|
|
|
11206
11215
|
}
|
|
11207
11216
|
|
|
11208
11217
|
class MicrophoneManagerState extends InputMediaDeviceManagerState {
|
|
11209
|
-
constructor() {
|
|
11210
|
-
super(
|
|
11218
|
+
constructor(disableMode) {
|
|
11219
|
+
super(disableMode,
|
|
11211
11220
|
// `microphone` is not in the W3C standard yet,
|
|
11212
11221
|
// but it's supported by Chrome and Safari.
|
|
11213
11222
|
'microphone');
|
|
@@ -11231,7 +11240,8 @@ class MicrophoneManagerState extends InputMediaDeviceManagerState {
|
|
|
11231
11240
|
this.setCurrentValue(this.speakingWhileMutedSubject, isSpeaking);
|
|
11232
11241
|
}
|
|
11233
11242
|
getDeviceIdFromStream(stream) {
|
|
11234
|
-
|
|
11243
|
+
const [track] = stream.getAudioTracks();
|
|
11244
|
+
return track?.getSettings().deviceId;
|
|
11235
11245
|
}
|
|
11236
11246
|
}
|
|
11237
11247
|
|
|
@@ -11288,18 +11298,6 @@ const createSoundDetector = (audioStream, onSoundDetectedStateChanged, options =
|
|
|
11288
11298
|
};
|
|
11289
11299
|
};
|
|
11290
11300
|
|
|
11291
|
-
/**
|
|
11292
|
-
* Flatten the stats report into an array of stats objects.
|
|
11293
|
-
*
|
|
11294
|
-
* @param report the report to flatten.
|
|
11295
|
-
*/
|
|
11296
|
-
const flatten = (report) => {
|
|
11297
|
-
const stats = [];
|
|
11298
|
-
report.forEach((s) => {
|
|
11299
|
-
stats.push(s);
|
|
11300
|
-
});
|
|
11301
|
-
return stats;
|
|
11302
|
-
};
|
|
11303
11301
|
const AUDIO_LEVEL_THRESHOLD = 0.2;
|
|
11304
11302
|
class RNSpeechDetector {
|
|
11305
11303
|
constructor() {
|
|
@@ -11382,20 +11380,24 @@ class RNSpeechDetector {
|
|
|
11382
11380
|
}
|
|
11383
11381
|
|
|
11384
11382
|
class MicrophoneManager extends InputMediaDeviceManager {
|
|
11385
|
-
constructor(call)
|
|
11386
|
-
|
|
11387
|
-
|
|
11383
|
+
constructor(call, disableMode = isReactNative()
|
|
11384
|
+
? 'disable-tracks'
|
|
11385
|
+
: 'stop-tracks') {
|
|
11386
|
+
super(call, new MicrophoneManagerState(disableMode), TrackType.AUDIO);
|
|
11387
|
+
this.speakingWhileMutedNotificationEnabled = true;
|
|
11388
|
+
this.subscriptions.push(createSubscription(combineLatest([
|
|
11388
11389
|
this.call.state.callingState$,
|
|
11389
11390
|
this.call.state.ownCapabilities$,
|
|
11390
11391
|
this.state.selectedDevice$,
|
|
11391
11392
|
this.state.status$,
|
|
11392
|
-
])
|
|
11393
|
-
if (callingState
|
|
11394
|
-
|
|
11395
|
-
await this.stopSpeakingWhileMutedDetection();
|
|
11396
|
-
}
|
|
11397
|
-
return;
|
|
11393
|
+
]), async ([callingState, ownCapabilities, deviceId, status]) => {
|
|
11394
|
+
if (callingState === CallingState.LEFT) {
|
|
11395
|
+
await this.stopSpeakingWhileMutedDetection();
|
|
11398
11396
|
}
|
|
11397
|
+
if (callingState !== CallingState.JOINED)
|
|
11398
|
+
return;
|
|
11399
|
+
if (!this.speakingWhileMutedNotificationEnabled)
|
|
11400
|
+
return;
|
|
11399
11401
|
if (ownCapabilities.includes(OwnCapability.SEND_AUDIO)) {
|
|
11400
11402
|
if (status === 'disabled') {
|
|
11401
11403
|
await this.startSpeakingWhileMutedDetection(deviceId);
|
|
@@ -11407,7 +11409,7 @@ class MicrophoneManager extends InputMediaDeviceManager {
|
|
|
11407
11409
|
else {
|
|
11408
11410
|
await this.stopSpeakingWhileMutedDetection();
|
|
11409
11411
|
}
|
|
11410
|
-
});
|
|
11412
|
+
}));
|
|
11411
11413
|
this.subscriptions.push(createSubscription(this.call.state.callingState$, (callingState) => {
|
|
11412
11414
|
// do nothing when noise filtering isn't turned on
|
|
11413
11415
|
if (!this.noiseCancellationRegistration || !this.noiseCancellation)
|
|
@@ -11502,6 +11504,22 @@ class MicrophoneManager extends InputMediaDeviceManager {
|
|
|
11502
11504
|
});
|
|
11503
11505
|
await this.call.notifyNoiseCancellationStopped();
|
|
11504
11506
|
}
|
|
11507
|
+
/**
|
|
11508
|
+
* Enables speaking while muted notification.
|
|
11509
|
+
*/
|
|
11510
|
+
async enableSpeakingWhileMutedNotification() {
|
|
11511
|
+
this.speakingWhileMutedNotificationEnabled = true;
|
|
11512
|
+
if (this.state.status === 'disabled') {
|
|
11513
|
+
await this.startSpeakingWhileMutedDetection(this.state.selectedDevice);
|
|
11514
|
+
}
|
|
11515
|
+
}
|
|
11516
|
+
/**
|
|
11517
|
+
* Disables speaking while muted notification.
|
|
11518
|
+
*/
|
|
11519
|
+
async disableSpeakingWhileMutedNotification() {
|
|
11520
|
+
this.speakingWhileMutedNotificationEnabled = false;
|
|
11521
|
+
await this.stopSpeakingWhileMutedDetection();
|
|
11522
|
+
}
|
|
11505
11523
|
getDevices() {
|
|
11506
11524
|
return getAudioDevices();
|
|
11507
11525
|
}
|
|
@@ -11539,9 +11557,8 @@ class MicrophoneManager extends InputMediaDeviceManager {
|
|
|
11539
11557
|
}
|
|
11540
11558
|
}
|
|
11541
11559
|
async stopSpeakingWhileMutedDetection() {
|
|
11542
|
-
if (!this.soundDetectorCleanup)
|
|
11560
|
+
if (!this.soundDetectorCleanup)
|
|
11543
11561
|
return;
|
|
11544
|
-
}
|
|
11545
11562
|
this.state.setSpeakingWhileMuted(false);
|
|
11546
11563
|
try {
|
|
11547
11564
|
await this.soundDetectorCleanup();
|
|
@@ -14864,7 +14881,7 @@ class StreamClient {
|
|
|
14864
14881
|
});
|
|
14865
14882
|
};
|
|
14866
14883
|
this.getUserAgent = () => {
|
|
14867
|
-
const version = "0.7.
|
|
14884
|
+
const version = "0.7.11" ;
|
|
14868
14885
|
return (this.userAgent ||
|
|
14869
14886
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
14870
14887
|
};
|