@stream-io/video-client 1.0.3 → 1.0.5
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 +14 -0
- package/dist/index.browser.es.js +54 -43
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +54 -43
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +54 -43
- package/dist/index.es.js.map +1 -1
- package/dist/src/gen/coordinator/index.d.ts +214 -0
- package/dist/src/stats/SfuStatsReporter.d.ts +2 -2
- package/dist/src/stats/stateStoreStatsReporter.d.ts +3 -2
- package/dist/src/stats/utils.d.ts +3 -0
- package/package.json +1 -1
- package/src/Call.ts +12 -5
- package/src/devices/InputMediaDeviceManager.ts +1 -0
- package/src/gen/coordinator/index.ts +214 -0
- package/src/stats/SfuStatsReporter.ts +6 -15
- package/src/stats/stateStoreStatsReporter.ts +29 -21
- package/src/stats/utils.ts +15 -11
package/dist/index.es.js
CHANGED
|
@@ -9789,25 +9789,29 @@ const flatten = (report) => {
|
|
|
9789
9789
|
};
|
|
9790
9790
|
const getSdkSignature = (clientDetails) => {
|
|
9791
9791
|
const { sdk, ...platform } = clientDetails;
|
|
9792
|
-
const sdkName = sdk
|
|
9793
|
-
|
|
9794
|
-
: sdk && sdk.type === SdkType.REACT_NATIVE
|
|
9795
|
-
? 'stream-react-native'
|
|
9796
|
-
: 'stream-js';
|
|
9797
|
-
const sdkVersion = sdk
|
|
9798
|
-
? `${sdk.major}.${sdk.minor}.${sdk.patch}`
|
|
9799
|
-
: '0.0.0-development';
|
|
9792
|
+
const sdkName = getSdkName(sdk);
|
|
9793
|
+
const sdkVersion = getSdkVersion(sdk);
|
|
9800
9794
|
return {
|
|
9801
9795
|
sdkName,
|
|
9802
9796
|
sdkVersion,
|
|
9803
9797
|
...platform,
|
|
9804
9798
|
};
|
|
9805
9799
|
};
|
|
9800
|
+
const getSdkName = (sdk) => {
|
|
9801
|
+
return sdk && sdk.type === SdkType.REACT
|
|
9802
|
+
? 'stream-react'
|
|
9803
|
+
: sdk && sdk.type === SdkType.REACT_NATIVE
|
|
9804
|
+
? 'stream-react-native'
|
|
9805
|
+
: 'stream-js';
|
|
9806
|
+
};
|
|
9807
|
+
const getSdkVersion = (sdk) => {
|
|
9808
|
+
return sdk ? `${sdk.major}.${sdk.minor}.${sdk.patch}` : '0.0.0-development';
|
|
9809
|
+
};
|
|
9806
9810
|
|
|
9807
9811
|
/**
|
|
9808
9812
|
* Creates a new StatsReporter instance that collects metrics about the ongoing call and reports them to the state store
|
|
9809
9813
|
*/
|
|
9810
|
-
const createStatsReporter = ({ subscriber, publisher, state, pollingIntervalInMs = 2000, }) => {
|
|
9814
|
+
const createStatsReporter = ({ subscriber, publisher, state, datacenter, pollingIntervalInMs = 2000, }) => {
|
|
9811
9815
|
const logger = getLogger(['stats']);
|
|
9812
9816
|
const getRawStatsForTrack = async (kind, selector) => {
|
|
9813
9817
|
if (kind === 'subscriber' && subscriber) {
|
|
@@ -9817,12 +9821,13 @@ const createStatsReporter = ({ subscriber, publisher, state, pollingIntervalInMs
|
|
|
9817
9821
|
return publisher.getStats(selector);
|
|
9818
9822
|
}
|
|
9819
9823
|
else {
|
|
9820
|
-
logger('warn', `Can't retrieve RTC stats for ${kind}`);
|
|
9821
9824
|
return undefined;
|
|
9822
9825
|
}
|
|
9823
9826
|
};
|
|
9824
9827
|
const getStatsForStream = async (kind, mediaStream) => {
|
|
9825
9828
|
const pc = kind === 'subscriber' ? subscriber : publisher;
|
|
9829
|
+
if (!pc)
|
|
9830
|
+
return [];
|
|
9826
9831
|
const statsForStream = [];
|
|
9827
9832
|
for (let track of mediaStream.getTracks()) {
|
|
9828
9833
|
const report = await pc.getStats(track);
|
|
@@ -9868,7 +9873,7 @@ const createStatsReporter = ({ subscriber, publisher, state, pollingIntervalInMs
|
|
|
9868
9873
|
});
|
|
9869
9874
|
}
|
|
9870
9875
|
catch (e) {
|
|
9871
|
-
logger('error', `Failed to collect stats for ${kind}
|
|
9876
|
+
logger('error', `Failed to collect stats for ${kind} of ${participant.userId}`, e);
|
|
9872
9877
|
}
|
|
9873
9878
|
}
|
|
9874
9879
|
}
|
|
@@ -9881,19 +9886,21 @@ const createStatsReporter = ({ subscriber, publisher, state, pollingIntervalInMs
|
|
|
9881
9886
|
}))
|
|
9882
9887
|
.then(aggregate),
|
|
9883
9888
|
publisher
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
9889
|
+
? publisher
|
|
9890
|
+
.getStats()
|
|
9891
|
+
.then((report) => transform(report, {
|
|
9892
|
+
kind: 'publisher',
|
|
9893
|
+
trackKind: 'video',
|
|
9894
|
+
}))
|
|
9895
|
+
.then(aggregate)
|
|
9896
|
+
: getEmptyStats(),
|
|
9890
9897
|
]);
|
|
9891
9898
|
const [subscriberRawStats, publisherRawStats] = await Promise.all([
|
|
9892
9899
|
getRawStatsForTrack('subscriber'),
|
|
9893
|
-
getRawStatsForTrack('publisher'),
|
|
9900
|
+
publisher ? getRawStatsForTrack('publisher') : undefined,
|
|
9894
9901
|
]);
|
|
9895
9902
|
state.setCallStatsReport({
|
|
9896
|
-
datacenter
|
|
9903
|
+
datacenter,
|
|
9897
9904
|
publisherStats,
|
|
9898
9905
|
subscriberStats,
|
|
9899
9906
|
subscriberRawStats,
|
|
@@ -9970,14 +9977,9 @@ const transform = (report, opts) => {
|
|
|
9970
9977
|
timestamp: Date.now(),
|
|
9971
9978
|
};
|
|
9972
9979
|
};
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
* @param stats the stats to aggregate.
|
|
9977
|
-
*/
|
|
9978
|
-
const aggregate = (stats) => {
|
|
9979
|
-
const aggregatedStats = {
|
|
9980
|
-
rawReport: stats,
|
|
9980
|
+
const getEmptyStats = (stats) => {
|
|
9981
|
+
return {
|
|
9982
|
+
rawReport: stats ?? { streams: [], timestamp: Date.now() },
|
|
9981
9983
|
totalBytesSent: 0,
|
|
9982
9984
|
totalBytesReceived: 0,
|
|
9983
9985
|
averageJitterInMs: 0,
|
|
@@ -9988,6 +9990,14 @@ const aggregate = (stats) => {
|
|
|
9988
9990
|
highestFramesPerSecond: 0,
|
|
9989
9991
|
timestamp: Date.now(),
|
|
9990
9992
|
};
|
|
9993
|
+
};
|
|
9994
|
+
/**
|
|
9995
|
+
* Aggregates generic stats.
|
|
9996
|
+
*
|
|
9997
|
+
* @param stats the stats to aggregate.
|
|
9998
|
+
*/
|
|
9999
|
+
const aggregate = (stats) => {
|
|
10000
|
+
const aggregatedStats = getEmptyStats(stats);
|
|
9991
10001
|
let maxArea = -1;
|
|
9992
10002
|
const area = (w, h) => w * h;
|
|
9993
10003
|
const qualityLimitationReasons = new Set();
|
|
@@ -10031,7 +10041,7 @@ class SfuStatsReporter {
|
|
|
10031
10041
|
this.run = async () => {
|
|
10032
10042
|
const [subscriberStats, publisherStats] = await Promise.all([
|
|
10033
10043
|
this.subscriber.getStats().then(flatten).then(JSON.stringify),
|
|
10034
|
-
this.publisher
|
|
10044
|
+
this.publisher?.getStats().then(flatten).then(JSON.stringify) ?? '[]',
|
|
10035
10045
|
]);
|
|
10036
10046
|
await this.sfuClient.sendStats({
|
|
10037
10047
|
sdk: this.sdkName,
|
|
@@ -10060,15 +10070,8 @@ class SfuStatsReporter {
|
|
|
10060
10070
|
this.publisher = publisher;
|
|
10061
10071
|
const webRTCInfo = getWebRTCInfo();
|
|
10062
10072
|
const { sdk, browser } = clientDetails;
|
|
10063
|
-
this.sdkName =
|
|
10064
|
-
|
|
10065
|
-
? 'stream-react'
|
|
10066
|
-
: sdk && sdk.type === SdkType.REACT_NATIVE
|
|
10067
|
-
? 'stream-react-native'
|
|
10068
|
-
: 'stream-js';
|
|
10069
|
-
this.sdkVersion = sdk
|
|
10070
|
-
? `${sdk.major}.${sdk.minor}.${sdk.patch}`
|
|
10071
|
-
: '0.0.0-development';
|
|
10073
|
+
this.sdkName = getSdkName(sdk);
|
|
10074
|
+
this.sdkVersion = getSdkVersion(sdk);
|
|
10072
10075
|
// The WebRTC version if passed from the SDK, it is taken else the browser info is sent.
|
|
10073
10076
|
this.webRTCVersion =
|
|
10074
10077
|
webRTCInfo?.version ||
|
|
@@ -11211,6 +11214,7 @@ class InputMediaDeviceManager {
|
|
|
11211
11214
|
resetStatusChangeRequest() {
|
|
11212
11215
|
this.statusChangePromise = undefined;
|
|
11213
11216
|
this.statusChangeAbortController = undefined;
|
|
11217
|
+
this.state.setPendingStatus(this.state.status);
|
|
11214
11218
|
}
|
|
11215
11219
|
}
|
|
11216
11220
|
|
|
@@ -12624,7 +12628,10 @@ class Call {
|
|
|
12624
12628
|
connectionConfig,
|
|
12625
12629
|
});
|
|
12626
12630
|
}
|
|
12627
|
-
|
|
12631
|
+
// anonymous users can't publish anything hence, there is no need
|
|
12632
|
+
// to create Publisher Peer Connection for them
|
|
12633
|
+
const isAnonymous = this.streamClient.user?.type === 'anonymous';
|
|
12634
|
+
if (!this.publisher && !isAnonymous) {
|
|
12628
12635
|
const audioSettings = this.state.settings?.audio;
|
|
12629
12636
|
const isDtxEnabled = !!audioSettings?.opus_dtx_enabled;
|
|
12630
12637
|
const isRedEnabled = !!audioSettings?.redundant_coding_enabled;
|
|
@@ -12642,6 +12649,7 @@ class Call {
|
|
|
12642
12649
|
subscriber: this.subscriber,
|
|
12643
12650
|
publisher: this.publisher,
|
|
12644
12651
|
state: this.state,
|
|
12652
|
+
datacenter: this.sfuClient.edgeName,
|
|
12645
12653
|
});
|
|
12646
12654
|
}
|
|
12647
12655
|
const clientDetails = getClientDetails();
|
|
@@ -12687,15 +12695,18 @@ class Call {
|
|
|
12687
12695
|
}
|
|
12688
12696
|
if (isMigrating) {
|
|
12689
12697
|
await this.subscriber.migrateTo(sfuClient, connectionConfig);
|
|
12690
|
-
await this.publisher
|
|
12698
|
+
await this.publisher?.migrateTo(sfuClient, connectionConfig);
|
|
12691
12699
|
}
|
|
12692
12700
|
else if (isReconnecting) {
|
|
12693
12701
|
if (reconnected) {
|
|
12694
12702
|
// update the SFU client instance on the subscriber and publisher
|
|
12695
12703
|
this.subscriber.setSfuClient(sfuClient);
|
|
12696
|
-
|
|
12697
|
-
|
|
12698
|
-
|
|
12704
|
+
// publisher might not be there (anonymous users)
|
|
12705
|
+
if (this.publisher) {
|
|
12706
|
+
this.publisher.setSfuClient(sfuClient);
|
|
12707
|
+
// and perform a full ICE restart on the publisher
|
|
12708
|
+
await this.publisher.restartIce();
|
|
12709
|
+
}
|
|
12699
12710
|
}
|
|
12700
12711
|
else if (previousSfuClient?.isFastReconnecting) {
|
|
12701
12712
|
// reconnection wasn't possible, so we need to do a full rejoin
|
|
@@ -15192,7 +15203,7 @@ class StreamClient {
|
|
|
15192
15203
|
});
|
|
15193
15204
|
};
|
|
15194
15205
|
this.getUserAgent = () => {
|
|
15195
|
-
const version = "1.0.
|
|
15206
|
+
const version = "1.0.5" ;
|
|
15196
15207
|
return (this.userAgent ||
|
|
15197
15208
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
15198
15209
|
};
|