You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-30 04:23:07 +03:00
Add Jitter to exported webrtc stats (#3270)
* stats: Add Jitter stats * Update src/webrtc/stats/trackStatsReporter.ts Co-authored-by: Robin <robin@robin.town> * stats: Fix typos in tests * stats: differences between 0 and undefined in jitter val --------- Co-authored-by: Robin <robin@robin.town>
This commit is contained in:
@ -87,6 +87,10 @@ describe("StatsReportBuilder", () => {
|
|||||||
["REMOTE_VIDEO_TRACK_ID", { height: 960, width: 1080 }],
|
["REMOTE_VIDEO_TRACK_ID", { height: 960, width: 1080 }],
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
|
jitter: new Map([
|
||||||
|
["REMOTE_AUDIO_TRACK_ID", 0.1],
|
||||||
|
["REMOTE_VIDEO_TRACK_ID", 50],
|
||||||
|
]),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -99,6 +103,7 @@ describe("StatsReportBuilder", () => {
|
|||||||
remoteAudioTrack.setCodec("opus");
|
remoteAudioTrack.setCodec("opus");
|
||||||
remoteAudioTrack.setLoss({ packetsTotal: 20, packetsLost: 0, isDownloadStream: true });
|
remoteAudioTrack.setLoss({ packetsTotal: 20, packetsLost: 0, isDownloadStream: true });
|
||||||
remoteAudioTrack.setBitrate({ download: 4000, upload: 0 });
|
remoteAudioTrack.setBitrate({ download: 4000, upload: 0 });
|
||||||
|
remoteAudioTrack.setJitter(0.1);
|
||||||
|
|
||||||
localVideoTrack.setCodec("v8");
|
localVideoTrack.setCodec("v8");
|
||||||
localVideoTrack.setLoss({ packetsTotal: 30, packetsLost: 6, isDownloadStream: false });
|
localVideoTrack.setLoss({ packetsTotal: 30, packetsLost: 6, isDownloadStream: false });
|
||||||
@ -111,5 +116,6 @@ describe("StatsReportBuilder", () => {
|
|||||||
remoteVideoTrack.setBitrate({ download: 5000000, upload: 0 });
|
remoteVideoTrack.setBitrate({ download: 5000000, upload: 0 });
|
||||||
remoteVideoTrack.setFramerate(60);
|
remoteVideoTrack.setFramerate(60);
|
||||||
remoteVideoTrack.setResolution({ width: 1080, height: 960 });
|
remoteVideoTrack.setResolution({ width: 1080, height: 960 });
|
||||||
|
remoteVideoTrack.setJitter(50);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -246,4 +246,30 @@ describe("TrackStatsReporter", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("should build jitter value in Track Stats", () => {
|
||||||
|
it("and returns track stats without jitter if report not 'inbound-rtp'", async () => {
|
||||||
|
const trackStats = new MediaTrackStats("1", "remote", "video");
|
||||||
|
TrackStatsReporter.buildJitter(trackStats, { jitter: 0.01 });
|
||||||
|
expect(trackStats.getJitter()).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and returns track stats with jitter", async () => {
|
||||||
|
const trackStats = new MediaTrackStats("1", "remote", "video");
|
||||||
|
TrackStatsReporter.buildJitter(trackStats, { type: "inbound-rtp", jitter: 0.01 });
|
||||||
|
expect(trackStats.getJitter()).toEqual(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and returns negative jitter if stats has no jitter value", async () => {
|
||||||
|
const trackStats = new MediaTrackStats("1", "remote", "video");
|
||||||
|
TrackStatsReporter.buildJitter(trackStats, { type: "inbound-rtp" });
|
||||||
|
expect(trackStats.getJitter()).toEqual(-1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("and returns jitter as number", async () => {
|
||||||
|
const trackStats = new MediaTrackStats("1", "remote", "video");
|
||||||
|
TrackStatsReporter.buildJitter(trackStats, { type: "inbound-rtp", jitter: "0.5" });
|
||||||
|
expect(trackStats.getJitter()).toEqual(500);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -45,6 +45,7 @@ export class MediaTrackStats {
|
|||||||
private bitrate: Bitrate = { download: 0, upload: 0 };
|
private bitrate: Bitrate = { download: 0, upload: 0 };
|
||||||
private resolution: Resolution = { width: -1, height: -1 };
|
private resolution: Resolution = { width: -1, height: -1 };
|
||||||
private framerate = 0;
|
private framerate = 0;
|
||||||
|
private jitter = 0;
|
||||||
private codec = "";
|
private codec = "";
|
||||||
private isAlive = true;
|
private isAlive = true;
|
||||||
private isMuted = false;
|
private isMuted = false;
|
||||||
@ -140,4 +141,15 @@ export class MediaTrackStats {
|
|||||||
public get enabled(): boolean {
|
public get enabled(): boolean {
|
||||||
return this.isEnabled;
|
return this.isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setJitter(jitter: number): void {
|
||||||
|
this.jitter = jitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jitter in milliseconds
|
||||||
|
*/
|
||||||
|
public getJitter(): number {
|
||||||
|
return this.jitter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ export interface ConnectionStatsReport {
|
|||||||
resolution: ResolutionMap;
|
resolution: ResolutionMap;
|
||||||
framerate: FramerateMap;
|
framerate: FramerateMap;
|
||||||
codec: CodecMap;
|
codec: CodecMap;
|
||||||
|
jitter: Map<TrackID, number>;
|
||||||
transport: TransportStats[];
|
transport: TransportStats[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ export class StatsReportBuilder {
|
|||||||
};
|
};
|
||||||
const framerates: FramerateMap = { local: new Map<TrackID, number>(), remote: new Map<TrackID, number>() };
|
const framerates: FramerateMap = { local: new Map<TrackID, number>(), remote: new Map<TrackID, number>() };
|
||||||
const codecs: CodecMap = { local: new Map<TrackID, string>(), remote: new Map<TrackID, string>() };
|
const codecs: CodecMap = { local: new Map<TrackID, string>(), remote: new Map<TrackID, string>() };
|
||||||
|
const jitter = new Map<TrackID, number>();
|
||||||
|
|
||||||
let audioBitrateDownload = 0;
|
let audioBitrateDownload = 0;
|
||||||
let audioBitrateUpload = 0;
|
let audioBitrateUpload = 0;
|
||||||
@ -67,6 +68,9 @@ export class StatsReportBuilder {
|
|||||||
resolutions[trackStats.getType()].set(trackId, trackStats.getResolution());
|
resolutions[trackStats.getType()].set(trackId, trackStats.getResolution());
|
||||||
framerates[trackStats.getType()].set(trackId, trackStats.getFramerate());
|
framerates[trackStats.getType()].set(trackId, trackStats.getFramerate());
|
||||||
codecs[trackStats.getType()].set(trackId, trackStats.getCodec());
|
codecs[trackStats.getType()].set(trackId, trackStats.getCodec());
|
||||||
|
if (trackStats.getType() === "remote") {
|
||||||
|
jitter.set(trackId, trackStats.getJitter());
|
||||||
|
}
|
||||||
|
|
||||||
trackStats.resetBitrate();
|
trackStats.resetBitrate();
|
||||||
}
|
}
|
||||||
@ -97,6 +101,7 @@ export class StatsReportBuilder {
|
|||||||
report.framerate = framerates;
|
report.framerate = framerates;
|
||||||
report.resolution = resolutions;
|
report.resolution = resolutions;
|
||||||
report.codec = codecs;
|
report.codec = codecs;
|
||||||
|
report.jitter = jitter;
|
||||||
return report;
|
return report;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +137,7 @@ export class StatsReportGatherer {
|
|||||||
}
|
}
|
||||||
const ts = this.trackStats.findTransceiverByTrackId(trackStats.trackId);
|
const ts = this.trackStats.findTransceiverByTrackId(trackStats.trackId);
|
||||||
TrackStatsReporter.setTrackStatsState(trackStats, ts);
|
TrackStatsReporter.setTrackStatsState(trackStats, ts);
|
||||||
|
TrackStatsReporter.buildJitter(trackStats, now);
|
||||||
} else if (before) {
|
} else if (before) {
|
||||||
byteSentStats.set(trackStats.trackId, StatsValueFormatter.getNonNegativeValue(now.bytesSent));
|
byteSentStats.set(trackStats.trackId, StatsValueFormatter.getNonNegativeValue(now.bytesSent));
|
||||||
TrackStatsReporter.buildBitrateSend(trackStats, now, before);
|
TrackStatsReporter.buildBitrateSend(trackStats, now, before);
|
||||||
|
@ -153,4 +153,18 @@ export class TrackStatsReporter {
|
|||||||
});
|
});
|
||||||
return { audioTrackSummary, videoTrackSummary };
|
return { audioTrackSummary, videoTrackSummary };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static buildJitter(trackStats: MediaTrackStats, statsReport: any): void {
|
||||||
|
if (statsReport.type !== "inbound-rtp") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const jitterStr = statsReport?.jitter;
|
||||||
|
if (jitterStr !== undefined) {
|
||||||
|
const jitter = StatsValueFormatter.getNonNegativeValue(jitterStr);
|
||||||
|
trackStats.setJitter(Math.round(jitter * 1000));
|
||||||
|
} else {
|
||||||
|
trackStats.setJitter(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user