Skip to content

Commit

Permalink
save
Browse files Browse the repository at this point in the history
  • Loading branch information
balazskreith committed Feb 10, 2025
1 parent 44537e2 commit ff67f0f
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 12 deletions.
5 changes: 4 additions & 1 deletion src/ClientMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ export class ClientMonitor extends EventEmitter {

videoFreezesDetector: config?.videoFreezesDetector ?? {
},
stuckedInboundTrackDetector: config?.stuckedInboundTrackDetector ?? {
dryInboundTrackDetector: config?.dryInboundTrackDetector ?? {
thresholdInMs: 5000,
},
dryOutboundTrackDetector: config?.dryOutboundTrackDetector ?? {
thresholdInMs: 5000,
},
audioDesyncDetector: config?.audioDesyncDetector ?? {
Expand Down
20 changes: 19 additions & 1 deletion src/ClientMonitorConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,25 @@ export type ClientMonitorConfig = {
/**
* Configuration for detecting inbound track stalling during monitoring.
*/
stuckedInboundTrackDetector: {
dryInboundTrackDetector: {
/**
* If true, the detection of stalled inbound tracks is disabled.
*
* DEFAULT: false
*/
disabled?: boolean;

/**
* The time threshold (in milliseconds) to determine if an inbound track
* is considered stalled.
*/
thresholdInMs: number;
};

/**
* Configuration for detecting inbound track stalling during monitoring.
*/
dryOutboundTrackDetector: {
/**
* If true, the detection of stalled inbound tracks is disabled.
*
Expand Down
13 changes: 13 additions & 0 deletions src/ClientMonitorEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { InboundTrackMonitor } from "./monitors/InboundTrackMonitor";
import { MediaPlayoutMonitor } from "./monitors/MediaPlayoutMonitor";
import { MediaSourceMonitor } from "./monitors/MediaSourceMonitor";
import { OutboundRtpMonitor } from "./monitors/OutboundRtpMonitor";
import { OutboundTrackMonitor } from "./monitors/OutboundTrackMonitor";
import { PeerConnectionMonitor } from "./monitors/PeerConnectionMonitor";
import { PeerConnectionTransportMonitor } from "./monitors/PeerConnectionTransportMonitor";
import { RemoteInboundRtpMonitor } from "./monitors/RemoteInboundRtpMonitor";
Expand Down Expand Up @@ -75,10 +76,18 @@ export type DryInboundTrackEventPayload = ClientMonitorBaseEvent & {
trackMonitor: InboundTrackMonitor,
}

export type DryOutboundTrackEventPayload = ClientMonitorBaseEvent & {
trackMonitor: OutboundTrackMonitor,
}

export type TooLongPcConnectionEstablishmentEventPayload = ClientMonitorBaseEvent & {
peerConnectionMonitor: PeerConnectionMonitor,
}

export type IceTupleChangedEventPayload = ClientMonitorBaseEvent & {
peerConnectionMonitor: PeerConnectionMonitor,
}

export type ScoreEventPayload = ClientMonitorBaseEvent & {
clientScore: number,
remarks?: string[],
Expand Down Expand Up @@ -148,6 +157,8 @@ export type NewCertificateMonitorEventPayload = ClientMonitorBaseEvent & {
certificateMonitor: CertificateMonitor,
}



export type ClientMonitorEvents = {
'sample-created': [SampleCreatedEventPayload],
"stats-collected": [StatsCollectedEventPayload],
Expand All @@ -161,6 +172,8 @@ export type ClientMonitorEvents = {
'synthesized-samples': [SynthesizedSamplesEventPayload],
'freezed-video-track': [FreezedVideoTrackEventPayload],
'dry-inbound-track': [DryInboundTrackEventPayload],
'dry-outbound-track': [DryOutboundTrackEventPayload],
'ice-tuple-changed': [IceTupleChangedEventPayload],
'too-long-pc-connection-establishment': [TooLongPcConnectionEstablishmentEventPayload]
// 'ice-restart': [peerConnectionMonitor: PeerConnectionMonitor],
'score': [ScoreEventPayload],
Expand Down
4 changes: 4 additions & 0 deletions src/detectors/AudioDesyncDetector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export class AudioDesyncDetector implements Detector {
) {

}
public lastDesyncDuration?: number;
private _startedDesyncAt?: number;
private _prevCorrectedSamples = 0;

Expand Down Expand Up @@ -42,6 +43,9 @@ export class AudioDesyncDetector implements Detector {

if (!inboundRtp.desync) {
if (wasDesync) {
if (this._startedDesyncAt) {
this.lastDesyncDuration = Date.now() - this._startedDesyncAt;
}
this._startedDesyncAt = undefined;
}
return;
Expand Down
15 changes: 12 additions & 3 deletions src/detectors/DryInboundTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,24 @@ export class DryInboundTrackDetector implements Detector {
}

private get config() {
return this.peerConnection.parent.config.stuckedInboundTrackDetector;
return this.peerConnection.parent.config.dryInboundTrackDetector;
}

private _activatedAt?: number;

public update() {
if (this._evented || this.config.disabled) return;
if (this.trackMonitor.getInboundRtp()?.bytesReceived !== 0) return;
const inboundRtp = this.trackMonitor.getInboundRtp();
if (this.trackMonitor.remoteOutboundTrackPaused) {
this._activatedAt = undefined;
return;
}

if (!this._activatedAt) {
this._activatedAt = Date.now();
}

const duration = Date.now() - inboundRtp.addedAt;
const duration = Date.now() - this._activatedAt;

if (duration < this.config.thresholdInMs) return;

Expand Down
50 changes: 50 additions & 0 deletions src/detectors/DryOutboundTrack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { OutboundTrackMonitor } from "../monitors/OutboundTrackMonitor";
import { Detector } from "./Detector";


export class DryOutboundTrackDetector implements Detector {
public readonly name = 'dry-outbound-track-detector';

public constructor(
public readonly trackMonitor: OutboundTrackMonitor,
) {
}

private _evented = false;

private get peerConnection() {
return this.trackMonitor.getPeerConnection();
}

private get config() {
return this.peerConnection.parent.config.dryOutboundTrackDetector;
}

private _activatedAt?: number;

public update() {
if (this._evented || this.config.disabled) return;
if (this.trackMonitor.getOutboundRtps()?.[0].bytesSent !== 0) return;
if (this.trackMonitor.track.muted || this.trackMonitor.track.readyState !== 'live') {
this._activatedAt = undefined;
return;
}

if (!this._activatedAt) {
this._activatedAt = Date.now();
}

const duration = Date.now() - this._activatedAt;

if (duration < this.config.thresholdInMs) return;

this._evented = true;

const clientMonitor = this.peerConnection.parent;

clientMonitor.emit('dry-outbound-track', {
trackMonitor: this.trackMonitor,
clientMonitor: clientMonitor,
});
}
}
47 changes: 47 additions & 0 deletions src/detectors/IceTupleChangeDetector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { PeerConnectionMonitor } from "../monitors/PeerConnectionMonitor";
import { Detector } from "./Detector";

export class IceTupleChangeDetector implements Detector {
public readonly name = 'ice-tuple-change-detector';

public constructor(
public readonly pcMonitor: PeerConnectionMonitor,
) {
}

public readonly tuples = new Set<string>();

public update() {
if (this.pcMonitor.closed) return;

const selectedIceCandidatePairs = this.pcMonitor.selectedIceCandidatePairs;
const wasEmpty = this.tuples.size === 0;
let changed = false;
const curentTuples = new Set<string>();

for (const pair of selectedIceCandidatePairs) {
const local = pair.getLocalCandidate();
const remote = pair.getRemoteCandidate();
const tuple = `${local?.address}:${local?.port}:${remote?.address}:${remote?.port}:${local?.protocol}`;

curentTuples.add(tuple);
if (!this.tuples.has(tuple)) {
changed = true;
this.tuples.add(tuple);
}
}
for (const tuple of this.tuples) {
if (!curentTuples.has(tuple)) {
changed = true;
this.tuples.delete(tuple);
}
}

if (wasEmpty || !changed) return;

this.pcMonitor.parent.emit('ice-tuple-changed', {
clientMonitor: this.pcMonitor.parent,
peerConnectionMonitor: this.pcMonitor,
});
}
}
7 changes: 1 addition & 6 deletions src/monitors/InboundTrackMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@ import { InboundRtpMonitor } from "./InboundRtpMonitor";
import { OutboundTrackSample } from "../schema/ClientSample";

export class InboundTrackMonitor {
public static applyOnAppDataAtSampling = <T extends Record<string, unknown> = Record<string, unknown>>(appData: Record<string, unknown>) => {
return {
...appData,
};
}

public readonly direction = 'inbound';
public readonly detectors: Detectors;
// public contentType: 'lowmotion' | 'highmotion' | 'standard' = 'standard';
public dtxMode = false;
public remoteOutboundTrackPaused = false;

public calculatedScore: CalculatedScore = {
weight: this.kind === 'audio' ? 1 : 2,
Expand Down
5 changes: 4 additions & 1 deletion src/monitors/OutboundTrackMonitor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Detectors } from "../detectors/Detectors";
import { DryOutboundTrackDetector } from "../detectors/DryOutboundTrack";
import { InboundTrackSample } from "../schema/ClientSample";
import { CalculatedScore } from "../scores/CalculatedScore";
import { MediaSourceMonitor } from "./MediaSourceMonitor";
Expand Down Expand Up @@ -36,7 +37,9 @@ export class OutboundTrackMonitor {
attachments?: Record<string, unknown>,
) {
this.attachments = attachments;
this.detectors = new Detectors();
this.detectors = new Detectors(
new DryOutboundTrackDetector(this),
);
}


Expand Down
2 changes: 2 additions & 0 deletions src/monitors/PeerConnectionMonitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { CongestionDetector } from "../detectors/CongestionDetector";
import { InboundTrackMonitor } from "./InboundTrackMonitor";
import { OutboundTrackMonitor } from "./OutboundTrackMonitor";
import { CalculatedScore } from "../scores/CalculatedScore";
import { IceTupleChangeDetector } from "../detectors/IceTupleChangeDetector";

const logger = createLogger('PeerConnectionMonitor');

Expand Down Expand Up @@ -142,6 +143,7 @@ export class PeerConnectionMonitor extends EventEmitter {
this.detectors = new Detectors(
new LongPcConnectionEstablishmentDetector(this),
new CongestionDetector(this),
new IceTupleChangeDetector(this),
);
}

Expand Down

0 comments on commit ff67f0f

Please sign in to comment.