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