UNPKG

@twilio/voice-sdk

Version:
217 lines 16.3 kB
"use strict"; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getRTCIceCandidateStatsReport = exports.getRTCStats = void 0; /** * @packageDocumentation * @module Voice * @internalapi */ // @ts-nocheck // tslint:disable no-empty var errors_1 = require("../errors"); var mockrtcstatsreport_1 = require("./mockrtcstatsreport"); var ERROR_PEER_CONNECTION_NULL = 'PeerConnection is null'; var ERROR_WEB_RTC_UNSUPPORTED = 'WebRTC statistics are unsupported'; /** * Helper function to find a specific stat from a report. * Some environment provide the stats report as a map (regular browsers) * but some provide stats report as an array (citrix vdi) * @private */ function findStatById(report, id) { if (typeof report.get === 'function') { return report.get(id); } return report.find(function (s) { return s.id === id; }); } /** * Generate WebRTC statistics report for the given {@link PeerConnection} * @param {PeerConnection} peerConnection - Target connection. * @return {Promise<RTCStatsReport>} WebRTC RTCStatsReport object */ function getRTCStatsReport(peerConnection) { if (!peerConnection) { return Promise.reject(new errors_1.InvalidArgumentError(ERROR_PEER_CONNECTION_NULL)); } if (typeof peerConnection.getStats !== 'function') { return Promise.reject(new errors_1.NotSupportedError(ERROR_WEB_RTC_UNSUPPORTED)); } var promise; try { promise = peerConnection.getStats(); } catch (e) { promise = new Promise(function (resolve) { return peerConnection.getStats(resolve); }).then(mockrtcstatsreport_1.default.fromRTCStatsResponse); } return promise; } /** * @typedef {Object} StatsOptions * Used for testing to inject and extract methods. * @property {function} [createRTCSample] - Method for parsing an RTCStatsReport */ /** * Collects any WebRTC statistics for the given {@link PeerConnection} * @param {PeerConnection} peerConnection - Target connection. * @param {StatsOptions} options - List of custom options. * @return {Promise<RTCSample>} Universally-formatted version of RTC stats. */ function getRTCStats(peerConnection, options) { options = Object.assign({ createRTCSample: createRTCSample }, options); return getRTCStatsReport(peerConnection).then(options.createRTCSample); } exports.getRTCStats = getRTCStats; /** * Generate WebRTC stats report containing relevant information about ICE candidates for the given {@link PeerConnection} * @param {PeerConnection} peerConnection - Target connection. * @return {Promise<RTCIceCandidateStatsReport>} RTCIceCandidateStatsReport object */ function getRTCIceCandidateStatsReport(peerConnection) { return getRTCStatsReport(peerConnection).then(function (report) { // Find the relevant information needed to determine selected candidates later var _a = Array.from(report.values()).reduce(function (rval, stat) { ['candidatePairs', 'localCandidates', 'remoteCandidates'].forEach(function (prop) { if (!rval[prop]) { rval[prop] = []; } }); switch (stat.type) { case 'candidate-pair': rval.candidatePairs.push(stat); break; case 'local-candidate': rval.localCandidates.push(stat); break; case 'remote-candidate': rval.remoteCandidates.push(stat); break; case 'transport': // This transport is the one being used if selectedCandidatePairId is populated if (stat.selectedCandidatePairId) { rval.transport = stat; } break; } return rval; }, {}), candidatePairs = _a.candidatePairs, localCandidates = _a.localCandidates, remoteCandidates = _a.remoteCandidates, transport = _a.transport; // This is a report containing information about the selected candidates, such as IDs // This is coming from WebRTC stats directly and doesn't contain the actual ICE Candidates info var selectedCandidatePairReport = candidatePairs.find(function (pair) { // Firefox return pair.selected || // Spec-compliant way (transport && pair.id === transport.selectedCandidatePairId); }); var selectedIceCandidatePairStats; if (selectedCandidatePairReport) { selectedIceCandidatePairStats = { localCandidate: localCandidates.find(function (candidate) { return candidate.id === selectedCandidatePairReport.localCandidateId; }), remoteCandidate: remoteCandidates.find(function (candidate) { return candidate.id === selectedCandidatePairReport.remoteCandidateId; }), }; } // Build the return object return { iceCandidateStats: __spreadArrays(localCandidates, remoteCandidates), selectedIceCandidatePairStats: selectedIceCandidatePairStats, }; }); } exports.getRTCIceCandidateStatsReport = getRTCIceCandidateStatsReport; /** * @typedef {Object} RTCSample - A sample containing relevant WebRTC stats information. * @property {Number} [timestamp] * @property {String} [codecName] - MimeType name of the codec being used by the outbound audio stream * @property {Number} [rtt] - Round trip time * @property {Number} [jitter] * @property {Number} [packetsSent] * @property {Number} [packetsLost] * @property {Number} [packetsReceived] * @property {Number} [bytesReceived] * @property {Number} [bytesSent] * @property {Number} [localAddress] * @property {Number} [remoteAddress] */ function RTCSample() { } /** * Create an RTCSample object from an RTCStatsReport * @private * @param {RTCStatsReport} statsReport * @returns {RTCSample} */ function createRTCSample(statsReport) { var activeTransportId = null; var sample = new RTCSample(); var fallbackTimestamp; Array.from(statsReport.values()).forEach(function (stats) { // Skip isRemote tracks which will be phased out completely and break in FF66. if (stats.isRemote) { return; } // Firefox hack -- Older firefox doesn't have dashes in type names var type = stats.type.replace('-', ''); fallbackTimestamp = fallbackTimestamp || stats.timestamp; // (rrowland) As I understand it, this is supposed to come in on remote-inbound-rtp but it's // currently coming in on remote-outbound-rtp, so I'm leaving this outside the switch until // the appropriate place to look is cleared up. if (stats.remoteId) { var remote = findStatById(statsReport, stats.remoteId); if (remote && remote.roundTripTime) { sample.rtt = remote.roundTripTime * 1000; } } switch (type) { case 'inboundrtp': sample.timestamp = sample.timestamp || stats.timestamp; sample.jitter = stats.jitter * 1000; sample.packetsLost = stats.packetsLost; sample.packetsReceived = stats.packetsReceived; sample.bytesReceived = stats.bytesReceived; break; case 'outboundrtp': sample.timestamp = stats.timestamp; sample.packetsSent = stats.packetsSent; sample.bytesSent = stats.bytesSent; if (stats.codecId) { var codec = findStatById(statsReport, stats.codecId); sample.codecName = codec ? codec.mimeType && codec.mimeType.match(/(.*\/)?(.*)/)[2] : stats.codecId; } break; case 'transport': activeTransportId = stats.id; break; } }); if (!sample.timestamp) { sample.timestamp = fallbackTimestamp; } var activeTransport = findStatById(statsReport, activeTransportId); if (!activeTransport) { return sample; } var selectedCandidatePair = findStatById(statsReport, activeTransport.selectedCandidatePairId); if (!selectedCandidatePair) { return sample; } var localCandidate = findStatById(statsReport, selectedCandidatePair.localCandidateId); var remoteCandidate = findStatById(statsReport, selectedCandidatePair.remoteCandidateId); if (!sample.rtt) { sample.rtt = selectedCandidatePair && (selectedCandidatePair.currentRoundTripTime * 1000); } Object.assign(sample, { // ip is deprecated. use address first then ip if on older versions of browser localAddress: localCandidate && (localCandidate.address || localCandidate.ip), remoteAddress: remoteCandidate && (remoteCandidate.address || remoteCandidate.ip), }); return sample; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWIvdHdpbGlvL3J0Yy9zdGF0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7Ozs7R0FJRztBQUNILGNBQWM7QUFDZCwwQkFBMEI7QUFDMUIsb0NBQW9FO0FBQ3BFLDJEQUFzRDtBQUV0RCxJQUFNLDBCQUEwQixHQUFHLHdCQUF3QixDQUFDO0FBQzVELElBQU0seUJBQXlCLEdBQUcsbUNBQW1DLENBQUM7QUFFdEU7Ozs7O0dBS0c7QUFDSCxTQUFTLFlBQVksQ0FBQyxNQUFNLEVBQUUsRUFBRTtJQUM5QixJQUFJLE9BQU8sTUFBTSxDQUFDLEdBQUcsS0FBSyxVQUFVLEVBQUU7UUFDcEMsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0tBQ3ZCO0lBQ0QsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQUEsQ0FBQyxJQUFJLE9BQUEsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQVgsQ0FBVyxDQUFDLENBQUM7QUFDdkMsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLGlCQUFpQixDQUFDLGNBQWM7SUFDdkMsSUFBSSxDQUFDLGNBQWMsRUFBRTtRQUNuQixPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSw2QkFBb0IsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLENBQUM7S0FDN0U7SUFFRCxJQUFJLE9BQU8sY0FBYyxDQUFDLFFBQVEsS0FBSyxVQUFVLEVBQUU7UUFDakQsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksMEJBQWlCLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDO0tBQ3pFO0lBRUQsSUFBSSxPQUFPLENBQUM7SUFDWixJQUFJO1FBQ0YsT0FBTyxHQUFHLGNBQWMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztLQUNyQztJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsT0FBTyxHQUFHLElBQUksT0FBTyxDQUFD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