diff --git a/README.md b/README.md index c54a0f2..c9067f7 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,27 @@ var pc = new RTCPeerConnection(yourConfiguration, { }) ``` +The new peerConnection object offers additional functions and callbacks: +```javascript +/** + * This is the rtcstatistic id ("PC_0", "PC_1", ...) assigned while constructing the peerConnection object + */ +var assignedID = pc.getRtcStatsId(); + +/** + * This is an optional callback that will be called after statistics have been fetched from the peerConnection + * It can be used to + * * modify or filter data from the statistics + * * add own data to the statistics you need to have in the results + * (reflect status changes on the signalling layer you want to see in association with the statistics) + * (e.g. switching from simulcast layers) + */ + pc.statsCallback = function(rawData: RTCStatsReport) => RTCStatsReport + + +``` + + If that integration is not possible there is a fallback integration which allows sending per-client information about the user id and conference id. This can be used by calling diff --git a/rtcstats.d.ts b/rtcstats.d.ts index 647e8b6..64c9629 100644 --- a/rtcstats.d.ts +++ b/rtcstats.d.ts @@ -8,6 +8,34 @@ export type RTCStatsDataType = RTCConfiguration | RTCIceCandidate | RTCSignaling RTCPeerConnectionState | undefined | ondatachannelArgs | string | RTCOfferOptions | undefined | createOfferArgs | createAnswerArgs | RTCSessionDescriptionInit | addIceCandidateArgs | object; +/** + * Type definition for an indexed object provided and returned in the statsCallback + */ +export interface RTCStatsData { + [index: string]: any +} +/** + * The extended functions of the peerConnection are exposed with this interface. + * Simply cast the peerConnection to this type to make use of em. + * const pc = new RTCPeerConnection(arg) as RTCStatsPeerConnection; + */ +export interface RTCStatsPeerConnection extends RTCPeerConnection +{ + /** + * This is the rtcstatistic id ("PC_0", "PC_1", ...) assigned while constructing the peerConnection object + */ + public getRtcStatsId(): string; + /** + * This is an optional callback that will be called after statistics have been fetched from the peerConnection + * It can be used to + * * modify or filter data from the statistics + * * add own data to the statistics you need to have in the results + * (reflect status changes on the signalling layer you want to see in association with the statistics) + * (e.g. switching from simulcast layers) + */ + public statsCallback?: (rawData: RTCStatsData) => RTCStatsData; +} + declare module "rtcstats" { /** * Initializes the logging and statistics callback into the trace method for all noted methods diff --git a/rtcstats.js b/rtcstats.js index 8278fee..3f57c91 100644 --- a/rtcstats.js +++ b/rtcstats.js @@ -52,23 +52,6 @@ function deltaCompression(oldStats, newStats) { return newStats; } -function mangleChromeStats(pc, response) { - var standardReport = {}; - var reports = response.result(); - reports.forEach(function(report) { - var standardStats = { - id: report.id, - timestamp: report.timestamp.getTime(), - type: report.type, - }; - report.names().forEach(function(name) { - standardStats[name] = report.stat(name); - }); - standardReport[standardStats.id] = standardStats; - }); - return standardReport; -} - function dumpStream(stream) { return { id: stream.id, @@ -124,10 +107,30 @@ module.exports = function(trace, getStatsInterval, prefixesToWrap) { } var origPeerConnection = window[prefix + 'RTCPeerConnection']; var peerconnection = function(config, constraints) { - var pc = new origPeerConnection(config, constraints); + + // Chrome does not accept if the constraints contain something it is not aware of + // So we make a real copy and remove stuff we use internally + var constraintsCopy = JSON.parse(JSON.stringify(constraints)); + if(constraintsCopy.rtcStatsClientId) + delete constraintsCopy.rtcStatsClientId; + if(constraintsCopy.rtcStatsPeerId) + delete constraintsCopy.rtcStatsPeerId; + if(constraintsCopy.rtcStatsConferenceId) + delete constraintsCopy.rtcStatsConferenceId; + + var pc = new origPeerConnection(config, constraintsCopy); var id = 'PC_' + peerconnectioncounter++; pc.__rtcStatsId = id; + // The optional callback that is invoked after having received the statistics via getStats() + var callback = undefined; + pc.statsCallback = callback; + + // Retrieve the rtcstats id used from outside + pc.getRtcStatsId = function() { + return pc.__rtcStatsId; + }; + if (!config) { config = { nullConfig: true }; } @@ -186,21 +189,16 @@ module.exports = function(trace, getStatsInterval, prefixesToWrap) { var prev = {}; var getStats = function() { - if (isFirefox || isSafari) { - pc.getStats(null).then(function(res) { - var now = map2obj(res); - var base = JSON.parse(JSON.stringify(now)); // our new prev - trace('getstats', id, deltaCompression(prev, now)); - prev = base; - }); - } else { - pc.getStats(function(res) { - var now = mangleChromeStats(pc, res); - var base = JSON.parse(JSON.stringify(now)); // our new prev - trace('getstats', id, deltaCompression(prev, now)); - prev = base; - }); - } + pc.getStats(null).then(function(res) { + // If the callback has been set we call it now to let the implementation modify the statics + // e.g. add own properties from the signalling layer + var now = map2obj(res); + if(pc.statsCallback) + now = pc.statsCallback(now); + var base = JSON.parse(JSON.stringify(now)); // our new prev + trace('getstats', id, deltaCompression(prev, now)); + prev = base; + }); }; // TODO: do we want one big interval and all peerconnections // queried in that or one setInterval per PC?