Wondering what’s next for npm?Check out our public roadmap! »

    getstats

    1.2.0 • Public • Published

    getStats.js | WebRTC getStats API

    Single Page Demo or Multi User P2P Demo

    npm downloads Build Status: Linux

    A tiny JavaScript library using WebRTC getStats API to return peer connection stats i.e. bandwidth usage, packets lost, local/remote ip addresses and ports, type of connection etc.

    It is MIT Licenced, which means that you can use it in any commercial/non-commercial product, free of cost.

    getStats

    npm install getstats
    
    cd node_modules
    cd getstats
    node server.js
    
    # and open:
    # http://localhost:9999/
    

    To use it:

    <script src="./node_modules/getstats/getStats.js"></script>

    Link the library

    <script src="https://cdn.webrtc-experiment.com/getStats.js"></script>
     
    <!-- or min.js -->
    <script src="https://cdn.webrtc-experiment.com/getStats.min.js"></script>
     
    <!-- or without CDN -->
    <script src="https://www.webrtc-experiment.com/getStats.js"></script>
     
    <!-- or rawgit -->
    <script src="https://rawgit.com/muaz-khan/getStats/master/getStats.js"></script>

    Or link specific build:

    Or:

    const getStats = require('getstats');
    import { getStats} from 'getstats';

    Usage

    var rtcPeerConnection = new RTCPeerConnection(rtcConfig);
     
    var repeatInterval = 2000; // 2000 ms == 2 seconds
    getStats(rtcPeerConnection, function(result) {
        result.connectionType.remote.ipAddress
        result.connectionType.remote.candidateType
        result.connectionType.transport
        
        result.bandwidth.speed // bandwidth download speed (bytes per second)
        
        // to access native "results" array
        result.results.forEach(function(item) {
            if (item.type === 'ssrc' && item.transportId === 'Channel-audio-1') {
                var packetsLost = item.packetsLost;
                var packetsSent = item.packetsSent;
                var audioInputLevel = item.audioInputLevel;
                var trackId = item.googTrackId; // media stream track id
                var isAudio = item.mediaType === 'audio'; // audio or video
                var isSending = item.id.indexOf('_send') !== -1; // sender or receiver
     
                console.log('SendRecv type', item.id.split('_send').pop());
                console.log('MediaStream track type', item.mediaType);
            }
        });
    }, repeatInterval);

    Safari?

    var audioTrack = stream.getTracks().filter(function(t) {
        return t.kind === 'audio';
    });
     
    getStats(peer, audioTrack, function(results) {
        // rest goes here
    }, 5 * 1000);

    result.datachannel

    // states => open or close
    alert(result.datachannel.state === 'open');

    result.isOfferer

    Offerer is the person who invoked createOffer method.

    result.encryption

    To detect which tech is used to encrypt your connections.

    alert(result.encryption === 'sha-256');

    result.nomore()

    This function can be used to ask to stop invoking getStats API.

    btnStopGetStats.onclick  = function() {
        getStatsResult.nomore();
    };

    result.bandwidth

    You can use result.bandwidth.speed to detect your system's available download speed.

    {
        "speed": 25191,
        "systemBandwidth": 0,
        "sentPerSecond": 0,
        "encodedPerSecond": 0,
        "helper": {
            "audioBytesSent": 103053,
            "videoBytestSent": 0,
            "videoBytesSent": 4316619
        },
        "availableSendBandwidth": "5181906",
        "googActualEncBitrate": "294608",
        "googAvailableSendBandwidth": "5181906",
        "googAvailableReceiveBandwidth": "0",
        "googRetransmitBitrate": "0",
        "googTargetEncBitrate": "1700000",
        "googBucketDelay": "0",
        "googTransmitBitrate": "198296"
    }

    result.audio

    {
        "send": {
            "tracks": ["ab5be64a-00b0-4c69-9ffa-b934a3cdaf92"],
            "codecs": ["opus"],
            "availableBandwidth": "0.4",
            "streams": 1
        },
        "recv": {
            "tracks": ["ab5be64a-00b0-4c69-9ffa-b934a3cdaf92"],
            "codecs": ["opus"],
            "availableBandwidth": "0.4",
            "streams": 1
        },
        "bytesSent": 103053,
        "bytesReceived": 103053
    }

    result.video

    {
        "send": {
            "tracks": ["c07bbd24-4e99-4b94-b429-5174370f8d12"],
            "codecs": ["VP9"],
            "availableBandwidth": "24.2",
            "streams": 1
        },
        "recv": {
            "tracks": ["c07bbd24-4e99-4b94-b429-5174370f8d12"],
            "codecs": ["VP9"],
            "availableBandwidth": "25.5",
            "streams": 1
        },
        "bytesSent": 4316619,
        "bytesReceived": 4294692
    }

    result.connectionType

    {
        "systemNetworkType": "wifi",
        "systemIpAddress": ["192.168.1.2:66666"],
        "local": {
            "candidateType": ["host"],
            "transport": ["udp"],
            "ipAddress": ["192.168.1.2:66666"],
            "networkType": ["wlan"]
        },
        "remote": {
            "candidateType": ["host"],
            "transport": ["udp"],
            "ipAddress": ["192.168.1.2:66666"],
            "networkType": []
        },
        "transport": "udp"
    }

    result.resolutions

    {
        "send": {
            "width": "640",
            "height": "480"
        },
        "recv": {
            "width": "640",
            "height": "480"
        }
    }

    result.results

    It is an array that is returned by browser's native PeerConnection API.

    // "getStatsResult" is your "result" object
    getStatsResult.results.forEach(function(item) {
        if (item.type === 'ssrc' && item.transportId === 'Channel-audio-1') {
            var packetsLost = item.packetsLost;
            var packetsSent = item.packetsSent;
            var audioInputLevel = item.audioInputLevel;
            var trackId = item.googTrackId; // media stream track id
            var isAudio = item.mediaType === 'audio'; // audio or video
            var isSending = item.id.indexOf('_send') !== -1; // sender or receiver
     
            console.log('SendRecv type', item.id.split('_send').pop());
            console.log('MediaStream track type', item.mediaType);
        }
    });

    Above array looks like this:

    [{
        "googTrackId": "ab5be64a-00b0-4c69-9ffa-b934a3cdaf92",
        "id": "googTrack_ab5be64a-00b0-4c69-9ffa-b934a3cdaf92",
        "type": "googTrack",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "googInitiator": "true",
        "id": "googLibjingleSession_2403774673032347671",
        "type": "googLibjingleSession",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "googActualEncBitrate": "294608",
        "googAvailableSendBandwidth": "5181906",
        "googRetransmitBitrate": "0",
        "googAvailableReceiveBandwidth": "0",
        "googTargetEncBitrate": "1700000",
        "googBucketDelay": "0",
        "googTransmitBitrate": "198296",
        "id": "bweforvideo",
        "type": "VideoBwe",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "googTrackId": "c07bbd24-4e99-4b94-b429-5174370f8d12",
        "id": "googTrack_c07bbd24-4e99-4b94-b429-5174370f8d12",
        "type": "googTrack",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "googFingerprint": "8B:---:70",
        "googFingerprintAlgorithm": "sha-256",
        "googDerBase64": "MII----FdhT",
        "id": "googCertificate_8B:---:70",
        "type": "googCertificate",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "googFingerprint": "EE:---:80",
        "googFingerprintAlgorithm": "sha-256",
        "googDerBase64": "MI----kr",
        "id": "googCertificate_EE:13:---:80",
        "type": "googCertificate",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "googComponent": "1",
        "remoteCertificateId": "googCertificate_EE:---:80",
        "selectedCandidatePairId": "Conn-audio-1-0",
        "dtlsCipher": "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
        "localCertificateId": "googCertificate_8B:---:70",
        "srtpCipher": "AES_CM_128_HMAC_SHA1_32",
        "id": "Channel-audio-1",
        "type": "googComponent",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "responsesSent": "12",
        "requestsReceived": "12",
        "googRemoteCandidateType": "local",
        "googReadable": "true",
        "googLocalAddress": "192.168.1.2:61885",
        "consentRequestsSent": "1",
        "googTransportType": "udp",
        "googChannelId": "Channel-audio-1",
        "googLocalCandidateType": "local",
        "googWritable": "true",
        "requestsSent": "12",
        "googRemoteAddress": "192.168.1.2:60256",
        "googRtt": "0",
        "googActiveConnection": "true",
        "packetsDiscardedOnSend": "0",
        "bytesReceived": "4455306",
        "responsesReceived": "12",
        "remoteCandidateId": "Cand-aws75dws",
        "localCandidateId": "Cand-4hzYq0su",
        "bytesSent": "4466782",
        "packetsSent": "5437",
        "id": "Conn-audio-1-0",
        "type": "googCandidatePair",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "portNumber": "61885",
        "networkType": "wlan",
        "ipAddress": "192.168.1.2",
        "transport": "udp",
        "candidateType": "host",
        "priority": "2122260223",
        "id": "Cand-4hzYq0su",
        "type": "localcandidate",
        "timestamp": "2017-11-21T04:09:48.850Z"
    }, {
        "portNumber": "60256",
        "ipAddress": "192.168.1.2",
        "transport": "udp",
        "candidateType": "host",
        "priority": "2122260223",
        "id": "Cand-aws75dws",
        "type": "remotecandidate",
        "timestamp": "2017-11-21T04:09:48.850Z"
    }, {
        "googDecodingCTN": "2206",
        "packetsLost": "0",
        "googSecondaryDecodedRate": "0",
        "googDecodingPLC": "21",
        "packetsReceived": "1056",
        "googExpandRate": "0.900574",
        "googJitterReceived": "1",
        "googDecodingCNG": "0",
        "ssrc": "3719978459",
        "googPreferredJitterBufferMs": "20",
        "googSpeechExpandRate": "0.178711",
        "totalSamplesDuration": "22.06",
        "totalAudioEnergy": "0",
        "transportId": "Channel-audio-1",
        "mediaType": "audio",
        "googDecodingPLCCNG": "72",
        "googCodecName": "opus",
        "googSecondaryDiscardedRate": "0",
        "googDecodingNormal": "2113",
        "googTrackId": "ab5be64a-00b0-4c69-9ffa-b934a3cdaf92",
        "audioOutputLevel": "0",
        "googAccelerateRate": "0",
        "bytesReceived": "103053",
        "googCurrentDelayMs": "61",
        "googDecodingCTSG": "0",
        "googCaptureStartNtpTimeMs": "3720226188883",
        "googPreemptiveExpandRate": "0",
        "googJitterBufferMs": "5",
        "googDecodingMuted": "71",
        "id": "ssrc_3719978459_recv",
        "type": "ssrc",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "audioInputLevel": "38",
        "packetsLost": "0",
        "googTrackId": "ab5be64a-00b0-4c69-9ffa-b934a3cdaf92",
        "googRtt": "1",
        "googResidualEchoLikelihoodRecentMax": "0",
        "googEchoCancellationReturnLossEnhancement": "-100",
        "totalSamplesDuration": "0",
        "googCodecName": "opus",
        "transportId": "Channel-audio-1",
        "mediaType": "audio",
        "aecDivergentFilterFraction": "0",
        "googEchoCancellationReturnLoss": "-100",
        "googResidualEchoLikelihood": "0",
        "googEchoCancellationQualityMin": "0",
        "totalAudioEnergy": "0",
        "ssrc": "4057371623",
        "googJitterReceived": "1",
        "googTypingNoiseState": "false",
        "packetsSent": "1056",
        "bytesSent": "103053",
        "id": "ssrc_4057371623_send",
        "type": "ssrc",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "googContentType": "realtime",
        "googCaptureStartNtpTimeMs": "3720226188863",
        "googTargetDelayMs": "28",
        "packetsLost": "0",
        "googDecodeMs": "3",
        "googFrameHeightReceived": "480",
        "googFrameRateOutput": "2",
        "packetsReceived": "3843",
        "ssrc": "2926085704",
        "googRenderDelayMs": "10",
        "googMaxDecodeMs": "4",
        "googTrackId": "c07bbd24-4e99-4b94-b429-5174370f8d12",
        "googFrameWidthReceived": "640",
        "codecImplementationName": "libvpx",
        "transportId": "Channel-audio-1",
        "mediaType": "video",
        "googTimingFrameInfo": "2498355253,490771956,490771960,490771967,490771967,490771974,0,1",
        "googInterframeDelayMax": "67",
        "googCodecName": "VP9",
        "googFrameRateReceived": "2",
        "qpSum": "35281",
        "framesDecoded": "348",
        "googNacksSent": "0",
        "googFirsSent": "0",
        "bytesReceived": "4294692",
        "googCurrentDelayMs": "28",
        "googMinPlayoutDelayMs": "0",
        "googFrameRateDecoded": "2",
        "googJitterBufferMs": "14",
        "googPlisSent": "0",
        "id": "ssrc_2926085704_recv",
        "type": "ssrc",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }, {
        "googFrameWidthSent": "640",
        "packetsLost": "0",
        "googRtt": "1",
        "googEncodeUsagePercent": "19",
        "googCpuLimitedResolution": "false",
        "googNacksReceived": "0",
        "googBandwidthLimitedResolution": "false",
        "googPlisReceived": "0",
        "googAvgEncodeMs": "7",
        "googTrackId": "c07bbd24-4e99-4b94-b429-5174370f8d12",
        "googFrameRateInput": "2",
        "framesEncoded": "348",
        "codecImplementationName": "libvpx",
        "transportId": "Channel-audio-1",
        "mediaType": "video",
        "googFrameHeightSent": "480",
        "googFrameRateSent": "18",
        "googCodecName": "VP9",
        "qpSum": "35291",
        "googAdaptationChanges": "0",
        "ssrc": "3181351409",
        "googFirsReceived": "0",
        "packetsSent": "3884",
        "bytesSent": "4316619",
        "id": "ssrc_3181351409_send",
        "type": "ssrc",
        "timestamp": "2017-11-21T04:10:10.905Z"
    }]

    Disclaimer

    There is no warranty, expressed or implied, associated with this product. Use at your own risk.

    License

    getStats.js is released under MIT licence . Copyright (c) Muaz Khan.

    Install

    npm i getstats

    DownloadsWeekly Downloads

    2,292

    Version

    1.2.0

    License

    MIT

    Unpacked Size

    114 kB

    Total Files

    8

    Last publish

    Collaborators

    • avatar