@stream-io/video-client 0.6.7 → 0.6.8
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 +125 -17
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +125 -17
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +125 -17
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +17 -1
- package/dist/src/coordinator/connection/client.d.ts +6 -6
- package/dist/src/devices/InputMediaDeviceManager.d.ts +18 -1
- package/dist/src/devices/SpeakerManager.d.ts +6 -1
- package/dist/src/gen/coordinator/index.d.ts +267 -2
- package/dist/src/rtc/signal.d.ts +1 -0
- package/package.json +4 -4
- package/src/Call.ts +42 -4
- package/src/devices/InputMediaDeviceManager.ts +140 -48
- package/src/devices/SpeakerManager.ts +6 -1
- package/src/devices/__tests__/InputMediaDeviceManagerFilters.test.ts +115 -0
- package/src/gen/coordinator/index.ts +262 -2
- package/src/helpers/DynascaleManager.ts +0 -2
- package/src/store/CallState.ts +5 -0
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.6.8](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.6.7...@stream-io/video-client-0.6.8) (2024-04-05)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **react:** Support for Background Filters and Background Blurring ([#1283](https://github.com/GetStream/stream-video-js/issues/1283)) ([f790ee7](https://github.com/GetStream/stream-video-js/commit/f790ee78c20fb0f5266e429a777d8bb7ef158c83)), closes [#1271](https://github.com/GetStream/stream-video-js/issues/1271) [#1276](https://github.com/GetStream/stream-video-js/issues/1276)
|
|
11
|
+
|
|
5
12
|
### [0.6.7](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.6.6...@stream-io/video-client-0.6.7) (2024-04-02)
|
|
6
13
|
|
|
7
14
|
|
package/dist/index.browser.es.js
CHANGED
|
@@ -5802,7 +5802,7 @@ class SignalServerClient {
|
|
|
5802
5802
|
const defaultOptions = {
|
|
5803
5803
|
baseUrl: '',
|
|
5804
5804
|
sendJson: true,
|
|
5805
|
-
timeout: 5 * 1000,
|
|
5805
|
+
timeout: 5 * 1000, // ms.
|
|
5806
5806
|
jsonOptions: {
|
|
5807
5807
|
ignoreUnknownFields: true,
|
|
5808
5808
|
},
|
|
@@ -6208,7 +6208,7 @@ const findOptimalScreenSharingLayers = (videoTrack, preferences) => {
|
|
|
6208
6208
|
return [
|
|
6209
6209
|
{
|
|
6210
6210
|
active: true,
|
|
6211
|
-
rid: 'q',
|
|
6211
|
+
rid: 'q', // single track, start from 'q'
|
|
6212
6212
|
width: settings.width || 0,
|
|
6213
6213
|
height: settings.height || 0,
|
|
6214
6214
|
scaleResolutionDownBy: 1,
|
|
@@ -7061,9 +7061,14 @@ class CallState {
|
|
|
7061
7061
|
this.thumbnails$ = this.thumbnailsSubject.asObservable();
|
|
7062
7062
|
this.eventHandlers = {
|
|
7063
7063
|
// these events are not updating the call state:
|
|
7064
|
+
'call.closed_caption': undefined,
|
|
7064
7065
|
'call.permission_request': undefined,
|
|
7065
7066
|
'call.recording_failed': undefined,
|
|
7066
7067
|
'call.recording_ready': undefined,
|
|
7068
|
+
'call.transcription_started': undefined,
|
|
7069
|
+
'call.transcription_stopped': undefined,
|
|
7070
|
+
'call.transcription_ready': undefined,
|
|
7071
|
+
'call.transcription_failed': undefined,
|
|
7067
7072
|
'call.user_muted': undefined,
|
|
7068
7073
|
'connection.error': undefined,
|
|
7069
7074
|
'connection.ok': undefined,
|
|
@@ -9896,7 +9901,6 @@ class DynascaleManager {
|
|
|
9896
9901
|
// play audio through the system's default device
|
|
9897
9902
|
const { selectedDevice } = this.call.speaker.state;
|
|
9898
9903
|
if (selectedDevice && 'setSinkId' in audioElement) {
|
|
9899
|
-
// @ts-expect-error setSinkId is not yet in the lib
|
|
9900
9904
|
audioElement.setSinkId(selectedDevice);
|
|
9901
9905
|
}
|
|
9902
9906
|
}
|
|
@@ -9906,7 +9910,6 @@ class DynascaleManager {
|
|
|
9906
9910
|
? null
|
|
9907
9911
|
: this.call.speaker.state.selectedDevice$.subscribe((deviceId) => {
|
|
9908
9912
|
if (deviceId) {
|
|
9909
|
-
// @ts-expect-error setSinkId is not yet in the lib
|
|
9910
9913
|
audioElement.setSinkId(deviceId);
|
|
9911
9914
|
}
|
|
9912
9915
|
});
|
|
@@ -10306,8 +10309,14 @@ class InputMediaDeviceManager {
|
|
|
10306
10309
|
this.stopOnLeave = true;
|
|
10307
10310
|
this.subscriptions = [];
|
|
10308
10311
|
this.isTrackStoppedDueToTrackEnd = false;
|
|
10309
|
-
this.
|
|
10310
|
-
|
|
10312
|
+
this.filters = [];
|
|
10313
|
+
/**
|
|
10314
|
+
* Disposes the manager.
|
|
10315
|
+
*
|
|
10316
|
+
* @internal
|
|
10317
|
+
*/
|
|
10318
|
+
this.dispose = () => {
|
|
10319
|
+
this.subscriptions.forEach((s) => s());
|
|
10311
10320
|
};
|
|
10312
10321
|
this.logger = getLogger([`${TrackType[trackType].toLowerCase()} manager`]);
|
|
10313
10322
|
if (deviceIds$ &&
|
|
@@ -10384,6 +10393,23 @@ class InputMediaDeviceManager {
|
|
|
10384
10393
|
return this.enable();
|
|
10385
10394
|
}
|
|
10386
10395
|
}
|
|
10396
|
+
/**
|
|
10397
|
+
* Registers a filter that will be applied to the stream.
|
|
10398
|
+
*
|
|
10399
|
+
* The registered filter will get the existing stream, and it should return
|
|
10400
|
+
* a new stream with the applied filter.
|
|
10401
|
+
*
|
|
10402
|
+
* @param filter the filter to register.
|
|
10403
|
+
* @returns a function that will unregister the filter.
|
|
10404
|
+
*/
|
|
10405
|
+
async registerFilter(filter) {
|
|
10406
|
+
this.filters.push(filter);
|
|
10407
|
+
await this.applySettingsToStream();
|
|
10408
|
+
return async () => {
|
|
10409
|
+
this.filters = this.filters.filter((f) => f !== filter);
|
|
10410
|
+
await this.applySettingsToStream();
|
|
10411
|
+
};
|
|
10412
|
+
}
|
|
10387
10413
|
/**
|
|
10388
10414
|
* Will set the default constraints for the device.
|
|
10389
10415
|
*
|
|
@@ -10479,7 +10505,62 @@ class InputMediaDeviceManager {
|
|
|
10479
10505
|
...defaultConstraints,
|
|
10480
10506
|
deviceId: this.state.selectedDevice,
|
|
10481
10507
|
};
|
|
10482
|
-
|
|
10508
|
+
/**
|
|
10509
|
+
* Chains two media streams together.
|
|
10510
|
+
*
|
|
10511
|
+
* In our case, filters MediaStreams are derived from their parent MediaStream.
|
|
10512
|
+
* However, once a child filter's track is stopped,
|
|
10513
|
+
* the tracks of the parent MediaStream aren't automatically stopped.
|
|
10514
|
+
* This leads to a situation where the camera indicator light is still on
|
|
10515
|
+
* even though the user stopped publishing video.
|
|
10516
|
+
*
|
|
10517
|
+
* This function works around this issue by stopping the parent MediaStream's tracks
|
|
10518
|
+
* as well once the child filter's tracks are stopped.
|
|
10519
|
+
*
|
|
10520
|
+
* It works by patching the stop() method of the child filter's tracks to also stop
|
|
10521
|
+
* the parent MediaStream's tracks of the same type. Here we assume that
|
|
10522
|
+
* the parent MediaStream has only one track of each type.
|
|
10523
|
+
*
|
|
10524
|
+
* @param parentStream the parent MediaStream. Omit for the root stream.
|
|
10525
|
+
*/
|
|
10526
|
+
const chainWith = (parentStream) => async (filterStream) => {
|
|
10527
|
+
if (!parentStream)
|
|
10528
|
+
return filterStream;
|
|
10529
|
+
// TODO OL: take care of track.enabled property as well
|
|
10530
|
+
const parent = await parentStream;
|
|
10531
|
+
filterStream.getTracks().forEach((track) => {
|
|
10532
|
+
const originalStop = track.stop;
|
|
10533
|
+
track.stop = function stop() {
|
|
10534
|
+
originalStop.call(track);
|
|
10535
|
+
parent.getTracks().forEach((parentTrack) => {
|
|
10536
|
+
if (parentTrack.kind === track.kind) {
|
|
10537
|
+
parentTrack.stop();
|
|
10538
|
+
}
|
|
10539
|
+
});
|
|
10540
|
+
};
|
|
10541
|
+
});
|
|
10542
|
+
parent.getTracks().forEach((parentTrack) => {
|
|
10543
|
+
// When the parent stream abruptly ends, we propagate the event
|
|
10544
|
+
// to the filter stream.
|
|
10545
|
+
// This usually happens when the camera/microphone permissions
|
|
10546
|
+
// are revoked or when the device is disconnected.
|
|
10547
|
+
const handleParentTrackEnded = () => {
|
|
10548
|
+
filterStream.getTracks().forEach((track) => {
|
|
10549
|
+
if (parentTrack.kind !== track.kind)
|
|
10550
|
+
return;
|
|
10551
|
+
track.stop();
|
|
10552
|
+
track.dispatchEvent(new Event('ended')); // propagate the event
|
|
10553
|
+
});
|
|
10554
|
+
};
|
|
10555
|
+
parentTrack.addEventListener('ended', handleParentTrackEnded);
|
|
10556
|
+
this.subscriptions.push(() => {
|
|
10557
|
+
parentTrack.removeEventListener('ended', handleParentTrackEnded);
|
|
10558
|
+
});
|
|
10559
|
+
});
|
|
10560
|
+
return filterStream;
|
|
10561
|
+
};
|
|
10562
|
+
// we publish the last MediaStream of the chain
|
|
10563
|
+
stream = await this.filters.reduce((parent, filter) => parent.then(filter).then(chainWith(parent)), this.getStream(constraints));
|
|
10483
10564
|
}
|
|
10484
10565
|
if (this.call.state.callingState === CallingState.JOINED) {
|
|
10485
10566
|
await this.publishStream(stream);
|
|
@@ -10515,10 +10596,10 @@ class InputMediaDeviceManager {
|
|
|
10515
10596
|
return '';
|
|
10516
10597
|
}
|
|
10517
10598
|
handleDisconnectedOrReplacedDevices() {
|
|
10518
|
-
this.subscriptions.push(combineLatest([
|
|
10599
|
+
this.subscriptions.push(createSubscription(combineLatest([
|
|
10519
10600
|
deviceIds$.pipe(pairwise()),
|
|
10520
10601
|
this.state.selectedDevice$,
|
|
10521
|
-
])
|
|
10602
|
+
]), async ([[prevDevices, currentDevices], deviceId]) => {
|
|
10522
10603
|
if (!deviceId) {
|
|
10523
10604
|
return;
|
|
10524
10605
|
}
|
|
@@ -11282,7 +11363,12 @@ class SpeakerManager {
|
|
|
11282
11363
|
constructor(call) {
|
|
11283
11364
|
this.state = new SpeakerState();
|
|
11284
11365
|
this.subscriptions = [];
|
|
11285
|
-
|
|
11366
|
+
/**
|
|
11367
|
+
* Disposes the manager.
|
|
11368
|
+
*
|
|
11369
|
+
* @internal
|
|
11370
|
+
*/
|
|
11371
|
+
this.dispose = () => {
|
|
11286
11372
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
11287
11373
|
};
|
|
11288
11374
|
this.call = call;
|
|
@@ -11477,10 +11563,10 @@ class Call {
|
|
|
11477
11563
|
// Call all leave call hooks, e.g. to clean up global event handlers
|
|
11478
11564
|
this.leaveCallHooks.forEach((hook) => hook());
|
|
11479
11565
|
this.clientStore.unregisterCall(this);
|
|
11480
|
-
this.camera.
|
|
11481
|
-
this.microphone.
|
|
11482
|
-
this.screenShare.
|
|
11483
|
-
this.speaker.
|
|
11566
|
+
this.camera.dispose();
|
|
11567
|
+
this.microphone.dispose();
|
|
11568
|
+
this.screenShare.dispose();
|
|
11569
|
+
this.speaker.dispose();
|
|
11484
11570
|
const stopOnLeavePromises = [];
|
|
11485
11571
|
if (this.camera.stopOnLeave) {
|
|
11486
11572
|
stopOnLeavePromises.push(this.camera.disable(true));
|
|
@@ -12282,6 +12368,20 @@ class Call {
|
|
|
12282
12368
|
this.stopRecording = async () => {
|
|
12283
12369
|
return this.streamClient.post(`${this.streamClientBasePath}/stop_recording`, {});
|
|
12284
12370
|
};
|
|
12371
|
+
/**
|
|
12372
|
+
* Starts the transcription of the call.
|
|
12373
|
+
*
|
|
12374
|
+
* @param request the request data.
|
|
12375
|
+
*/
|
|
12376
|
+
this.startTranscription = async (request) => {
|
|
12377
|
+
return this.streamClient.post(`${this.streamClientBasePath}/start_transcription`, request);
|
|
12378
|
+
};
|
|
12379
|
+
/**
|
|
12380
|
+
* Stops the transcription of the call.
|
|
12381
|
+
*/
|
|
12382
|
+
this.stopTranscription = async () => {
|
|
12383
|
+
return this.streamClient.post(`${this.streamClientBasePath}/stop_transcription`);
|
|
12384
|
+
};
|
|
12285
12385
|
/**
|
|
12286
12386
|
* Sends a `call.permission_request` event to all users connected to the call. The call settings object contains infomration about which permissions can be requested during a call (for example a user might be allowed to request permission to publish audio, but not video).
|
|
12287
12387
|
*/
|
|
@@ -12490,6 +12590,14 @@ class Call {
|
|
|
12490
12590
|
}
|
|
12491
12591
|
return this.streamClient.get(`${endpoint}/recordings`);
|
|
12492
12592
|
};
|
|
12593
|
+
/**
|
|
12594
|
+
* Retrieves the list of transcriptions for the current call.
|
|
12595
|
+
*
|
|
12596
|
+
* @returns the list of transcriptions.
|
|
12597
|
+
*/
|
|
12598
|
+
this.queryTranscriptions = async () => {
|
|
12599
|
+
return this.streamClient.get(`${this.streamClientBasePath}/transcriptions`);
|
|
12600
|
+
};
|
|
12493
12601
|
/**
|
|
12494
12602
|
* Retrieve call statistics for a particular call session (historical).
|
|
12495
12603
|
* Here `callSessionID` is mandatory.
|
|
@@ -13557,7 +13665,7 @@ function UserFromToken(token) {
|
|
|
13557
13665
|
*/
|
|
13558
13666
|
function DevToken(userId) {
|
|
13559
13667
|
return [
|
|
13560
|
-
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
|
|
13668
|
+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9', //{"alg": "HS256", "typ": "JWT"}
|
|
13561
13669
|
encodeBase64(JSON.stringify({ user_id: userId })),
|
|
13562
13670
|
'devtoken', // hardcoded signature
|
|
13563
13671
|
].join('.');
|
|
@@ -14369,7 +14477,7 @@ class StreamClient {
|
|
|
14369
14477
|
});
|
|
14370
14478
|
};
|
|
14371
14479
|
this.getUserAgent = () => {
|
|
14372
|
-
const version = "0.6.
|
|
14480
|
+
const version = "0.6.8" ;
|
|
14373
14481
|
return (this.userAgent ||
|
|
14374
14482
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
14375
14483
|
};
|
|
@@ -14484,7 +14592,7 @@ class StreamClient {
|
|
|
14484
14592
|
}
|
|
14485
14593
|
this.options = {
|
|
14486
14594
|
timeout: 5000,
|
|
14487
|
-
withCredentials: false,
|
|
14595
|
+
withCredentials: false, // making sure cookies are not sent
|
|
14488
14596
|
warmUp: false,
|
|
14489
14597
|
...inputOptions,
|
|
14490
14598
|
};
|