infobip-rtc
Version:
Infobip RTC JavaScript SDK - Infobip WebRTC API Implementation
188 lines • 9.59 kB
JavaScript
import { NetworkQualityStatistics } from "./media/NetworkQualityStatistics";
import { MediaStatsAdapter } from "./media/MediaStatsAdapter";
import { CallMediaStatsLog, SelectedIceCandidatePairLog } from "../Log";
import { MediaStatsDiffUtil } from "./media/MediaStatsDiffUtil";
import { TotalMediaStats } from "../../call/stats/TotalMediaStats";
import { AudioStats } from "../../call/stats/AudioStats";
import { CurrentMediaStats } from "../../call/stats/CurrentMediaStats";
export class PeerConnectionMediaMonitor {
constructor(callId, name, conferenceId, pc, isVideo, logger) {
this.callId = callId;
this.name = name;
this.conferenceId = conferenceId;
this.pc = pc;
this.isVideo = isVideo;
this.logger = logger;
this.previousConferenceStats = new Map();
this.summaryInterval = setInterval(() => this.sendSummaryStats(), PeerConnectionMediaMonitor.DEFAULT_MONITOR_SUMMARY_INTERVAL);
this.trackMonitoringInterval = setInterval(() => this.sendTrackStats(), PeerConnectionMediaMonitor.DEFAULT_MONITOR_TRACK_INTERVAL);
}
setIsVideo(isVideo) {
this.isVideo = isVideo;
}
stop() {
let totalMediaStats = this.sendTotalCallStats();
clearInterval(this.summaryInterval);
clearInterval(this.trackMonitoringInterval);
return totalMediaStats;
}
onNetworkQualityStatistics(callback) {
this.networkQualityStatisticsListener = callback;
}
sendSelectedCandidatePair(rtcStatsReport) {
if (!this.selectedCandidatePair) {
let selectedCandidatePair = MediaStatsAdapter.extractSelectedCandidatePair(rtcStatsReport);
if (selectedCandidatePair) {
this.logger.log((new SelectedIceCandidatePairLog(this.callId, selectedCandidatePair)));
this.selectedCandidatePair = selectedCandidatePair;
}
}
}
sendTotalCallStats() {
let totalMediaStats = new TotalMediaStats();
this.previousConferenceStats.forEach((callStats, trackId) => {
var _a;
if (trackId) {
if (!this.isVideo) {
this.fillAudioStats(callStats, totalMediaStats.totalAudioStats);
}
this.sendExtractedStats(callStats, trackId, "Total");
}
else {
if (!this.isVideo) {
totalMediaStats.totalAudioStats.roundTripTime = (_a = callStats.callStats.currentRoundTripTime) !== null && _a !== void 0 ? _a : 0;
}
this.sendExtractedMediaStats(callStats, callStats.callStats.timestamp, null, "Total");
}
});
return totalMediaStats;
}
sendTrackStats() {
if (!this.callId && !this.conferenceId) {
return;
}
if (!this.pc || !PeerConnectionMediaMonitor.MONITOR_ICE_STATES.has(this.pc.iceConnectionState)) {
return;
}
this.pc.getSenders().forEach(sender => this.sendStatsForTrack(sender.track));
this.pc.getReceivers().forEach(receiver => this.sendStatsForTrack(receiver.track));
}
sendSummaryStats() {
if (!this.callId && !this.conferenceId) {
return;
}
if (!this.pc || !PeerConnectionMediaMonitor.MONITOR_ICE_STATES.has(this.pc.iceConnectionState)) {
return;
}
this.sendSummaryStatsForPeerConnection();
}
sendStatsForTrack(track) {
if (!track) {
return;
}
const trackId = track === null || track === void 0 ? void 0 : track.id;
const trackLabel = (track === null || track === void 0 ? void 0 : track.label) || (this.name + "_" + trackId);
this.sendStatsForLabeledTrack(track, trackLabel || "unknown");
}
emitNetworkQualityStats(previousCallStats, diffStats) {
const remoteAudioStats = diffStats.remoteAudio;
if (!remoteAudioStats) {
return;
}
const localAudioStats = diffStats.localAudio;
if (!localAudioStats) {
return;
}
if (!diffStats.callStats.currentRoundTripTime) {
return;
}
const networkQualityStatistics = NetworkQualityStatistics.forRTCStats(diffStats.callStats.currentRoundTripTime, remoteAudioStats.jitter, remoteAudioStats.packetsReceived, remoteAudioStats.packetsLost, remoteAudioStats.codec || localAudioStats.codec);
if (previousCallStats || networkQualityStatistics.mos !== 1.0) {
diffStats.callStats.mos = networkQualityStatistics.mos;
if (this.networkQualityStatisticsListener) {
let currentMediaStats = this.getCurrentMediaStats(diffStats);
this.networkQualityStatisticsListener(networkQualityStatistics, currentMediaStats);
}
}
}
getCurrentMediaStats(diffStats) {
var _a, _b;
let currentMediaStats = new CurrentMediaStats();
let currentAudioStats = new AudioStats();
currentAudioStats.roundTripTime = (_a = diffStats.callStats.currentRoundTripTime) !== null && _a !== void 0 ? _a : 0;
currentAudioStats.jitter = diffStats.remoteAudio.jitter;
currentAudioStats.codec = (_b = diffStats.remoteAudio.codec) !== null && _b !== void 0 ? _b : diffStats.localAudio.codec;
currentAudioStats.packetsLost = diffStats.remoteAudio.packetsLost;
currentAudioStats.packetsReceived = diffStats.remoteAudio.packetsReceived;
currentAudioStats.bytesReceived = diffStats.remoteAudio.bytesReceived;
currentAudioStats.packetsSent = diffStats.localAudio.packetsSent;
currentAudioStats.retransmittedPacketsSent = diffStats.localAudio.retransmittedPacketsSent;
currentAudioStats.bytesSent = diffStats.localAudio.bytesSent;
currentAudioStats.retransmittedBytesSent = diffStats.localAudio.retransmittedBytesSent;
currentMediaStats.currentAudioStats = currentAudioStats;
return currentMediaStats;
}
sendSummaryStatsForPeerConnection() {
this.pc.getStats()
.then(rtcStatsReport => {
let currentCallStats = MediaStatsAdapter.extract(rtcStatsReport, this.isVideo);
let previousCallStats = this.previousConferenceStats.get(null);
let diffCallStats = MediaStatsDiffUtil.diff(previousCallStats, currentCallStats, this.isVideo);
this.emitNetworkQualityStats(previousCallStats, diffCallStats);
this.sendExtractedMediaStats(diffCallStats, diffCallStats.callStats.timestamp, null, this.name);
this.previousConferenceStats.set(null, currentCallStats);
this.sendSelectedCandidatePair(rtcStatsReport);
});
}
sendStatsForLabeledTrack(track, label) {
this.pc.getStats(track)
.then(rtcStatsReport => {
let currentCallStats = MediaStatsAdapter.extract(rtcStatsReport, this.isVideo);
let previousCallStats = this.previousConferenceStats.get(track.id);
let diffCallStats = MediaStatsDiffUtil.diff(previousCallStats, currentCallStats, this.isVideo);
this.sendExtractedStats(diffCallStats, track.id, label);
this.previousConferenceStats.set(track.id, currentCallStats);
this.sendSelectedCandidatePair(rtcStatsReport);
});
}
sendExtractedMediaStats(data, timestamp, trackId, label) {
data.trackId = trackId || data["id"];
this.logger.log(new CallMediaStatsLog(label, this.conferenceId, this.callId, this.name, data, timestamp));
}
sendExtractedStats(diffCallStats, trackId, label) {
diffCallStats.extractedRemoteStats.forEach(remoteStats => this.sendExtractedMediaStats(remoteStats, diffCallStats.callStats.timestamp, trackId, label));
diffCallStats.extractedLocalStats.forEach(localStats => this.sendExtractedMediaStats(localStats, diffCallStats.callStats.timestamp, trackId, label));
}
fillAudioStats(stats, audioStats) {
let audioLocalMediaStats = stats.localAudio;
if (audioLocalMediaStats != null) {
this.fillLocalAudioStats(audioStats, audioLocalMediaStats);
}
let audioRemoteMediaStats = stats.remoteAudio;
if (audioRemoteMediaStats != null) {
this.fillRemoteAudioStats(audioStats, audioRemoteMediaStats);
}
}
fillRemoteAudioStats(audioStats, audioRemoteMediaStats) {
if (audioStats.codec == null) {
audioStats.codec = audioRemoteMediaStats.codec;
}
audioStats.bytesReceived = audioRemoteMediaStats.bytesReceived;
audioStats.packetsReceived = audioRemoteMediaStats.packetsReceived;
audioStats.packetsLost = audioRemoteMediaStats.packetsLost;
audioStats.jitter = audioRemoteMediaStats.jitter;
}
fillLocalAudioStats(audioStats, audioLocalMediaStats) {
if (audioStats.codec == null) {
audioStats.codec = audioLocalMediaStats.codec;
}
audioStats.bytesSent = audioLocalMediaStats.bytesSent;
audioStats.packetsSent = audioLocalMediaStats.packetsSent;
audioStats.retransmittedBytesSent = audioLocalMediaStats.retransmittedBytesSent;
audioStats.retransmittedPacketsSent = audioLocalMediaStats.retransmittedPacketsSent;
}
}
PeerConnectionMediaMonitor.MONITOR_ICE_STATES = new Set(["connected", "completed"]);
PeerConnectionMediaMonitor.DEFAULT_MONITOR_SUMMARY_INTERVAL = 1000;
PeerConnectionMediaMonitor.DEFAULT_MONITOR_TRACK_INTERVAL = 10000;
//# sourceMappingURL=PeerConnectionMediaMonitor.js.map