@livedigital/client 2.21.0 → 2.22.0
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/dist/engine/index.d.ts +2 -1
- package/dist/engine/wid/WebRTCIssueDetector.d.ts +2 -0
- package/dist/engine/wid/WebRTCIssueEmitter.d.ts +5 -3
- package/dist/engine/wid/lib/NetworkScoresCalculator.d.ts +10 -0
- package/dist/engine/wid/types.d.ts +8 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.es.js +1 -1
- package/dist/index.js +1 -1
- package/dist/types/engine.d.ts +3 -1
- package/package.json +1 -1
- package/src/engine/DefaultEngineDependenciesFactory.ts +1 -0
- package/src/engine/index.ts +3 -1
- package/src/engine/wid/WebRTCIssueDetector.ts +17 -1
- package/src/engine/wid/WebRTCIssueEmitter.ts +10 -3
- package/src/engine/wid/detectors/InboundNetworkIssueDetector.ts +1 -20
- package/src/engine/wid/detectors/OutboundNetworkIssueDetector.ts +1 -20
- package/src/engine/wid/lib/NetworkScoresCalculator.ts +122 -0
- package/src/engine/wid/types.ts +9 -0
- package/src/index.ts +4 -1
- package/src/types/engine.ts +4 -1
package/dist/types/engine.d.ts
CHANGED
|
@@ -7,11 +7,13 @@ import ChannelEventHandler from '../engine/handlers/ChannelEventHandler';
|
|
|
7
7
|
import MediaSoupEventHandler from '../engine/handlers/MediaSoupEventHandler';
|
|
8
8
|
import WebRTCIssueDetector from '../engine/wid/WebRTCIssueDetector';
|
|
9
9
|
import { LoadBalancerApiClientParams } from '../engine/network/LoadBalancerClient';
|
|
10
|
-
import { IssueDetectorResult } from '../engine/wid/types';
|
|
10
|
+
import { IssueDetectorResult, NetworkScores } from '../engine/wid/types';
|
|
11
11
|
import { LogLevel } from './common';
|
|
12
12
|
export declare type IssuesHandler = (issues: IssueDetectorResult) => void;
|
|
13
|
+
export declare type NetworkScoresUpdatedHandler = (networks: NetworkScores) => void;
|
|
13
14
|
export interface CreateIssueDetectorParams {
|
|
14
15
|
onIssues?: IssuesHandler;
|
|
16
|
+
onNetworkScoresUpdated?: NetworkScoresUpdatedHandler;
|
|
15
17
|
ignoreSSRCList?: number[];
|
|
16
18
|
}
|
|
17
19
|
export interface CreateMediaParams {
|
package/package.json
CHANGED
|
@@ -50,6 +50,7 @@ class DefaultEngineDependenciesFactory implements EngineDependenciesFactory {
|
|
|
50
50
|
createIssueDetector(params: CreateIssueDetectorParams): WebRTCIssueDetector {
|
|
51
51
|
return new WebRTCIssueDetector({
|
|
52
52
|
onIssues: params.onIssues,
|
|
53
|
+
onNetworkScoresUpdated: params.onNetworkScoresUpdated,
|
|
53
54
|
ignoreSSRCList: params.ignoreSSRCList,
|
|
54
55
|
});
|
|
55
56
|
}
|
package/src/engine/index.ts
CHANGED
|
@@ -28,7 +28,7 @@ import VideoTrack from './media/tracks/VideoTrack';
|
|
|
28
28
|
import PeerTrack from './media/tracks/PeerTrack';
|
|
29
29
|
import WebRTCIssueDetector from './wid/WebRTCIssueDetector';
|
|
30
30
|
import { retryAsync } from '../helpers/retry';
|
|
31
|
-
import { EngineDependenciesFactory, IssuesHandler } from '../types/engine';
|
|
31
|
+
import { EngineDependenciesFactory, IssuesHandler, NetworkScoresUpdatedHandler } from '../types/engine';
|
|
32
32
|
import { LogLevels } from '../constants/common';
|
|
33
33
|
import { LoadBalancerApiClientParams } from './network/LoadBalancerClient';
|
|
34
34
|
import validateAppData from '../helpers/appDataValidator';
|
|
@@ -42,6 +42,7 @@ type EngineParams = {
|
|
|
42
42
|
logLevel?: LogLevel;
|
|
43
43
|
onLogMessage?: LogMessageHandler;
|
|
44
44
|
onIssues?: IssuesHandler;
|
|
45
|
+
onNetworkScoresUpdated?: NetworkScoresUpdatedHandler;
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
class Engine {
|
|
@@ -108,6 +109,7 @@ class Engine {
|
|
|
108
109
|
|
|
109
110
|
this.webRtcIssueDetector = dependenciesFactory.createIssueDetector({
|
|
110
111
|
onIssues: params.onIssues,
|
|
112
|
+
onNetworkScoresUpdated: params.onNetworkScoresUpdated,
|
|
111
113
|
ignoreSSRCList: [1234], // mediasoup-client probator
|
|
112
114
|
});
|
|
113
115
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WebRTCStats } from '@peermetrics/webrtc-stats';
|
|
1
|
+
import { WebRTCStats, WebRTCStatsEventData } from '@peermetrics/webrtc-stats';
|
|
2
2
|
import { WebRTCIssueEmitter } from './WebRTCIssueEmitter';
|
|
3
3
|
import {
|
|
4
4
|
WebRTCIssueDetectorConstructorParams,
|
|
@@ -16,6 +16,7 @@ import OutboundNetworkIssueDetector from './detectors/OutboundNetworkIssueDetect
|
|
|
16
16
|
import NetworkMediaSyncIssueDetector from './detectors/NetworkMediaSyncIssueDetector';
|
|
17
17
|
import AvailableOutgoingBitrateIssueDetector from './detectors/AvailableOutgoingBitrateIssueDetector';
|
|
18
18
|
import VideoCodecMismatchDetector from './detectors/VideoCodecMismatchDetector';
|
|
19
|
+
import NetworkScoresCalculator from './lib/NetworkScoresCalculator';
|
|
19
20
|
|
|
20
21
|
class WebRTCIssueDetector {
|
|
21
22
|
private readonly webrtcStats: WebRTCStats;
|
|
@@ -26,6 +27,8 @@ class WebRTCIssueDetector {
|
|
|
26
27
|
|
|
27
28
|
private readonly detectors: IssueDetector[] = [];
|
|
28
29
|
|
|
30
|
+
private readonly networkScoresCalculator: NetworkScoresCalculator;
|
|
31
|
+
|
|
29
32
|
readonly eventEmitter = new WebRTCIssueEmitter();
|
|
30
33
|
|
|
31
34
|
#running = false;
|
|
@@ -35,6 +38,10 @@ class WebRTCIssueDetector {
|
|
|
35
38
|
this.eventEmitter.on(EventType.Issue, params.onIssues);
|
|
36
39
|
}
|
|
37
40
|
|
|
41
|
+
if (params.onNetworkScoresUpdated) {
|
|
42
|
+
this.eventEmitter.on(EventType.NetworkScoresUpdated, params.onNetworkScoresUpdated);
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
// Move instantiation from the constructor
|
|
39
46
|
this.webrtcStats = new WebRTCStats({
|
|
40
47
|
getStatsInterval: this.getStatsInterval,
|
|
@@ -55,11 +62,15 @@ class WebRTCIssueDetector {
|
|
|
55
62
|
new VideoCodecMismatchDetector(),
|
|
56
63
|
];
|
|
57
64
|
|
|
65
|
+
this.networkScoresCalculator = new NetworkScoresCalculator();
|
|
66
|
+
|
|
58
67
|
this.webrtcStats.on('stats', (event) => {
|
|
59
68
|
this.detectIssues({
|
|
60
69
|
data: event.data,
|
|
61
70
|
ignoreSSRCList: params.ignoreSSRCList,
|
|
62
71
|
});
|
|
72
|
+
|
|
73
|
+
this.calculateNetworkScores(event.data);
|
|
63
74
|
});
|
|
64
75
|
}
|
|
65
76
|
|
|
@@ -115,6 +126,11 @@ class WebRTCIssueDetector {
|
|
|
115
126
|
}
|
|
116
127
|
}
|
|
117
128
|
|
|
129
|
+
private calculateNetworkScores(data: WebRTCStatsEventData): void {
|
|
130
|
+
const networkScores = this.networkScoresCalculator.calculate(data);
|
|
131
|
+
this.eventEmitter.emit(EventType.NetworkScoresUpdated, networkScores);
|
|
132
|
+
}
|
|
133
|
+
|
|
118
134
|
private wrapRTCPeerConnection(): void {
|
|
119
135
|
if (!window.RTCPeerConnection) {
|
|
120
136
|
return;
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
EventType,
|
|
4
|
+
EventPayload,
|
|
5
|
+
IssueDetectorResult,
|
|
6
|
+
NetworkScores,
|
|
7
|
+
} from './types';
|
|
3
8
|
|
|
4
9
|
export declare interface WebRTCIssueEmitter {
|
|
5
|
-
on(event: EventType, listener: (
|
|
6
|
-
|
|
10
|
+
on(event: EventType.Issue, listener: (payload: IssueDetectorResult) => void): this;
|
|
11
|
+
on(event: EventType.NetworkScoresUpdated, listener: (payload: NetworkScores) => void): this;
|
|
12
|
+
emit(event: EventType.Issue, payload: EventPayload): boolean;
|
|
13
|
+
emit(event: EventType.NetworkScoresUpdated, payload: NetworkScores): boolean;
|
|
7
14
|
}
|
|
8
15
|
|
|
9
16
|
export class WebRTCIssueEmitter extends EventEmitter {}
|
|
@@ -65,36 +65,17 @@ class InboundNetworkIssueDetector implements IssueDetector {
|
|
|
65
65
|
? Math.round((deltaPacketLost * 100) / (deltaPacketReceived + deltaPacketLost))
|
|
66
66
|
: 0;
|
|
67
67
|
|
|
68
|
-
const effectiveLatency = rtt + (avgJitter * 2) + 10;
|
|
69
|
-
let rFactor = effectiveLatency < 160
|
|
70
|
-
? 93.2 - (effectiveLatency / 40)
|
|
71
|
-
: 93.2 - (effectiveLatency / 120) - 10;
|
|
72
|
-
rFactor -= (packetsLoss * 2.5);
|
|
73
|
-
const mos = 1 + (0.035) * rFactor + (0.000007) * rFactor * (rFactor - 60) * (100 - rFactor);
|
|
74
|
-
|
|
75
68
|
const isHighPacketsLoss = packetsLoss > 5;
|
|
76
69
|
const isHighJitter = avgJitter >= 200;
|
|
77
70
|
const isHighRTT = rtt >= 250;
|
|
78
71
|
const isHighJitterBufferDelay = avgJitterBufferDelay > 500;
|
|
79
|
-
const isPoorConnectionQuality = mos < 3.1;
|
|
80
|
-
|
|
81
72
|
const isNetworkIssue = (!isHighPacketsLoss && isHighJitter) || isHighJitter || isHighPacketsLoss;
|
|
82
73
|
const isServerIssue = isHighRTT && !isHighJitter && !isHighPacketsLoss;
|
|
83
74
|
const isNetworkMediaLatencyIssue = isHighPacketsLoss && isHighJitter;
|
|
84
75
|
const isNetworkMediaSyncIssue = isHighJitter && isHighJitterBufferDelay;
|
|
85
76
|
|
|
86
77
|
const debug = `packetLoss: ${packetsLoss}%, jitter: ${avgJitter}, rtt: ${rtt},`
|
|
87
|
-
+ ` jitterBuffer: ${avgJitterBufferDelay}ms
|
|
88
|
-
|
|
89
|
-
if (isPoorConnectionQuality) {
|
|
90
|
-
issues.push({
|
|
91
|
-
type: IssueType.Network,
|
|
92
|
-
reason: IssueReason.LowInboundMOS,
|
|
93
|
-
iceCandidate: data.connection.local.id,
|
|
94
|
-
debug,
|
|
95
|
-
data: mos,
|
|
96
|
-
});
|
|
97
|
-
}
|
|
78
|
+
+ ` jitterBuffer: ${avgJitterBufferDelay}ms`;
|
|
98
79
|
|
|
99
80
|
if (isNetworkIssue) {
|
|
100
81
|
issues.push({
|
|
@@ -65,20 +65,11 @@ class OutboundNetworkIssueDetector implements IssueDetector {
|
|
|
65
65
|
? Math.round((deltaPacketLost * 100) / (deltaPacketSent + deltaPacketLost))
|
|
66
66
|
: 0;
|
|
67
67
|
|
|
68
|
-
const effectiveLatency = rtt + (avgJitter * 2) + 10;
|
|
69
|
-
let rFactor = effectiveLatency < 160
|
|
70
|
-
? 93.2 - (effectiveLatency / 40)
|
|
71
|
-
: 93.2 - (effectiveLatency / 120) - 10;
|
|
72
|
-
rFactor -= (packetsLoss * 2.5);
|
|
73
|
-
const mos = 1 + (0.035) * rFactor + (0.000007) * rFactor * (rFactor - 60) * (100 - rFactor);
|
|
74
|
-
|
|
75
68
|
const isHighPacketsLoss = packetsLoss > 5;
|
|
76
69
|
const isHighJitter = avgJitter >= 200;
|
|
77
|
-
const isPoorConnectionQuality = mos < 3.5;
|
|
78
70
|
const isNetworkMediaLatencyIssue = isHighPacketsLoss && isHighJitter;
|
|
79
71
|
const isNetworkIssue = (!isHighPacketsLoss && isHighJitter) || isHighJitter || isHighPacketsLoss;
|
|
80
|
-
const debug = `packetLoss: ${packetsLoss}%, jitter: ${avgJitter}, rtt: ${rtt}
|
|
81
|
-
+ ` MOS: ${mos}`;
|
|
72
|
+
const debug = `packetLoss: ${packetsLoss}%, jitter: ${avgJitter}, rtt: ${rtt}`;
|
|
82
73
|
|
|
83
74
|
if (isNetworkMediaLatencyIssue) {
|
|
84
75
|
issues.push({
|
|
@@ -98,16 +89,6 @@ class OutboundNetworkIssueDetector implements IssueDetector {
|
|
|
98
89
|
});
|
|
99
90
|
}
|
|
100
91
|
|
|
101
|
-
if (isPoorConnectionQuality) {
|
|
102
|
-
issues.push({
|
|
103
|
-
type: IssueType.Network,
|
|
104
|
-
reason: IssueReason.LowOutboundMOS,
|
|
105
|
-
iceCandidate: data.connection.local.id,
|
|
106
|
-
debug,
|
|
107
|
-
data: mos,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
92
|
return issues;
|
|
112
93
|
}
|
|
113
94
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/* eslint-disable class-methods-use-this */
|
|
2
|
+
import { WebRTCStatsEventData } from '@peermetrics/webrtc-stats';
|
|
3
|
+
import { NetworkScore, NetworkScores } from '../types';
|
|
4
|
+
|
|
5
|
+
class NetworkScoresCalculator {
|
|
6
|
+
#lastProcessedStats: { [connectionId: string]: WebRTCStatsEventData } = {};
|
|
7
|
+
|
|
8
|
+
calculate(data: WebRTCStatsEventData): NetworkScores {
|
|
9
|
+
const outbound = this.calcucateOutboundScore(data);
|
|
10
|
+
const inbound = this.calculateInboundScore(data);
|
|
11
|
+
this.#lastProcessedStats[data.connection.id] = data;
|
|
12
|
+
return { outbound, inbound };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private calcucateOutboundScore(data: WebRTCStatsEventData): NetworkScore | undefined {
|
|
16
|
+
const remoteInboundRTPStreamsStats = [
|
|
17
|
+
...data.remote?.audio.inbound || [],
|
|
18
|
+
...data.remote?.video.inbound || [],
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
if (!remoteInboundRTPStreamsStats.length) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const previousStats = this.#lastProcessedStats[data.connection.id];
|
|
26
|
+
if (!previousStats) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const previousRemoteInboundRTPStreamsStats = [
|
|
31
|
+
...previousStats.remote?.audio.inbound || [],
|
|
32
|
+
...previousStats.remote?.video.inbound || [],
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const { packetsSent } = data.connection;
|
|
36
|
+
const lastPacketsSent = previousStats.connection.packetsSent;
|
|
37
|
+
|
|
38
|
+
const rtpNetworkStats = remoteInboundRTPStreamsStats.reduce((stats, currentStreamStats) => {
|
|
39
|
+
const previousStreamStats = previousRemoteInboundRTPStreamsStats
|
|
40
|
+
.find((stream) => stream.ssrc === currentStreamStats.ssrc);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
sumJitter: stats.sumJitter + currentStreamStats.jitter,
|
|
44
|
+
packetsLost: stats.packetsLost + currentStreamStats.packetsLost,
|
|
45
|
+
lastPacketsLost: stats.lastPacketsLost + (previousStreamStats?.packetsLost || 0),
|
|
46
|
+
};
|
|
47
|
+
}, {
|
|
48
|
+
sumJitter: 0,
|
|
49
|
+
packetsLost: 0,
|
|
50
|
+
lastPacketsLost: 0,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const rtt = (1e3 * data.connection.currentRoundTripTime) || 0;
|
|
54
|
+
const { sumJitter } = rtpNetworkStats;
|
|
55
|
+
const avgJitter = sumJitter / remoteInboundRTPStreamsStats.length;
|
|
56
|
+
|
|
57
|
+
const deltaPacketSent = packetsSent - lastPacketsSent;
|
|
58
|
+
const deltaPacketLost = rtpNetworkStats.packetsLost - rtpNetworkStats.lastPacketsLost;
|
|
59
|
+
|
|
60
|
+
const packetsLoss = deltaPacketSent && deltaPacketLost
|
|
61
|
+
? Math.round((deltaPacketLost * 100) / (deltaPacketSent + deltaPacketLost))
|
|
62
|
+
: 0;
|
|
63
|
+
|
|
64
|
+
return this.calculateMOS({ avgJitter, rtt, packetsLoss });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private calculateInboundScore(data: WebRTCStatsEventData): NetworkScore | undefined {
|
|
68
|
+
const inboundRTPStreamsStats = [...data.audio?.inbound, ...data.video?.inbound];
|
|
69
|
+
if (!inboundRTPStreamsStats.length) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const previousStats = this.#lastProcessedStats[data.connection.id];
|
|
74
|
+
if (!previousStats) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const previousInboundStreamStats = [...previousStats.video?.inbound, ...previousStats.audio?.inbound];
|
|
79
|
+
const { packetsReceived } = data.connection;
|
|
80
|
+
const lastPacketsReceived = previousStats.connection.packetsReceived;
|
|
81
|
+
|
|
82
|
+
const rtpNetworkStats = inboundRTPStreamsStats.reduce((stats, currentStreamStats) => {
|
|
83
|
+
const previousStreamStats = previousInboundStreamStats.find((stream) => stream.ssrc === currentStreamStats.ssrc);
|
|
84
|
+
return {
|
|
85
|
+
sumJitter: stats.sumJitter + currentStreamStats.jitter,
|
|
86
|
+
packetsLost: stats.packetsLost + currentStreamStats.packetsLost,
|
|
87
|
+
lastPacketsLost: stats.lastPacketsLost + (previousStreamStats?.packetsLost || 0),
|
|
88
|
+
};
|
|
89
|
+
}, {
|
|
90
|
+
sumJitter: 0,
|
|
91
|
+
packetsLost: 0,
|
|
92
|
+
lastPacketsLost: 0,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const rtt = (1e3 * data.connection.currentRoundTripTime) || 0;
|
|
96
|
+
const { sumJitter } = rtpNetworkStats;
|
|
97
|
+
const avgJitter = sumJitter / inboundRTPStreamsStats.length;
|
|
98
|
+
|
|
99
|
+
const deltaPacketReceived = packetsReceived - lastPacketsReceived;
|
|
100
|
+
const deltaPacketLost = rtpNetworkStats.packetsLost - rtpNetworkStats.lastPacketsLost;
|
|
101
|
+
|
|
102
|
+
const packetsLoss = deltaPacketReceived && deltaPacketLost
|
|
103
|
+
? Math.round((deltaPacketLost * 100) / (deltaPacketReceived + deltaPacketLost))
|
|
104
|
+
: 0;
|
|
105
|
+
|
|
106
|
+
return this.calculateMOS({ avgJitter, rtt, packetsLoss });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private calculateMOS(
|
|
110
|
+
{ avgJitter, rtt, packetsLoss }:
|
|
111
|
+
{ avgJitter: number, rtt: number, packetsLoss: number },
|
|
112
|
+
): number {
|
|
113
|
+
const effectiveLatency = rtt + (avgJitter * 2) + 10;
|
|
114
|
+
let rFactor = effectiveLatency < 160
|
|
115
|
+
? 93.2 - (effectiveLatency / 40)
|
|
116
|
+
: 93.2 - (effectiveLatency / 120) - 10;
|
|
117
|
+
rFactor -= (packetsLoss * 2.5);
|
|
118
|
+
return 1 + (0.035) * rFactor + (0.000007) * rFactor * (rFactor - 60) * (100 - rFactor);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default NetworkScoresCalculator;
|
package/src/engine/wid/types.ts
CHANGED
|
@@ -14,12 +14,14 @@ export interface IssueDetector {
|
|
|
14
14
|
|
|
15
15
|
export enum EventType {
|
|
16
16
|
Issue = 'issue',
|
|
17
|
+
NetworkScoresUpdated = 'network-scores-updated',
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export type EventPayload = IssueDetectorResult;
|
|
20
21
|
|
|
21
22
|
export type WebRTCIssueDetectorConstructorParams = {
|
|
22
23
|
onIssues?: (payload: IssueDetectorResult) => void,
|
|
24
|
+
onNetworkScoresUpdated?: (payload: NetworkScores) => void,
|
|
23
25
|
ignoreSSRCList?: number[],
|
|
24
26
|
};
|
|
25
27
|
|
|
@@ -60,3 +62,10 @@ export type DetectIssuesPayload = {
|
|
|
60
62
|
data: WebRTCStatsEventData,
|
|
61
63
|
ignoreSSRCList?: number[],
|
|
62
64
|
};
|
|
65
|
+
|
|
66
|
+
export type NetworkScore = number;
|
|
67
|
+
|
|
68
|
+
export type NetworkScores = {
|
|
69
|
+
outbound?: NetworkScore,
|
|
70
|
+
inbound?: NetworkScore,
|
|
71
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ import Engine from './engine';
|
|
|
14
14
|
import Peer from './engine/Peer';
|
|
15
15
|
import { LoadBalancerApiClientParams } from './engine/network/LoadBalancerClient';
|
|
16
16
|
import DefaultEngineDependenciesFactory from './engine/DefaultEngineDependenciesFactory';
|
|
17
|
-
import { IssuesHandler } from './types/engine';
|
|
17
|
+
import { IssuesHandler, NetworkScoresUpdatedHandler } from './types/engine';
|
|
18
18
|
|
|
19
19
|
type ClientParams = {
|
|
20
20
|
observer?: EnhancedEventEmitter;
|
|
@@ -24,6 +24,7 @@ type ClientParams = {
|
|
|
24
24
|
logLevel?: LogLevel,
|
|
25
25
|
onLogMessage?: LogMessageHandler;
|
|
26
26
|
onIssues?: IssuesHandler,
|
|
27
|
+
onNetworkScoresUpdated?: NetworkScoresUpdatedHandler,
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
class Client {
|
|
@@ -37,6 +38,7 @@ class Client {
|
|
|
37
38
|
network,
|
|
38
39
|
onLogMessage,
|
|
39
40
|
onIssues,
|
|
41
|
+
onNetworkScoresUpdated,
|
|
40
42
|
logLevel,
|
|
41
43
|
} = params;
|
|
42
44
|
|
|
@@ -54,6 +56,7 @@ class Client {
|
|
|
54
56
|
logLevel,
|
|
55
57
|
onLogMessage,
|
|
56
58
|
onIssues,
|
|
59
|
+
onNetworkScoresUpdated,
|
|
57
60
|
});
|
|
58
61
|
}
|
|
59
62
|
|
package/src/types/engine.ts
CHANGED
|
@@ -7,13 +7,16 @@ import ChannelEventHandler from '../engine/handlers/ChannelEventHandler';
|
|
|
7
7
|
import MediaSoupEventHandler from '../engine/handlers/MediaSoupEventHandler';
|
|
8
8
|
import WebRTCIssueDetector from '../engine/wid/WebRTCIssueDetector';
|
|
9
9
|
import { LoadBalancerApiClientParams } from '../engine/network/LoadBalancerClient';
|
|
10
|
-
import { IssueDetectorResult } from '../engine/wid/types';
|
|
10
|
+
import { IssueDetectorResult, NetworkScores } from '../engine/wid/types';
|
|
11
11
|
import { LogLevel } from './common';
|
|
12
12
|
|
|
13
13
|
export type IssuesHandler = (issues: IssueDetectorResult) => void;
|
|
14
14
|
|
|
15
|
+
export type NetworkScoresUpdatedHandler = (networks: NetworkScores) => void;
|
|
16
|
+
|
|
15
17
|
export interface CreateIssueDetectorParams {
|
|
16
18
|
onIssues?: IssuesHandler;
|
|
19
|
+
onNetworkScoresUpdated?: NetworkScoresUpdatedHandler;
|
|
17
20
|
ignoreSSRCList?: number[];
|
|
18
21
|
}
|
|
19
22
|
|