@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 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
 
@@ -9513,7 +9513,7 @@ const toRtcConfiguration = (config) => {
9513
9513
  *
9514
9514
  * @param report the report to flatten.
9515
9515
  */
9516
- const flatten$1 = (report) => {
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$1(report);
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$1).then(JSON.stringify),
9767
- this.publisher.getStats().then(flatten$1).then(JSON.stringify),
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)), this.getStream(constraints));
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 (stream) {
11047
- this.setDevice(this.getDeviceIdFromStream(stream));
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
- return stream.getVideoTracks()[0]?.getSettings().deviceId;
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('disable-tracks',
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
- return stream.getAudioTracks()[0]?.getSettings().deviceId;
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
- super(call, new MicrophoneManagerState(), TrackType.AUDIO);
11386
- combineLatest([
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
- ]).subscribe(async ([callingState, ownCapabilities, deviceId, status]) => {
11392
- if (callingState !== CallingState.JOINED) {
11393
- if (callingState === CallingState.LEFT) {
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.10" ;
14885
+ const version = "0.7.11" ;
14869
14886
  return (this.userAgent ||
14870
14887
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
14871
14888
  };