-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPeerConnectionStats.js.html
432 lines (355 loc) · 42.4 KB
/
PeerConnectionStats.js.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Adding favicon -->
<!-- Adding meta -->
<!-- Adding external script-->
<!-- Adding external style-->
<!-- Adding scripts-->
<!-- Adding style-->
<!-- Adding overlay script-->
<!-- Adding overlay style-->
<title>
PeerConnectionStats.js
</title>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/third-party/ionicons.min.css">
<link type="text/css" rel="stylesheet" href="styles/third-party/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/reset.css">
<link type="text/css" rel="stylesheet" href="styles/clean-jsdoc-theme-base.css">
<link type="text/css" rel="stylesheet" href="styles/clean-jsdoc-theme-light.css">
<svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
style="display:none">
<defs>
<symbol id="copy-icon" viewbox="0 0 488.3 488.3">
<g>
<path
d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z" />
<path
d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z" />
</g>
</symbol>
<symbol id='search-icon' viewBox="0 0 512 512">
<g>
<g>
<path
d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z" />
</g>
</g>
<g>
<g>
<path
d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z" />
</g>
</g>
</symbol>
<symbol id="down-icon" viewBox="0 0 16 16">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"
>
</path>
</symbol>
</defs>
</svg>
</head>
<body>
<nav class="navbar" id="navbar">
<div class="navbar-heading" id="navbar-heading"><a href="index.html"><h2 class="navbar-heading-text">JavaScript SDK</h2></a></div><div class="search-box" id="search-box"><div class="search-box-input-container"><input class="search-box-input" type="text" placeholder="Search..." id="search-box-input" /><svg class="search-icon" alt="search-icon"><use xlink:href="#search-icon"></use></svg></div><div class="search-item-container" id="search-item-container"><ul class="search-item-ul" id="search-item-ul"></ul></div></div><div class="sidebar-main-content" id="sidebar-main-content"><div class="accordion collapsed" id="7557599" > <h3 class="accordion-heading">Modules<svg><use xlink:href="#down-icon"></use></svg></h3><ul class="accordion-content"><li class="accordion collapsed child" id=8443790><div class="accordion-heading child"><a href="module-Director.html">Director</a><svg><use xlink:href="#down-icon"></use></svg></div><ul class='methods accordion-content'><li data-type='method'><a href="module-Director.html#~getEndpoint">getEndpoint</a></li><li data-type='method'><a href="module-Director.html#~getLiveDomain">getLiveDomain</a></li><li data-type='method'><a href="module-Director.html#~getPublisher">getPublisher</a></li><li data-type='method'><a href="module-Director.html#~getSubscriber">getSubscriber</a></li><li data-type='method'><a href="module-Director.html#~setEndpoint">setEndpoint</a></li><li data-type='method'><a href="module-Director.html#~setLiveDomain">setLiveDomain</a></li></ul></li><li class="accordion collapsed child" id=5836212><div class="accordion-heading child"><a href="module-Logger.html">Logger</a><svg><use xlink:href="#down-icon"></use></svg></div><ul class='methods accordion-content'><li data-type='method'><a href="module-Logger.html#~get">get</a></li><li data-type='method'><a href="module-Logger.html#~getHistory">getHistory</a></li><li data-type='method'><a href="module-Logger.html#~getHistoryMaxSize">getHistoryMaxSize</a></li><li data-type='method'><a href="module-Logger.html#~getLevel">getLevel</a></li><li data-type='method'><a href="module-Logger.html#~setHandler">setHandler</a></li><li data-type='method'><a href="module-Logger.html#~setHistoryMaxSize">setHistoryMaxSize</a></li><li data-type='method'><a href="module-Logger.html#~setLevel">setLevel</a></li></ul></li><li class="accordion collapsed child" id=810655><div class="accordion-heading child"><a href="module-SdpParser.html">SdpParser</a><svg><use xlink:href="#down-icon"></use></svg></div><ul class='methods accordion-content'><li data-type='method'><a href="module-SdpParser.html#~adaptCodecName">adaptCodecName</a></li><li data-type='method'><a href="module-SdpParser.html#~getAvailableHeaderExtensionIdRange">getAvailableHeaderExtensionIdRange</a></li><li data-type='method'><a href="module-SdpParser.html#~getAvailablePayloadTypeRange">getAvailablePayloadTypeRange</a></li><li data-type='method'><a href="module-SdpParser.html#~removeSdpLine">removeSdpLine</a></li><li data-type='method'><a href="module-SdpParser.html#~renegotiate">renegotiate</a></li><li data-type='method'><a href="module-SdpParser.html#~setAbsoluteCaptureTime">setAbsoluteCaptureTime</a></li><li data-type='method'><a href="module-SdpParser.html#~setDependencyDescriptor">setDependencyDescriptor</a></li><li data-type='method'><a href="module-SdpParser.html#~setDTX">setDTX</a></li><li data-type='method'><a href="module-SdpParser.html#~setMultiopus">setMultiopus</a></li><li data-type='method'><a href="module-SdpParser.html#~setSimulcast">setSimulcast</a></li><li data-type='method'><a href="module-SdpParser.html#~setStereo">setStereo</a></li><li data-type='method'><a href="module-SdpParser.html#~setVideoBitrate">setVideoBitrate</a></li><li data-type='method'><a href="module-SdpParser.html#~updateMissingVideoExtensions">updateMissingVideoExtensions</a></li></ul></li></ul> </div><div class="accordion collapsed" id="1490423" > <h3 class="accordion-heading">Classes<svg><use xlink:href="#down-icon"></use></svg></h3><ul class="accordion-content"><li class="accordion collapsed child" id=4205529><div class="accordion-heading child"><a href="BaseWebRTC.html">BaseWebRTC</a><svg><use xlink:href="#down-icon"></use></svg></div><ul class='methods accordion-content'><li data-type='method'><a href="BaseWebRTC.html#getRTCPeerConnection">getRTCPeerConnection</a></li><li data-type='method'><a href="BaseWebRTC.html#isActive">isActive</a></li><li data-type='method'><a href="BaseWebRTC.html#reconnect">reconnect</a></li><li data-type='method'><a href="BaseWebRTC.html#setReconnect">setReconnect</a></li><li data-type='method'><a href="BaseWebRTC.html#stop">stop</a></li></ul></li><li class="accordion collapsed child" id=8899913><div class="accordion-heading child"><a href="PeerConnection.html">PeerConnection</a><svg><use xlink:href="#down-icon"></use></svg></div><ul class='methods accordion-content'><li data-type='method'><a href="PeerConnection.html#.getCapabilities">getCapabilities</a></li><li data-type='method'><a href="PeerConnection.html#addRemoteTrack">addRemoteTrack</a></li><li data-type='method'><a href="PeerConnection.html#closeRTCPeer">closeRTCPeer</a></li><li data-type='method'><a href="PeerConnection.html#createRTCPeer">createRTCPeer</a></li><li data-type='method'><a href="PeerConnection.html#getRTCLocalSDP">getRTCLocalSDP</a></li><li data-type='method'><a href="PeerConnection.html#getRTCPeer">getRTCPeer</a></li><li data-type='method'><a href="PeerConnection.html#getRTCPeerStatus">getRTCPeerStatus</a></li><li data-type='method'><a href="PeerConnection.html#getTracks">getTracks</a></li><li data-type='method'><a href="PeerConnection.html#initStats">initStats</a></li><li data-type='method'><a href="PeerConnection.html#replaceTrack">replaceTrack</a></li><li data-type='method'><a href="PeerConnection.html#setRTCRemoteSDP">setRTCRemoteSDP</a></li><li data-type='method'><a href="PeerConnection.html#stopStats">stopStats</a></li><li data-type='method'><a href="PeerConnection.html#updateBandwidthRestriction">updateBandwidthRestriction</a></li><li data-type='method'><a href="PeerConnection.html#updateBitrate">updateBitrate</a></li></ul></li><li class="accordion collapsed child" id=281125><div class="accordion-heading child"><a href="Publish.html">Publish</a><svg><use xlink:href="#down-icon"></use></svg></div><ul class='methods accordion-content'><li data-type='method'><a href="Publish.html#connect">connect</a></li><li data-type='method'><a href="Publish.html#getRTCPeerConnection">getRTCPeerConnection</a></li><li data-type='method'><a href="Publish.html#isActive">isActive</a></li><li data-type='method'><a href="Publish.html#reconnect">reconnect</a></li><li data-type='method'><a href="Publish.html#record">record</a></li><li data-type='method'><a href="Publish.html#setReconnect">setReconnect</a></li><li data-type='method'><a href="Publish.html#stop">stop</a></li><li data-type='method'><a href="Publish.html#unrecord">unrecord</a></li></ul></li><li class="accordion collapsed child" id=6958554><div class="accordion-heading child"><a href="Signaling.html">Signaling</a><svg><use xlink:href="#down-icon"></use></svg></div><ul class='methods accordion-content'><li data-type='method'><a href="Signaling.html#close">close</a></li><li data-type='method'><a href="Signaling.html#cmd">cmd</a></li><li data-type='method'><a href="Signaling.html#connect">connect</a></li><li data-type='method'><a href="Signaling.html#publish">publish</a></li><li data-type='method'><a href="Signaling.html#subscribe">subscribe</a></li></ul></li><li class="accordion collapsed child" id=3108999><div class="accordion-heading child"><a href="StreamEvents.html">StreamEvents</a><svg><use xlink:href="#down-icon"></use></svg></div><ul class='methods accordion-content'><li data-type='method'><a href="StreamEvents.html#.getEventsLocation">getEventsLocation</a></li><li data-type='method'><a href="StreamEvents.html#.init">init</a></li><li data-type='method'><a href="StreamEvents.html#.setEventsLocation">setEventsLocation</a></li><li data-type='method'><a href="StreamEvents.html#onUserCount">onUserCount</a></li><li data-type='method'><a href="StreamEvents.html#stop">stop</a></li></ul></li><li class="accordion collapsed child" id=9464527><div class="accordion-heading child"><a href="View.html">View</a><svg><use xlink:href="#down-icon"></use></svg></div><ul class='methods accordion-content'><li data-type='method'><a href="View.html#addRemoteTrack">addRemoteTrack</a></li><li data-type='method'><a href="View.html#connect">connect</a></li><li data-type='method'><a href="View.html#getRTCPeerConnection">getRTCPeerConnection</a></li><li data-type='method'><a href="View.html#isActive">isActive</a></li><li data-type='method'><a href="View.html#project">project</a></li><li data-type='method'><a href="View.html#reconnect">reconnect</a></li><li data-type='method'><a href="View.html#select">select</a></li><li data-type='method'><a href="View.html#setReconnect">setReconnect</a></li><li data-type='method'><a href="View.html#stop">stop</a></li><li data-type='method'><a href="View.html#unproject">unproject</a></li></ul></li></ul> </div><div class="accordion collapsed" id="2939770" > <h3 class="accordion-heading">Events<svg><use xlink:href="#down-icon"></use></svg></h3><ul class="accordion-content"><li class="accordion-list" id=""><a href="BaseWebRTC.html#event:reconnect">reconnect</a></li><li class="accordion-list" id=""><a href="PeerConnection.html#event:connectionStateChange">connectionStateChange</a></li><li class="accordion-list" id=""><a href="PeerConnection.html#event:stats">stats</a></li><li class="accordion-list" id=""><a href="PeerConnection.html#event:track">track</a></li><li class="accordion-list" id=""><a href="Publish.html#event:reconnect">reconnect</a></li><li class="accordion-list" id=""><a href="Signaling.html#event:broadcastEvent">broadcastEvent</a></li><li class="accordion-list" id=""><a href="Signaling.html#event:wsConnectionClose">wsConnectionClose</a></li><li class="accordion-list" id=""><a href="Signaling.html#event:wsConnectionError">wsConnectionError</a></li><li class="accordion-list" id=""><a href="Signaling.html#event:wsConnectionSuccess">wsConnectionSuccess</a></li><li class="accordion-list" id=""><a href="View.html#event:reconnect">reconnect</a></li></ul> </div><div class="accordion collapsed" id="3049150" > <h3 class="accordion-heading">Global<svg><use xlink:href="#down-icon"></use></svg></h3><ul class="accordion-content"><li class="accordion-list" id=""><a href="global.html#addCandidateReport">addCandidateReport</a></li><li class="accordion-list" id=""><a href="global.html#addInboundRtpReport">addInboundRtpReport</a></li><li class="accordion-list" id=""><a href="global.html#addOutboundRtpReport">addOutboundRtpReport</a></li><li class="accordion-list" id=""><a href="global.html#addPeerEvents">addPeerEvents</a></li><li class="accordion-list" id=""><a href="global.html#AudioCodec">AudioCodec</a></li><li class="accordion-list" id=""><a href="global.html#calculatePacketsLostDelta">calculatePacketsLostDelta</a></li><li class="accordion-list" id=""><a href="global.html#calculatePacketsLostRatio">calculatePacketsLostRatio</a></li><li class="accordion-list" id=""><a href="global.html#ConnectionStats">ConnectionStats</a></li><li class="accordion-list" id=""><a href="global.html#DirectorPublisherOptions">DirectorPublisherOptions</a></li><li class="accordion-list" id=""><a href="global.html#DirectorSubscriberOptions">DirectorSubscriberOptions</a></li><li class="accordion-list" id=""><a href="global.html#getBaseRtpReportData">getBaseRtpReportData</a></li><li class="accordion-list" id=""><a href="global.html#getCodecData">getCodecData</a></li><li class="accordion-list" id=""><a href="global.html#getMediaType">getMediaType</a></li><li class="accordion-list" id=""><a href="global.html#InboundStats">InboundStats</a></li><li class="accordion-list" id=""><a href="global.html#LayerInfo">LayerInfo</a></li><li class="accordion-list" id=""><a href="global.html#loggerHandler">loggerHandler</a></li><li class="accordion-list" id=""><a href="global.html#LogLevel">LogLevel</a></li><li class="accordion-list" id=""><a href="global.html#onUserCountCallback">onUserCountCallback</a></li><li class="accordion-list" id=""><a href="global.html#OnUserCountOptions">OnUserCountOptions</a></li><li class="accordion-list" id=""><a href="global.html#OutboundStats">OutboundStats</a></li><li class="accordion-list" id=""><a href="global.html#SignalingPublishOptions">SignalingPublishOptions</a></li><li class="accordion-list" id=""><a href="global.html#SignalingSubscribeOptions">SignalingSubscribeOptions</a></li><li class="accordion-list" id=""><a href="global.html#tokenGeneratorCallback">tokenGeneratorCallback</a></li><li class="accordion-list" id=""><a href="global.html#TrackReport">TrackReport</a></li><li class="accordion-list" id=""><a href="global.html#VideoCodec">VideoCodec</a></li><li class="accordion-list" id=""><a href="global.html#WowzaCapability">WowzaCapability</a></li><li class="accordion-list" id=""><a href="global.html#WowzaDirectorResponse">WowzaDirectorResponse</a></li></ul> </div>
</nav>
<div class="navbar-ham" id="navbar-ham">
<div>
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</div>
</div>
<div id="main" class="main-content">
<h1 id='page-title' class="page-title">
PeerConnectionStats.js
</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>import EventEmitter from 'events'
import Logger from './Logger'
const logger = Logger.get('PeerConnectionStats')
/**
* @typedef {Object} ConnectionStats
* @property {RTCStatsReport} raw - All RTCPeerConnection stats without parsing. Reference {@link https://developer.mozilla.org/en-US/docs/Web/API/RTCStatsReport}.
* @property {TrackReport} audio - Parsed audio information.
* @property {TrackReport} video - Parsed video information.
* @property {Number} availableOutgoingBitrate - The available outbound capacity of the network connection. The higher the value, the more bandwidth you can assume is available for outgoing data. The value is reported in bits per second.
*
* This value comes from the nominated candidate-pair.
* @property {Number} totalRoundTripTime - Total round trip time is the total time in seconds that has elapsed between sending STUN requests and receiving the responses.
*
* This value comes from the nominated candidate-pair.
* @property {Number} currentRoundTripTime - Current round trip time indicate the number of seconds it takes for data to be sent by this peer to the remote peer and back over the connection described by this pair of ICE candidates.
*
* This value comes from the nominated candidate-pair.
* @property {RTCIceCandidateType} candidateType - Local candidate type from the nominated candidate-pair which indicates the type of ICE candidate the object represents.
*/
/**
* @typedef {Object} TrackReport
* @property {Array<InboundStats>} inbounds - Parsed information of each inbound-rtp.
* @property {Array<OutboundStats>} outbounds - Parsed information of each outbound-rtp.
*/
/**
* @typedef {Object} InboundStats
* @property {String} id - inbound-rtp Id.
* @property {Number} jitter - Current Jitter measured in seconds.
* @property {String} [mimeType] - Mime type if related report had codec report associated.
* @property {Number} [framesPerSecond] - Current framerate if it's video report.
* @property {Number} [frameHeight] - Current frame height if it's video report.
* @property {Number} [frameWidth] - Current frame width if it's video report.
* @property {Number} timestamp - Timestamp of report.
* @property {Number} totalBytesReceived - Total bytes received is an integer value which indicates the total number of bytes received so far from this synchronization source.
* @property {Number} totalPacketsReceived - Total packets received indicates the total number of packets of any kind that have been received on the connection described by the pair of candidates.
* @property {Number} totalPacketsLost - Total packets lost.
* @property {Number} packetsLostRatioPerSecond - Total packet lost ratio per second.
* @property {Number} packetsLostDeltaPerSecond - Total packet lost delta per second.
* @property {Number} bitrate - Current bitrate in bits per second.
*/
/**
* @typedef {Object} OutboundStats
* @property {String} id - outbound-rtp Id.
* @property {String} [mimeType] - Mime type if related report had codec report associated.
* @property {Number} [framesPerSecond] - Current framerate if it's video report.
* @property {Number} [frameHeight] - Current frame height if it's video report.
* @property {Number} [frameWidth] - Current frame width if it's video report.
* @property {String} [qualityLimitationReason] - If it's video report, indicate the reason why the media quality in the stream is currently being reduced by the codec during encoding, or none if no quality reduction is being performed.
* @property {Number} timestamp - Timestamp of report.
* @property {Number} totalBytesSent - Total bytes sent indicates the total number of payload bytes that hve been sent so far on the connection described by the candidate pair.
* @property {Number} bitrate - Current bitrate in bits per second.
*/
export const peerConnectionStatsEvents = {
stats: 'stats'
}
export default class PeerConnectionStats extends EventEmitter {
constructor (peer) {
super()
this.peer = peer
this.stats = null
this.emitInterval = null
this.previousStats = null
}
/**
* Initialize the statistics monitoring of the RTCPeerConnection.
*/
init () {
logger.info('Initializing peer connection stats')
this.emitInterval = setInterval(async () => {
const stats = await this.peer.getStats()
this.parseStats(stats)
/**
* Peer connection incoming stats.
*
* @event PeerConnection#stats
* @type {ConnectionStats}
*/
this.emit(peerConnectionStatsEvents.stats, this.stats)
}, 1000)
}
/**
* Parse incoming RTCPeerConnection stats.
* @param {RTCStatsReport} rawStats - RTCPeerConnection stats.
* @returns {ConnectionStats} RTCPeerConnection stats parsed.
*/
parseStats (rawStats) {
this.previousStats = this.stats
const statsObject = {
audio: {
inbounds: [],
outbounds: []
},
video: {
inbounds: [],
outbounds: []
},
raw: rawStats
}
for (const report of rawStats.values()) {
switch (report.type) {
case 'outbound-rtp': {
addOutboundRtpReport(report, this.previousStats, statsObject)
break
}
case 'inbound-rtp': {
addInboundRtpReport(report, this.previousStats, statsObject)
break
}
case 'candidate-pair': {
if (report.nominated) {
addCandidateReport(report, statsObject)
}
break
}
default:
break
}
}
this.stats = statsObject
}
/**
* Stops the monitoring of RTCPeerConnection statistics.
*/
stop () {
logger.info('Stopping peer connection stats')
clearInterval(this.emitInterval)
}
}
/**
* Parse and add incoming outbound-rtp report from RTCPeerConnection to final report.
* @param {Object} report - JSON object which represents a report from RTCPeerConnection stats.
* @param {ConnectionStats} previousStats - Previous stats parsed.
* @param {Object} statsObject - Current stats object being parsed.
*/
const addOutboundRtpReport = (report, previousStats, statsObject) => {
const mediaType = getMediaType(report)
const codecInfo = getCodecData(report.codecId, statsObject.raw)
const additionalData = getBaseRtpReportData(report, mediaType)
additionalData.totalBytesSent = report.bytesSent
additionalData.id = report.id
additionalData.mid = report.mid
const previousBytesSent = previousStats ? previousStats[mediaType].outbounds.find(x => x.id === additionalData.id)?.totalBytesSent ?? 0 : null
additionalData.bitrate = previousBytesSent ? 8 * (report.bytesSent - previousBytesSent) : 0
if (mediaType === 'video') {
additionalData.qualityLimitationReason = report.qualityLimitationReason
}
statsObject[mediaType].outbounds.push({
...codecInfo,
...additionalData
})
}
/**
* Parse and add incoming inbound-rtp report from RTCPeerConnection to final report.
* @param {Object} report - JSON object which represents a report from RTCPeerConnection stats.
* @param {ConnectionStats} previousStats - Previous stats parsed.
* @param {Object} statsObject - Current stats object being parsed.
*/
const addInboundRtpReport = (report, previousStats, statsObject) => {
let mediaType = getMediaType(report)
const codecInfo = getCodecData(report.codecId, statsObject.raw)
// Safari is missing mediaType and kind for 'inbound-rtp'
if (!['audio', 'video'].includes(mediaType)) {
if (report.id.includes('Video')) mediaType = 'video'
else mediaType = 'audio'
}
const additionalData = getBaseRtpReportData(report, mediaType)
additionalData.totalBytesReceived = report.bytesReceived
additionalData.totalPacketsReceived = report.packetsReceived
additionalData.totalPacketsLost = report.packetsLost
additionalData.jitter = report.jitter
additionalData.id = report.id
additionalData.mid = report.mid
additionalData.trackIdentifier = report.trackIdentifier
additionalData.bitrate = 0
additionalData.packetsLostRatioPerSecond = 0
additionalData.packetsLostDeltaPerSecond = 0
if (previousStats) {
const previousReport = previousStats[mediaType].inbounds.find(x => x.id === additionalData.id)
if (previousReport) {
const previousBytesReceived = previousReport.totalBytesReceived
additionalData.bitrate = 8 * (report.bytesReceived - previousBytesReceived)
additionalData.packetsLostRatioPerSecond = calculatePacketsLostRatio(additionalData, previousReport)
additionalData.packetsLostDeltaPerSecond = calculatePacketsLostDelta(additionalData, previousReport)
}
}
statsObject[mediaType].inbounds.push({
...codecInfo,
...additionalData
})
}
/**
* Parse and add incoming candidate-pair report from RTCPeerConnection to final report.
* Also adds associated local-candidate data to report.
* @param {Object} report - JSON object which represents a report from RTCPeerConnection stats.
* @param {Object} statsObject - Current stats object being parsed.
*/
const addCandidateReport = (report, statsObject) => {
statsObject.totalRoundTripTime = report.totalRoundTripTime
statsObject.currentRoundTripTime = report.currentRoundTripTime
statsObject.availableOutgoingBitrate = report.availableOutgoingBitrate
statsObject.candidateType = statsObject.raw.get(report.localCandidateId).candidateType
}
/**
* Get media type.
* @param {Object} report - JSON object which represents a report from RTCPeerConnection stats.
* @returns {String} Media type.
*/
const getMediaType = (report) => {
return report.mediaType || report.kind
}
/**
* Get codec information from stats.
* @param {String} codecReportId - Codec report ID.
* @param {RTCStatsReport} rawStats - RTCPeerConnection stats.
* @returns {Object} Object containing codec information.
*/
const getCodecData = (codecReportId, rawStats) => {
const { mimeType } = codecReportId ? rawStats.get(codecReportId) ?? {} : {}
return { mimeType }
}
/**
* Get common information for RTP reports.
* @param {Object} report - JSON object which represents a report from RTCPeerConnection stats.
* @param {String} mediaType - Media type.
* @returns {Object} Object containing common information.
*/
const getBaseRtpReportData = (report, mediaType) => {
const additionalData = {}
if (mediaType === 'video') {
additionalData.framesPerSecond = report.framesPerSecond
additionalData.frameHeight = report.frameHeight
additionalData.frameWidth = report.frameWidth
}
additionalData.timestamp = report.timestamp
return additionalData
}
/**
* Calculate the ratio packets lost
* @param {Object} actualReport - JSON object which represents a parsed report.
* @param {Object} previousReport - JSON object which represents a parsed report.
* @returns {Number} Packets lost ratio
*/
const calculatePacketsLostRatio = (actualReport, previousReport) => {
const currentLostPackages = calculatePacketsLostDelta(actualReport, previousReport)
const currentReceivedPackages = actualReport.totalPacketsReceived - previousReport.totalPacketsReceived
return currentLostPackages / currentReceivedPackages
}
/**
* Calculate the delta packets lost
* @param {Object} actualReport - JSON object which represents a parsed report.
* @param {Object} previousReport - JSON object which represents a parsed report.
* @returns {Number} Packets lost ratio
*/
const calculatePacketsLostDelta = (actualReport, previousReport) => {
return actualReport.totalPacketsLost - previousReport.totalPacketsLost
}
</code></pre>
</article>
</section>
</div>
<footer class="footer" id="footer">
</footer>
<script src="scripts/third-party/prettify.js"></script>
<script src="scripts/third-party/lang-css.js"></script>
<script type="text/javascript" src="scripts/misc.js"></script>
<script>prettyPrint();</script>
<script src="scripts/linenumber.js"></script>
<script src="scripts/fix-code-block.js"></script>
<script src="scripts/fix-navbar.js"></script>
<script src="scripts/search.js"></script>
<script src="scripts/third-party/fuse.js"></script>
<script>
var list = [{"title":"Director","link":"<a href=\"module-Director.html\">Director</a>"},{"title":"module:Director~getEndpoint","link":"<a href=\"module-Director.html#~getEndpoint\">module:Director~getEndpoint ▸ undefined</a>"},{"title":"module:Director~getLiveDomain","link":"<a href=\"module-Director.html#~getLiveDomain\">module:Director~getLiveDomain ▸ undefined</a>"},{"title":"module:Director~getPublisher","link":"<a href=\"module-Director.html#~getPublisher\">module:Director~getPublisher ▸ undefined</a>"},{"title":"module:Director~getSubscriber","link":"<a href=\"module-Director.html#~getSubscriber\">module:Director~getSubscriber ▸ undefined</a>"},{"title":"module:Director~setEndpoint","link":"<a href=\"module-Director.html#~setEndpoint\">module:Director~setEndpoint ▸ undefined</a>"},{"title":"module:Director~setLiveDomain","link":"<a href=\"module-Director.html#~setLiveDomain\">module:Director~setLiveDomain ▸ undefined</a>"},{"title":"Logger","link":"<a href=\"module-Logger.html\">Logger</a>"},{"title":"module:Logger~get","link":"<a href=\"module-Logger.html#~get\">module:Logger~get ▸ undefined</a>"},{"title":"module:Logger~getHistory","link":"<a href=\"module-Logger.html#~getHistory\">module:Logger~getHistory ▸ undefined</a>"},{"title":"module:Logger~getHistoryMaxSize","link":"<a href=\"module-Logger.html#~getHistoryMaxSize\">module:Logger~getHistoryMaxSize ▸ undefined</a>"},{"title":"module:Logger~getLevel","link":"<a href=\"module-Logger.html#~getLevel\">module:Logger~getLevel ▸ undefined</a>"},{"title":"module:Logger~setHandler","link":"<a href=\"module-Logger.html#~setHandler\">module:Logger~setHandler ▸ undefined</a>"},{"title":"module:Logger~setHistoryMaxSize","link":"<a href=\"module-Logger.html#~setHistoryMaxSize\">module:Logger~setHistoryMaxSize ▸ undefined</a>"},{"title":"module:Logger~setLevel","link":"<a href=\"module-Logger.html#~setLevel\">module:Logger~setLevel ▸ undefined</a>"},{"title":"SdpParser","link":"<a href=\"module-SdpParser.html\">SdpParser</a>"},{"title":"module:SdpParser~adaptCodecName","link":"<a href=\"module-SdpParser.html#~adaptCodecName\">module:SdpParser~adaptCodecName ▸ undefined</a>"},{"title":"module:SdpParser~getAvailableHeaderExtensionIdRange","link":"<a href=\"module-SdpParser.html#~getAvailableHeaderExtensionIdRange\">module:SdpParser~getAvailableHeaderExtensionIdRange ▸ undefined</a>"},{"title":"module:SdpParser~getAvailablePayloadTypeRange","link":"<a href=\"module-SdpParser.html#~getAvailablePayloadTypeRange\">module:SdpParser~getAvailablePayloadTypeRange ▸ undefined</a>"},{"title":"module:SdpParser~removeSdpLine","link":"<a href=\"module-SdpParser.html#~removeSdpLine\">module:SdpParser~removeSdpLine ▸ undefined</a>"},{"title":"module:SdpParser~renegotiate","link":"<a href=\"module-SdpParser.html#~renegotiate\">module:SdpParser~renegotiate ▸ undefined</a>"},{"title":"module:SdpParser~setAbsoluteCaptureTime","link":"<a href=\"module-SdpParser.html#~setAbsoluteCaptureTime\">module:SdpParser~setAbsoluteCaptureTime ▸ undefined</a>"},{"title":"module:SdpParser~setDependencyDescriptor","link":"<a href=\"module-SdpParser.html#~setDependencyDescriptor\">module:SdpParser~setDependencyDescriptor ▸ undefined</a>"},{"title":"module:SdpParser~setDTX","link":"<a href=\"module-SdpParser.html#~setDTX\">module:SdpParser~setDTX ▸ undefined</a>"},{"title":"module:SdpParser~setMultiopus","link":"<a href=\"module-SdpParser.html#~setMultiopus\">module:SdpParser~setMultiopus ▸ undefined</a>"},{"title":"module:SdpParser~setSimulcast","link":"<a href=\"module-SdpParser.html#~setSimulcast\">module:SdpParser~setSimulcast ▸ undefined</a>"},{"title":"module:SdpParser~setStereo","link":"<a href=\"module-SdpParser.html#~setStereo\">module:SdpParser~setStereo ▸ undefined</a>"},{"title":"module:SdpParser~setVideoBitrate","link":"<a href=\"module-SdpParser.html#~setVideoBitrate\">module:SdpParser~setVideoBitrate ▸ undefined</a>"},{"title":"module:SdpParser~updateMissingVideoExtensions","link":"<a href=\"module-SdpParser.html#~updateMissingVideoExtensions\">module:SdpParser~updateMissingVideoExtensions ▸ undefined</a>"},{"title":"BaseWebRTC","link":"<a href=\"BaseWebRTC.html\">BaseWebRTC</a>"},{"title":"BaseWebRTC#getRTCPeerConnection","link":"<a href=\"BaseWebRTC.html#getRTCPeerConnection\">BaseWebRTC ▸ getRTCPeerConnection</a>"},{"title":"BaseWebRTC#isActive","link":"<a href=\"BaseWebRTC.html#isActive\">BaseWebRTC ▸ isActive</a>"},{"title":"BaseWebRTC#reconnect","link":"<a href=\"BaseWebRTC.html#reconnect\">BaseWebRTC ▸ reconnect</a>"},{"title":"BaseWebRTC#setReconnect","link":"<a href=\"BaseWebRTC.html#setReconnect\">BaseWebRTC ▸ setReconnect</a>"},{"title":"BaseWebRTC#stop","link":"<a href=\"BaseWebRTC.html#stop\">BaseWebRTC ▸ stop</a>"},{"title":"PeerConnection","link":"<a href=\"PeerConnection.html\">PeerConnection</a>"},{"title":"PeerConnection.getCapabilities","link":"<a href=\"PeerConnection.html#.getCapabilities\">PeerConnection ▸ getCapabilities</a>"},{"title":"PeerConnection#addRemoteTrack","link":"<a href=\"PeerConnection.html#addRemoteTrack\">PeerConnection ▸ addRemoteTrack</a>"},{"title":"PeerConnection#closeRTCPeer","link":"<a href=\"PeerConnection.html#closeRTCPeer\">PeerConnection ▸ closeRTCPeer</a>"},{"title":"PeerConnection#createRTCPeer","link":"<a href=\"PeerConnection.html#createRTCPeer\">PeerConnection ▸ createRTCPeer</a>"},{"title":"PeerConnection#getRTCLocalSDP","link":"<a href=\"PeerConnection.html#getRTCLocalSDP\">PeerConnection ▸ getRTCLocalSDP</a>"},{"title":"PeerConnection#getRTCPeer","link":"<a href=\"PeerConnection.html#getRTCPeer\">PeerConnection ▸ getRTCPeer</a>"},{"title":"PeerConnection#getRTCPeerStatus","link":"<a href=\"PeerConnection.html#getRTCPeerStatus\">PeerConnection ▸ getRTCPeerStatus</a>"},{"title":"PeerConnection#getTracks","link":"<a href=\"PeerConnection.html#getTracks\">PeerConnection ▸ getTracks</a>"},{"title":"PeerConnection#initStats","link":"<a href=\"PeerConnection.html#initStats\">PeerConnection ▸ initStats</a>"},{"title":"PeerConnection#replaceTrack","link":"<a href=\"PeerConnection.html#replaceTrack\">PeerConnection ▸ replaceTrack</a>"},{"title":"PeerConnection#setRTCRemoteSDP","link":"<a href=\"PeerConnection.html#setRTCRemoteSDP\">PeerConnection ▸ setRTCRemoteSDP</a>"},{"title":"PeerConnection#stopStats","link":"<a href=\"PeerConnection.html#stopStats\">PeerConnection ▸ stopStats</a>"},{"title":"PeerConnection#updateBandwidthRestriction","link":"<a href=\"PeerConnection.html#updateBandwidthRestriction\">PeerConnection ▸ updateBandwidthRestriction</a>"},{"title":"PeerConnection#updateBitrate","link":"<a href=\"PeerConnection.html#updateBitrate\">PeerConnection ▸ updateBitrate</a>"},{"title":"Publish","link":"<a href=\"Publish.html\">Publish</a>"},{"title":"Publish#connect","link":"<a href=\"Publish.html#connect\">Publish ▸ connect</a>"},{"title":"Publish#getRTCPeerConnection","link":"<a href=\"Publish.html#getRTCPeerConnection\">Publish ▸ getRTCPeerConnection</a>"},{"title":"Publish#isActive","link":"<a href=\"Publish.html#isActive\">Publish ▸ isActive</a>"},{"title":"Publish#reconnect","link":"<a href=\"Publish.html#reconnect\">Publish ▸ reconnect</a>"},{"title":"Publish#record","link":"<a href=\"Publish.html#record\">Publish ▸ record</a>"},{"title":"Publish#setReconnect","link":"<a href=\"Publish.html#setReconnect\">Publish ▸ setReconnect</a>"},{"title":"Publish#stop","link":"<a href=\"Publish.html#stop\">Publish ▸ stop</a>"},{"title":"Publish#unrecord","link":"<a href=\"Publish.html#unrecord\">Publish ▸ unrecord</a>"},{"title":"Signaling","link":"<a href=\"Signaling.html\">Signaling</a>"},{"title":"Signaling#close","link":"<a href=\"Signaling.html#close\">Signaling ▸ close</a>"},{"title":"Signaling#cmd","link":"<a href=\"Signaling.html#cmd\">Signaling ▸ cmd</a>"},{"title":"Signaling#connect","link":"<a href=\"Signaling.html#connect\">Signaling ▸ connect</a>"},{"title":"Signaling#publish","link":"<a href=\"Signaling.html#publish\">Signaling ▸ publish</a>"},{"title":"Signaling#subscribe","link":"<a href=\"Signaling.html#subscribe\">Signaling ▸ subscribe</a>"},{"title":"StreamEvents","link":"<a href=\"StreamEvents.html\">StreamEvents</a>"},{"title":"StreamEvents.getEventsLocation","link":"<a href=\"StreamEvents.html#.getEventsLocation\">StreamEvents ▸ getEventsLocation</a>"},{"title":"StreamEvents.init","link":"<a href=\"StreamEvents.html#.init\">StreamEvents ▸ init</a>"},{"title":"StreamEvents.setEventsLocation","link":"<a href=\"StreamEvents.html#.setEventsLocation\">StreamEvents ▸ setEventsLocation</a>"},{"title":"StreamEvents#onUserCount","link":"<a href=\"StreamEvents.html#onUserCount\">StreamEvents ▸ onUserCount</a>"},{"title":"StreamEvents#stop","link":"<a href=\"StreamEvents.html#stop\">StreamEvents ▸ stop</a>"},{"title":"View","link":"<a href=\"View.html\">View</a>"},{"title":"View#addRemoteTrack","link":"<a href=\"View.html#addRemoteTrack\">View ▸ addRemoteTrack</a>"},{"title":"View#connect","link":"<a href=\"View.html#connect\">View ▸ connect</a>"},{"title":"View#getRTCPeerConnection","link":"<a href=\"View.html#getRTCPeerConnection\">View ▸ getRTCPeerConnection</a>"},{"title":"View#isActive","link":"<a href=\"View.html#isActive\">View ▸ isActive</a>"},{"title":"View#project","link":"<a href=\"View.html#project\">View ▸ project</a>"},{"title":"View#reconnect","link":"<a href=\"View.html#reconnect\">View ▸ reconnect</a>"},{"title":"View#select","link":"<a href=\"View.html#select\">View ▸ select</a>"},{"title":"View#setReconnect","link":"<a href=\"View.html#setReconnect\">View ▸ setReconnect</a>"},{"title":"View#stop","link":"<a href=\"View.html#stop\">View ▸ stop</a>"},{"title":"View#unproject","link":"<a href=\"View.html#unproject\">View ▸ unproject</a>"},{"title":"reconnect","link":"<a href=\"BaseWebRTC.html#event:reconnect\">reconnect</a>"},{"title":"connectionStateChange","link":"<a href=\"PeerConnection.html#event:connectionStateChange\">connectionStateChange</a>"},{"title":"stats","link":"<a href=\"PeerConnection.html#event:stats\">stats</a>"},{"title":"track","link":"<a href=\"PeerConnection.html#event:track\">track</a>"},{"title":"reconnect","link":"<a href=\"Publish.html#event:reconnect\">reconnect</a>"},{"title":"broadcastEvent","link":"<a href=\"Signaling.html#event:broadcastEvent\">broadcastEvent</a>"},{"title":"wsConnectionClose","link":"<a href=\"Signaling.html#event:wsConnectionClose\">wsConnectionClose</a>"},{"title":"wsConnectionError","link":"<a href=\"Signaling.html#event:wsConnectionError\">wsConnectionError</a>"},{"title":"wsConnectionSuccess","link":"<a href=\"Signaling.html#event:wsConnectionSuccess\">wsConnectionSuccess</a>"},{"title":"reconnect","link":"<a href=\"View.html#event:reconnect\">reconnect</a>"},{"title":"addCandidateReport","link":"<a href=\"global.html#addCandidateReport\">addCandidateReport</a>"},{"title":"addInboundRtpReport","link":"<a href=\"global.html#addInboundRtpReport\">addInboundRtpReport</a>"},{"title":"addOutboundRtpReport","link":"<a href=\"global.html#addOutboundRtpReport\">addOutboundRtpReport</a>"},{"title":"addPeerEvents","link":"<a href=\"global.html#addPeerEvents\">addPeerEvents</a>"},{"title":"AudioCodec","link":"<a href=\"global.html#AudioCodec\">AudioCodec</a>"},{"title":"calculatePacketsLostDelta","link":"<a href=\"global.html#calculatePacketsLostDelta\">calculatePacketsLostDelta</a>"},{"title":"calculatePacketsLostRatio","link":"<a href=\"global.html#calculatePacketsLostRatio\">calculatePacketsLostRatio</a>"},{"title":"ConnectionStats","link":"<a href=\"global.html#ConnectionStats\">ConnectionStats</a>"},{"title":"DirectorPublisherOptions","link":"<a href=\"global.html#DirectorPublisherOptions\">DirectorPublisherOptions</a>"},{"title":"DirectorSubscriberOptions","link":"<a href=\"global.html#DirectorSubscriberOptions\">DirectorSubscriberOptions</a>"},{"title":"getBaseRtpReportData","link":"<a href=\"global.html#getBaseRtpReportData\">getBaseRtpReportData</a>"},{"title":"getCodecData","link":"<a href=\"global.html#getCodecData\">getCodecData</a>"},{"title":"getMediaType","link":"<a href=\"global.html#getMediaType\">getMediaType</a>"},{"title":"InboundStats","link":"<a href=\"global.html#InboundStats\">InboundStats</a>"},{"title":"LayerInfo","link":"<a href=\"global.html#LayerInfo\">LayerInfo</a>"},{"title":"loggerHandler","link":"<a href=\"global.html#loggerHandler\">loggerHandler</a>"},{"title":"LogLevel","link":"<a href=\"global.html#LogLevel\">LogLevel</a>"},{"title":"onUserCountCallback","link":"<a href=\"global.html#onUserCountCallback\">onUserCountCallback</a>"},{"title":"OnUserCountOptions","link":"<a href=\"global.html#OnUserCountOptions\">OnUserCountOptions</a>"},{"title":"OutboundStats","link":"<a href=\"global.html#OutboundStats\">OutboundStats</a>"},{"title":"SignalingPublishOptions","link":"<a href=\"global.html#SignalingPublishOptions\">SignalingPublishOptions</a>"},{"title":"SignalingSubscribeOptions","link":"<a href=\"global.html#SignalingSubscribeOptions\">SignalingSubscribeOptions</a>"},{"title":"tokenGeneratorCallback","link":"<a href=\"global.html#tokenGeneratorCallback\">tokenGeneratorCallback</a>"},{"title":"TrackReport","link":"<a href=\"global.html#TrackReport\">TrackReport</a>"},{"title":"VideoCodec","link":"<a href=\"global.html#VideoCodec\">VideoCodec</a>"},{"title":"WowzaCapability","link":"<a href=\"global.html#WowzaCapability\">WowzaCapability</a>"},{"title":"WowzaDirectorResponse","link":"<a href=\"global.html#WowzaDirectorResponse\">WowzaDirectorResponse</a>"}];
var options =
setupSearch(list, options)
</script>
</body>
</html>