From a5783c52f5983df7a41c0808c0afae9420134859 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 7 Mar 2019 14:13:57 +0100 Subject: [PATCH] openvidu-browser: Stream webrtc stats gathering foundation --- openvidu-browser/src/OpenVidu/Stream.ts | 151 ++++++++++++++++++++++++ 1 file changed, 151 insertions(+) diff --git a/openvidu-browser/src/OpenVidu/Stream.ts b/openvidu-browser/src/OpenVidu/Stream.ts index 4131a96d..34254f56 100644 --- a/openvidu-browser/src/OpenVidu/Stream.ts +++ b/openvidu-browser/src/OpenVidu/Stream.ts @@ -846,6 +846,23 @@ export class Stream implements EventDispatcher { private initWebRtcStats(): void { this.webRtcStats = new WebRtcStats(this); this.webRtcStats.initWebRtcStats(); + + //TODO: send common webrtc stats from client to openvidu-server + /*if (this.session.openvidu.webrtcStatsInterval > 0) { + setInterval(() => { + this.gatherStatsForPeer().then(jsonStats => { + const body = { + sessionId: this.session.sessionId, + participantPrivateId: this.connection.rpcSessionId, + stats: jsonStats + } + var xhr = new XMLHttpRequest(); + xhr.open('POST', this.session.openvidu.httpUri + '/elasticsearch/webrtc-stats', true); + xhr.setRequestHeader('Content-Type', 'application/json'); + xhr.send(JSON.stringify(body)); + }) + }, this.session.openvidu.webrtcStatsInterval * 1000); + }*/ } private stopWebRtcStats(): void { @@ -868,4 +885,138 @@ export class Stream implements EventDispatcher { return returnValue; } + private gatherStatsForPeer(): Promise { + return new Promise((resolve, reject) => { + if (this.isLocal()) { + + // Publisher stream stats + + this.getRTCPeerConnection().getSenders().forEach(sender => sender.getStats() + .then( + response => { + response.forEach(report => { + + if (this.isReportWanted(report)) { + + const finalReport = {}; + + finalReport['type'] = report.type; + finalReport['timestamp'] = report.timestamp; + finalReport['id'] = report.id; + + // Common to Chrome, Firefox and Safari + if (report.type === 'outbound-rtp') { + finalReport['ssrc'] = report.ssrc; + finalReport['firCount'] = report.firCount; + finalReport['pliCount'] = report.pliCount; + finalReport['nackCount'] = report.nackCount; + finalReport['qpSum'] = report.qpSum; + + // Set media type + if (!!report.kind) { + finalReport['mediaType'] = report.kind; + } else if (!!report.mediaType) { + finalReport['mediaType'] = report.mediaType; + } else { + // Safari does not have 'mediaType' defined for inbound-rtp. Must be inferred from 'id' field + finalReport['mediaType'] = (report.id.indexOf('VideoStream') !== -1) ? 'video' : 'audio'; + } + + if (finalReport['mediaType'] === 'video') { + finalReport['framesEncoded'] = report.framesEncoded; + } + + finalReport['packetsSent'] = report.packetsSent; + finalReport['bytesSent'] = report.bytesSent; + } + + // Only for Chrome and Safari + if (report.type === 'candidate-pair' && report.totalRoundTripTime !== undefined) { + // This is the final selected candidate pair + finalReport['availableOutgoingBitrate'] = report.availableOutgoingBitrate; + finalReport['rtt'] = report.currentRoundTripTime; + finalReport['averageRtt'] = report.totalRoundTripTime / report.responsesReceived; + } + + // Only for Firefox >= 66.0 + if (report.type === 'remote-inbound-rtp' || report.type === 'remote-outbound-rtp') { + + } + + console.log(finalReport); + } + }); + })); + } else { + + // Subscriber stream stats + + this.getRTCPeerConnection().getReceivers().forEach(receiver => receiver.getStats() + .then( + response => { + response.forEach(report => { + + if (this.isReportWanted(report)) { + + const finalReport = {}; + + finalReport['type'] = report.type; + finalReport['timestamp'] = report.timestamp; + finalReport['id'] = report.id; + + // Common to Chrome, Firefox and Safari + if (report.type === 'inbound-rtp') { + finalReport['ssrc'] = report.ssrc; + finalReport['firCount'] = report.firCount; + finalReport['pliCount'] = report.pliCount; + finalReport['nackCount'] = report.nackCount; + finalReport['qpSum'] = report.qpSum; + + // Set media type + if (!!report.kind) { + finalReport['mediaType'] = report.kind; + } else if (!!report.mediaType) { + finalReport['mediaType'] = report.mediaType; + } else { + // Safari does not have 'mediaType' defined for inbound-rtp. Must be inferred from 'id' field + finalReport['mediaType'] = (report.id.indexOf('VideoStream') !== -1) ? 'video' : 'audio'; + } + + if (finalReport['mediaType'] === 'video') { + finalReport['framesDecoded'] = report.framesDecoded; + } + + finalReport['packetsReceived'] = report.packetsReceived; + finalReport['packetsLost'] = report.packetsLost; + finalReport['jitter'] = report.jitter; + finalReport['bytesReceived'] = report.bytesReceived; + } + + // Only for Chrome and Safari + if (report.type === 'candidate-pair' && report.totalRoundTripTime !== undefined) { + // This is the final selected candidate pair + finalReport['availableIncomingBitrate'] = report.availableIncomingBitrate; + finalReport['rtt'] = report.currentRoundTripTime; + finalReport['averageRtt'] = report.totalRoundTripTime / report.responsesReceived; + } + + // Only for Firefox >= 66.0 + if (report.type === 'remote-inbound-rtp' || report.type === 'remote-outbound-rtp') { + + } + console.log(finalReport); + } + }) + }) + ) + } + }); + } + + private isReportWanted(report: any): boolean { + return report.type === 'inbound-rtp' && !this.isLocal() || + report.type === 'outbound-rtp' && this.isLocal() || + (report.type === 'candidate-pair' && report.nominated && report.bytesSent > 0); + } + } \ No newline at end of file