UNPKG

infobip-rtc

Version:

Infobip RTC JavaScript SDK - Infobip WebRTC API Implementation

188 lines 9.59 kB
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