@gcorevideo/player 2.22.16 → 2.22.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/assets/clappr-nerd-stats/clappr-nerd-stats.ejs +76 -78
  2. package/assets/clappr-nerd-stats/clappr-nerd-stats.scss +10 -7
  3. package/dist/core.js +10 -14
  4. package/dist/index.css +1441 -1440
  5. package/dist/index.js +589 -522
  6. package/dist/player.d.ts +216 -159
  7. package/dist/plugins/index.css +1204 -1203
  8. package/dist/plugins/index.js +581 -506
  9. package/docs/api/player.clapprstats.exportmetrics.md +1 -1
  10. package/docs/api/player.clapprstats.md +5 -15
  11. package/docs/api/player.clapprstatssettings.md +13 -0
  12. package/docs/api/player.clips.destroy.md +18 -0
  13. package/docs/api/player.clips.disable.md +18 -0
  14. package/docs/api/player.clips.enable.md +18 -0
  15. package/docs/api/player.clips.md +170 -0
  16. package/docs/api/player.clips.render.md +18 -0
  17. package/docs/api/player.clips.supportedversion.md +16 -0
  18. package/docs/api/player.clips.version.md +14 -0
  19. package/docs/api/player.clipspluginsettings.md +2 -2
  20. package/docs/api/player.clipspluginsettings.text.md +1 -1
  21. package/docs/api/player.md +27 -18
  22. package/docs/api/player.mediacontrol.md +1 -1
  23. package/docs/api/{player.mediacontrol.getelement.md → player.mediacontrol.mount.md} +20 -7
  24. package/docs/api/player.mediacontrolleftelement.md +1 -1
  25. package/docs/api/{player.clapprnerdstats._constructor_.md → player.nerdstats._constructor_.md} +3 -3
  26. package/docs/api/{player.clapprnerdstats.md → player.nerdstats.md} +5 -5
  27. package/docs/api/player.qualitylevel.height.md +1 -1
  28. package/docs/api/player.qualitylevel.level.md +1 -1
  29. package/docs/api/player.qualitylevel.md +4 -4
  30. package/docs/api/player.qualitylevel.width.md +1 -1
  31. package/docs/api/player.timeposition.current.md +1 -1
  32. package/docs/api/player.timeposition.md +2 -2
  33. package/docs/api/player.timeposition.total.md +1 -1
  34. package/docs/api/player.timeprogress.md +6 -4
  35. package/docs/api/player.timevalue.md +1 -1
  36. package/lib/index.plugins.d.ts +2 -1
  37. package/lib/index.plugins.d.ts.map +1 -1
  38. package/lib/index.plugins.js +2 -1
  39. package/lib/playback/dash-playback/DashPlayback.d.ts +0 -1
  40. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  41. package/lib/playback/dash-playback/DashPlayback.js +9 -12
  42. package/lib/playback/hls-playback/HlsPlayback.d.ts +1 -1
  43. package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
  44. package/lib/playback/hls-playback/HlsPlayback.js +0 -1
  45. package/lib/playback.types.d.ts +24 -12
  46. package/lib/playback.types.d.ts.map +1 -1
  47. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +4 -0
  48. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -1
  49. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +20 -23
  50. package/lib/plugins/clappr-nerd-stats/NerdStats.d.ts +86 -0
  51. package/lib/plugins/clappr-nerd-stats/NerdStats.d.ts.map +1 -0
  52. package/lib/plugins/clappr-nerd-stats/NerdStats.js +390 -0
  53. package/lib/plugins/clappr-nerd-stats/formatter.d.ts +5 -0
  54. package/lib/plugins/clappr-nerd-stats/formatter.d.ts.map +1 -1
  55. package/lib/plugins/clappr-nerd-stats/formatter.js +56 -24
  56. package/lib/plugins/clappr-nerd-stats/speedtest/index.d.ts +2 -2
  57. package/lib/plugins/clappr-nerd-stats/speedtest/index.d.ts.map +1 -1
  58. package/lib/plugins/clappr-nerd-stats/speedtest/types.d.ts +1 -1
  59. package/lib/plugins/clappr-nerd-stats/speedtest/types.d.ts.map +1 -1
  60. package/lib/plugins/clappr-nerd-stats/types.d.ts +3 -0
  61. package/lib/plugins/clappr-nerd-stats/types.d.ts.map +1 -1
  62. package/lib/plugins/clappr-nerd-stats/utils.d.ts +7 -0
  63. package/lib/plugins/clappr-nerd-stats/utils.d.ts.map +1 -0
  64. package/lib/plugins/clappr-nerd-stats/utils.js +67 -0
  65. package/lib/plugins/clappr-stats/ClapprStats.d.ts +27 -32
  66. package/lib/plugins/clappr-stats/ClapprStats.d.ts.map +1 -1
  67. package/lib/plugins/clappr-stats/ClapprStats.js +94 -202
  68. package/lib/plugins/clappr-stats/types.d.ts +65 -25
  69. package/lib/plugins/clappr-stats/types.d.ts.map +1 -1
  70. package/lib/plugins/clappr-stats/types.js +37 -2
  71. package/lib/plugins/clappr-stats/utils.d.ts +1 -1
  72. package/lib/plugins/clappr-stats/utils.d.ts.map +1 -1
  73. package/lib/plugins/clappr-stats/utils.js +1 -3
  74. package/lib/plugins/seek-time/SeekTime.d.ts +1 -1
  75. package/lib/plugins/seek-time/SeekTime.d.ts.map +1 -1
  76. package/lib/plugins/seek-time/SeekTime.js +3 -4
  77. package/lib/testUtils.d.ts +2 -1
  78. package/lib/testUtils.d.ts.map +1 -1
  79. package/lib/testUtils.js +3 -2
  80. package/package.json +1 -1
  81. package/src/index.plugins.ts +2 -1
  82. package/src/playback/dash-playback/DashPlayback.ts +10 -15
  83. package/src/playback/hls-playback/HlsPlayback.ts +2 -4
  84. package/src/playback.types.ts +25 -11
  85. package/src/plugins/clappr-nerd-stats/NerdStats.ts +503 -0
  86. package/src/plugins/clappr-nerd-stats/formatter.ts +91 -47
  87. package/src/plugins/clappr-nerd-stats/speedtest/index.ts +2 -2
  88. package/src/plugins/clappr-nerd-stats/speedtest/types.ts +1 -1
  89. package/src/plugins/clappr-nerd-stats/types.ts +43 -3
  90. package/src/plugins/clappr-nerd-stats/utils.ts +75 -0
  91. package/src/plugins/clappr-stats/ClapprStats.ts +242 -306
  92. package/src/plugins/clappr-stats/__tests__/ClapprStats.test.ts +133 -0
  93. package/src/plugins/clappr-stats/types.ts +93 -47
  94. package/src/plugins/clappr-stats/utils.ts +4 -6
  95. package/src/plugins/error-screen/__tests__/ErrorScreen.test.ts +3 -4
  96. package/src/plugins/seek-time/SeekTime.ts +4 -5
  97. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +1 -0
  98. package/src/testUtils.ts +3 -2
  99. package/temp/player.api.json +311 -159
  100. package/tsconfig.tsbuildinfo +1 -1
  101. package/docs/api/player.clapprstats.setupdatemetrics.md +0 -56
  102. package/docs/api/player.clipsplugin.gettext.md +0 -58
  103. package/docs/api/player.clipsplugin.md +0 -59
  104. package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +0 -435
@@ -0,0 +1,390 @@
1
+ import { UICorePlugin, Events, template, Playback, } from '@clappr/core';
2
+ import { reportError, trace } from '@gcorevideo/utils';
3
+ import Mousetrap from 'mousetrap';
4
+ import assert from 'assert';
5
+ import { CLAPPR_VERSION } from '../../build.js';
6
+ import { ClapprStatsEvents, } from '../clappr-stats/types.js';
7
+ import { newMetrics as newBaseMetrics } from '../clappr-stats/utils.js';
8
+ import Formatter from './formatter.js';
9
+ import { clearSpeedTestResults, configureSpeedTest, drawSpeedTestResults, initSpeedTest, startSpeedtest, stopSpeedtest, } from './speedtest/index.js';
10
+ import '../../../assets/clappr-nerd-stats/clappr-nerd-stats.scss';
11
+ import pluginHtml from '../../../assets/clappr-nerd-stats/clappr-nerd-stats.ejs';
12
+ import buttonHtml from '../../../assets/clappr-nerd-stats/button.ejs';
13
+ import statsIcon from '../../../assets/icons/new/stats.svg';
14
+ import { GearEvents } from '../bottom-gear/BottomGear.js';
15
+ import { drawSummary, getPingQuality } from './utils.js';
16
+ import { getDownloadQuality } from './utils.js';
17
+ const PLAYBACK_NAMES = {
18
+ dash: 'DASH.js',
19
+ hls: 'HLS.js',
20
+ html5_video: 'Native',
21
+ };
22
+ const T = 'plugins.nerd_stats';
23
+ /**
24
+ * `PLUGIN` that displays useful network-related statistics.
25
+ * @beta
26
+ *
27
+ * @remarks
28
+ * Depends on:
29
+ *
30
+ * - {@link BottomGear}
31
+ *
32
+ * - {@link ClapprStats}
33
+ *
34
+ * The plugin is rendered as an item in the gear menu.
35
+ *
36
+ * When clicked, it shows an overlay window with the information about the network speed, latency, etc,
37
+ * and recommended quality level.
38
+ */
39
+ export class NerdStats extends UICorePlugin {
40
+ container = null;
41
+ speedtestMetrics = {
42
+ connectionSpeed: 0,
43
+ ping: 0,
44
+ jitter: 0,
45
+ };
46
+ metrics = newMetrics();
47
+ open = false;
48
+ shortcut;
49
+ iconPosition;
50
+ static buttonTemplate = template(buttonHtml);
51
+ /**
52
+ * @internal
53
+ */
54
+ get name() {
55
+ return 'nerd_stats';
56
+ }
57
+ /**
58
+ * @internal
59
+ */
60
+ get supportedVersion() {
61
+ return { min: CLAPPR_VERSION };
62
+ }
63
+ static template = template(pluginHtml);
64
+ /**
65
+ * @internal
66
+ */
67
+ get attributes() {
68
+ return {
69
+ class: 'clappr-nerd-stats',
70
+ };
71
+ }
72
+ /**
73
+ * @internal
74
+ */
75
+ get events() {
76
+ return {
77
+ click: 'clicked',
78
+ 'click #nerd-stats-close': 'hide',
79
+ 'click #nerd-stats-refresh': 'refreshSpeedTest',
80
+ };
81
+ }
82
+ clicked(e) {
83
+ e.stopPropagation();
84
+ e.preventDefault();
85
+ }
86
+ get statsBoxElem() {
87
+ return this.$el.find('#nerd-stats-box');
88
+ }
89
+ get statsBoxWidthThreshold() {
90
+ return 720;
91
+ }
92
+ get playerWidth() {
93
+ return this.core.$el.width();
94
+ }
95
+ get playerHeight() {
96
+ return this.core.$el.height();
97
+ }
98
+ constructor(core) {
99
+ super(core);
100
+ this.shortcut = core.options.clapprNerdStats?.shortcut ?? [
101
+ 'command+shift+s',
102
+ 'ctrl+shift+s',
103
+ ];
104
+ this.iconPosition =
105
+ core.options.clapprNerdStats?.iconPosition ?? 'bottom-right';
106
+ this.speedtestMetrics = {
107
+ connectionSpeed: 0,
108
+ ping: 0,
109
+ jitter: 0,
110
+ };
111
+ configureSpeedTest(core.options.clapprNerdStats?.speedTestServers ?? []);
112
+ }
113
+ /**
114
+ * @internal
115
+ */
116
+ bindEvents() {
117
+ this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady);
118
+ this.listenTo(this.core, Events.CORE_RESIZE, this.onPlayerResize);
119
+ this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChanged);
120
+ }
121
+ onCoreReady() {
122
+ const bottomGear = this.core.getPlugin('bottom_gear');
123
+ assert(bottomGear, 'bottom_gear plugin is required');
124
+ this.listenTo(bottomGear, GearEvents.RENDERED, this.attach);
125
+ Mousetrap.bind(this.shortcut, this.toggle);
126
+ this.updateResolution();
127
+ }
128
+ onActiveContainerChanged() {
129
+ this.container = this.core.activeContainer;
130
+ const clapprStats = this.container?.getPlugin('clappr_stats');
131
+ assert(clapprStats, 'clappr-stats not available. Please, include it as a plugin of your Clappr instance.\n' +
132
+ 'For more info, visit: https://github.com/clappr/clappr-stats.');
133
+ this.listenTo(clapprStats, ClapprStatsEvents.REPORT, this.updateMetrics);
134
+ this.listenTo(this.core.activeContainer, Events.CONTAINER_VOLUME, () => {
135
+ this.metrics.general.volume = this.container?.volume ?? 0;
136
+ this.$el
137
+ .find('#nerd-stats-volume')
138
+ .text(Formatter.formatVolume(this.metrics.general.volume));
139
+ });
140
+ this.listenTo(this.core.activePlayback, Events.PLAYBACK_LOADEDMETADATA, () => {
141
+ this.$el
142
+ .find('#nerd-stats-playback-type')
143
+ .text(this.formatPlaybackName(this.core.activePlayback.getPlaybackType()));
144
+ });
145
+ this.updateMetrics(clapprStats.exportMetrics());
146
+ this.$el
147
+ .find('#nerd-stats-playback-name')
148
+ .text(PLAYBACK_NAMES[this.core.activePlayback.name] ?? '-');
149
+ this.core.activeContainer.$el.append(this.$el);
150
+ }
151
+ /**
152
+ * @internal
153
+ */
154
+ destroy() {
155
+ Mousetrap.unbind(this.shortcut);
156
+ return super.destroy();
157
+ }
158
+ toggle = () => {
159
+ if (this.open) {
160
+ this.hide();
161
+ }
162
+ else {
163
+ this.show();
164
+ }
165
+ };
166
+ show() {
167
+ this.$el.show();
168
+ this.statsBoxElem.scrollTop(this.statsBoxElem.scrollTop());
169
+ this.open = true;
170
+ this.refreshSpeedTest();
171
+ initSpeedTest(this.speedtestMetrics)
172
+ .then(() => {
173
+ startSpeedtest();
174
+ })
175
+ .catch((e) => {
176
+ reportError(e);
177
+ this.disable();
178
+ });
179
+ }
180
+ hide() {
181
+ this.$el.hide();
182
+ this.open = false;
183
+ stopSpeedtest();
184
+ }
185
+ onPlayerResize() {
186
+ this.setStatsBoxSize();
187
+ this.updateResolution();
188
+ }
189
+ updateResolution() {
190
+ this.metrics.general.resolution = {
191
+ width: this.playerWidth,
192
+ height: this.playerHeight,
193
+ };
194
+ this.$el
195
+ .find('#nerd-stats-resolution-width')
196
+ .text(this.metrics.general.resolution.width);
197
+ this.$el
198
+ .find('#nerd-stats-resolution-height')
199
+ .text(this.metrics.general.resolution.height);
200
+ }
201
+ estimateQuality() {
202
+ trace(`${T} estimateQuality`);
203
+ const videoQualityNames = [
204
+ 'SD (480p)',
205
+ 'HD (720p)',
206
+ 'Full HD (1080p)',
207
+ '2K (1440p)',
208
+ '4K (2160p)',
209
+ ];
210
+ const { connectionSpeed, ping } = this.speedtestMetrics;
211
+ if (!connectionSpeed || !ping) {
212
+ const calculatingText = this.core.i18n.t('stats.calculating');
213
+ this.metrics.custom.vodQuality = calculatingText;
214
+ this.metrics.custom.liveQuality = calculatingText;
215
+ return;
216
+ }
217
+ const downloadQuality = getDownloadQuality(connectionSpeed);
218
+ const pingQuality = getPingQuality(ping);
219
+ const liveQuality = Math.min(downloadQuality, pingQuality);
220
+ const prefix = 'Optimal for ';
221
+ this.metrics.custom.vodQuality =
222
+ prefix + videoQualityNames[downloadQuality - 1];
223
+ this.metrics.custom.liveQuality =
224
+ prefix + videoQualityNames[liveQuality - 1];
225
+ }
226
+ updateMetrics(metrics) {
227
+ trace(`${T} updateMetrics`, { custom: this.speedtestMetrics });
228
+ Object.assign(this.metrics, metrics);
229
+ this.updateEstimatedQuality();
230
+ this.$el
231
+ .find('#nerd-stats-current-time')
232
+ .text(Formatter.formatTime(this.metrics.extra.currentTime));
233
+ this.$el
234
+ .find('#nerd-stats-video-duration')
235
+ .text(Formatter.formatTime(this.metrics.extra.duration));
236
+ this.$el
237
+ .find('#nerd-stats-buffer-size')
238
+ .text(Formatter.formatTime(this.metrics.extra.buffersize));
239
+ this.$el
240
+ .find('#nerd-stats-bitrate-weighted-mean')
241
+ .text(Formatter.formatBitrate(this.metrics.extra.bitrateWeightedMean));
242
+ this.$el
243
+ .find('#nerd-stats-bitrate-most-used')
244
+ .text(Formatter.formatBitrate(this.metrics.extra.bitrateMostUsed));
245
+ this.$el
246
+ .find('#nerd-stats-watched-percentage')
247
+ .text(Formatter.formatPercentage(this.metrics.extra.watchedPercentage));
248
+ this.$el
249
+ .find('#nerd-stats-buffering-percentage')
250
+ .text(Formatter.formatPercentage(this.metrics.extra.bufferingPercentage));
251
+ this.$el
252
+ .find('#nerd-stats-startup-time')
253
+ .text(Formatter.formatTime(this.metrics.chrono.startup));
254
+ this.$el
255
+ .find('#nerd-stats-watch-time')
256
+ .text(Formatter.formatTime(this.metrics.chrono.watch));
257
+ this.$el
258
+ .find('#nerd-stats-pause-time')
259
+ .text(Formatter.formatTime(this.metrics.chrono.pause));
260
+ this.$el
261
+ .find('#nerd-stats-buffering-time')
262
+ .text(Formatter.formatTime(this.metrics.chrono.buffering));
263
+ this.$el
264
+ .find('#nerd-stats-session-time')
265
+ .text(Formatter.formatTime(this.metrics.chrono.session));
266
+ this.$el.find('#nerd-stats-plays').text(this.metrics.counters.play);
267
+ this.$el.find('#nerd-stats-pauses').text(this.metrics.counters.pause);
268
+ this.$el.find('#nerd-stats-errors').text(this.metrics.counters.error);
269
+ this.$el
270
+ .find('#nerd-stats-bufferings')
271
+ .text(this.metrics.counters.buffering);
272
+ this.$el
273
+ .find('#nerd-stats-decoded-frames')
274
+ .text(this.metrics.counters.decodedFrames);
275
+ this.$el
276
+ .find('#nerd-stats-dropped-frames')
277
+ .text(this.metrics.counters.droppedFrames);
278
+ this.$el
279
+ .find('#nerd-stats-bitrate-changes')
280
+ .text(this.metrics.counters.changeLevel);
281
+ this.$el.find('#nerd-stats-seeks').text(this.metrics.counters.seek);
282
+ this.$el
283
+ .find('#nerd-stats-fullscreen')
284
+ .text(this.metrics.counters.fullscreen);
285
+ this.$el.find('#nerd-stats-dvr-usage').text(this.metrics.counters.dvrUsage);
286
+ this.$el
287
+ .find('#nerd-stats-fps')
288
+ .text(Formatter.formatFps(this.metrics.counters.fps));
289
+ this.setStatsBoxSize();
290
+ drawSpeedTestResults();
291
+ drawSummary(this.speedtestMetrics, this.$el.find('#nerd-stats-quality-vod'), this.$el.find('#nerd-stats-quality-live'));
292
+ if (!this.open) {
293
+ this.hide();
294
+ }
295
+ }
296
+ updateEstimatedQuality() {
297
+ this.estimateQuality();
298
+ this.$el
299
+ .find('#nerd-stats-quality-vod-text')
300
+ .html(this.metrics.custom.vodQuality);
301
+ this.$el
302
+ .find('#nerd-stats-quality-live-text')
303
+ .html(this.metrics.custom.liveQuality);
304
+ }
305
+ setStatsBoxSize() {
306
+ if (this.playerWidth >= this.statsBoxWidthThreshold) {
307
+ this.statsBoxElem.addClass('wide');
308
+ this.statsBoxElem.removeClass('narrow');
309
+ }
310
+ else {
311
+ this.statsBoxElem.removeClass('wide');
312
+ this.statsBoxElem.addClass('narrow');
313
+ }
314
+ }
315
+ /**
316
+ * @internal
317
+ */
318
+ render() {
319
+ this.$el
320
+ .html(NerdStats.template({
321
+ metrics: Formatter.format(this.metrics ?? newMetrics()),
322
+ iconPosition: this.iconPosition,
323
+ i18n: this.core.i18n,
324
+ }))
325
+ .hide();
326
+ return this;
327
+ }
328
+ attach() {
329
+ trace(`${T} attach`);
330
+ const gear = this.core.getPlugin('bottom_gear');
331
+ gear
332
+ .addItem('nerd_stats')
333
+ .html(NerdStats.buttonTemplate({
334
+ icon: statsIcon,
335
+ i18n: this.core.i18n,
336
+ }))
337
+ .on('click', (e) => {
338
+ e.stopPropagation();
339
+ this.toggle();
340
+ });
341
+ }
342
+ clearSpeedtestMetrics() {
343
+ const clapprStats = this.container?.getPlugin('clappr_stats');
344
+ this.speedtestMetrics.connectionSpeed = 0;
345
+ this.speedtestMetrics.ping = 0;
346
+ this.speedtestMetrics.jitter = 0;
347
+ if (clapprStats) {
348
+ this.updateMetrics(clapprStats.exportMetrics());
349
+ }
350
+ }
351
+ refreshSpeedTest() {
352
+ stopSpeedtest();
353
+ setTimeout(() => {
354
+ this.clearSpeedtestMetrics();
355
+ clearSpeedTestResults();
356
+ drawSpeedTestResults();
357
+ }, 200);
358
+ setTimeout(() => {
359
+ startSpeedtest();
360
+ }, 800);
361
+ }
362
+ formatPlaybackName(playbackType) {
363
+ switch (playbackType) {
364
+ case Playback.VOD:
365
+ return this.core.i18n.t('vod');
366
+ case Playback.LIVE:
367
+ return this.core.i18n.t('live');
368
+ default:
369
+ return '-';
370
+ }
371
+ }
372
+ }
373
+ function newMetrics() {
374
+ return {
375
+ ...newBaseMetrics(),
376
+ general: {
377
+ displayResolution: '',
378
+ resolution: {
379
+ width: 0,
380
+ height: 0,
381
+ },
382
+ volume: 0,
383
+ },
384
+ custom: {
385
+ connectionSpeed: 0,
386
+ ping: 0,
387
+ jitter: 0,
388
+ },
389
+ };
390
+ }
@@ -3,6 +3,11 @@ type MetricsValue = number | string;
3
3
  type Metrics = Partial<Record<MetricsKind, Partial<Record<MetricsType, MetricsValue>>>>;
4
4
  export default class Formatter {
5
5
  static format(metrics: Metrics): Metrics;
6
+ static formatVolume(volume: number): string;
7
+ static formatTime(time: number): string;
8
+ static formatFps(fps: number): string;
9
+ static formatPercentage(percentage: number): string;
10
+ static formatBitrate(bitrate: number): string;
6
11
  }
7
12
  export {};
8
13
  //# sourceMappingURL=formatter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../../src/plugins/clappr-nerd-stats/formatter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAyExD,KAAK,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AACpC,KAAK,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAExF,MAAM,CAAC,OAAO,OAAO,SAAS;IAC5B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;CA8BzC"}
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../../src/plugins/clappr-nerd-stats/formatter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAsFnE,KAAK,YAAY,GAAG,MAAM,GAAG,MAAM,CAAA;AACnC,KAAK,OAAO,GAAG,OAAO,CACpB,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,CAChE,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,SAAS;IAC5B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAkCxC,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAI3C,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAMvC,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIrC,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAMnD,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAK9C"}
@@ -3,63 +3,72 @@ const timeScale = new humanFormat.Scale({
3
3
  ms: 1,
4
4
  sec: 1000,
5
5
  min: 60000,
6
- hours: 3600000
6
+ hours: 3600000,
7
7
  });
8
8
  const percentScale = new humanFormat.Scale({
9
- '%': 1
9
+ '%': 1,
10
10
  });
11
+ const metricTemplates = {
12
+ fps: {
13
+ scale: 'SI',
14
+ decimals: 0,
15
+ },
16
+ volume: {
17
+ scale: percentScale,
18
+ },
19
+ };
11
20
  const formattingTemplate = {
12
21
  general: {
13
22
  volume: {
14
- scale: percentScale
15
- }
23
+ scale: percentScale,
24
+ },
16
25
  },
17
26
  timers: {
18
27
  startup: {
19
- scale: timeScale
28
+ scale: timeScale,
20
29
  },
21
30
  watch: {
22
- scale: timeScale
31
+ scale: timeScale,
23
32
  },
24
33
  pause: {
25
- scale: timeScale
34
+ scale: timeScale,
26
35
  },
27
36
  buffering: {
28
- scale: timeScale
37
+ scale: timeScale,
29
38
  },
30
39
  session: {
31
- scale: timeScale
40
+ scale: timeScale,
32
41
  },
33
42
  latency: {
34
- scale: timeScale
35
- }
43
+ scale: timeScale,
44
+ },
36
45
  },
37
46
  extra: {
38
47
  buffersize: {
39
- scale: timeScale
48
+ scale: timeScale,
40
49
  },
41
50
  duration: {
42
- scale: timeScale
51
+ scale: timeScale,
43
52
  },
44
53
  currentTime: {
45
- scale: timeScale
54
+ scale: timeScale,
46
55
  },
47
56
  bitrateWeightedMean: {
48
- unit: 'bps'
57
+ unit: 'bps',
49
58
  },
50
59
  bitrateMostUsed: {
51
- unit: 'bps'
60
+ unit: 'bps',
52
61
  },
53
62
  bandwidth: {
54
- unit: 'bps'
63
+ unit: 'bps',
55
64
  },
56
65
  watchedPercentage: {
57
- scale: percentScale
66
+ scale: percentScale,
58
67
  },
59
68
  bufferingPercentage: {
60
- scale: percentScale
61
- }
62
- }
69
+ scale: percentScale,
70
+ },
71
+ },
63
72
  };
64
73
  export default class Formatter {
65
74
  static format(metrics) {
@@ -69,8 +78,10 @@ export default class Formatter {
69
78
  formattedMetrics[type] = fmt;
70
79
  const typeTemplate = formattingTemplate[type];
71
80
  Object.entries(mm).forEach(([name, value]) => {
72
- // const value = mm[name];
73
- if (typeTemplate && typeTemplate[name] && (typeof value === 'number') && !isNaN(value)) {
81
+ if (typeTemplate &&
82
+ typeTemplate[name] &&
83
+ typeof value === 'number' &&
84
+ !isNaN(value)) {
74
85
  // @ts-ignore
75
86
  const templateScale = typeTemplate[name].scale || 'SI';
76
87
  // @ts-ignore
@@ -78,7 +89,7 @@ export default class Formatter {
78
89
  fmt[name] = humanFormat(value, {
79
90
  scale: templateScale,
80
91
  unit: templateUnit,
81
- decimals: 2
92
+ decimals: 2,
82
93
  });
83
94
  }
84
95
  else {
@@ -88,4 +99,25 @@ export default class Formatter {
88
99
  });
89
100
  return formattedMetrics;
90
101
  }
102
+ static formatVolume(volume) {
103
+ return humanFormat(volume, metricTemplates.volume);
104
+ }
105
+ static formatTime(time) {
106
+ return humanFormat(time, {
107
+ scale: timeScale,
108
+ });
109
+ }
110
+ static formatFps(fps) {
111
+ return humanFormat(fps, metricTemplates.fps);
112
+ }
113
+ static formatPercentage(percentage) {
114
+ return humanFormat(percentage, {
115
+ scale: percentScale,
116
+ });
117
+ }
118
+ static formatBitrate(bitrate) {
119
+ return humanFormat(bitrate, {
120
+ unit: 'bps',
121
+ });
122
+ }
91
123
  }
@@ -1,7 +1,7 @@
1
1
  import { type Server } from './Speedtest.js';
2
- import { CustomMetrics } from './types.js';
2
+ import { SpeedtestMetrics } from './types.js';
3
3
  export declare function drawSpeedTestResults(): void;
4
- export declare const initSpeedTest: (customMetrics: CustomMetrics) => Promise<void>;
4
+ export declare const initSpeedTest: (customMetrics: SpeedtestMetrics) => Promise<void>;
5
5
  export declare const stopSpeedtest: () => void;
6
6
  export declare const startSpeedtest: () => void;
7
7
  export declare const clearSpeedTestResults: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/clappr-nerd-stats/speedtest/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAkC,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAqC3C,wBAAgB,oBAAoB,SAmBnC;AAID,eAAO,MAAM,aAAa,kBAAmB,aAAa,KAAG,OAAO,CAAC,IAAI,CA+ExE,CAAC;AAEF,eAAO,MAAM,aAAa,YAIzB,CAAC;AAEF,eAAO,MAAM,cAAc,YAI1B,CAAC;AAEF,eAAO,MAAM,qBAAqB,YAEjC,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAGnD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/clappr-nerd-stats/speedtest/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAkC,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAqC9C,wBAAgB,oBAAoB,SAmBnC;AAID,eAAO,MAAM,aAAa,kBAAmB,gBAAgB,KAAG,OAAO,CAAC,IAAI,CA+E3E,CAAC;AAEF,eAAO,MAAM,aAAa,YAIzB,CAAC;AAEF,eAAO,MAAM,cAAc,YAI1B,CAAC;AAEF,eAAO,MAAM,qBAAqB,YAEjC,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAGnD"}
@@ -1,4 +1,4 @@
1
- export type CustomMetrics = {
1
+ export type SpeedtestMetrics = {
2
2
  ping: number;
3
3
  jitter: number;
4
4
  connectionSpeed: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/plugins/clappr-nerd-stats/speedtest/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/plugins/clappr-nerd-stats/speedtest/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB,CAAA"}
@@ -1,4 +1,7 @@
1
1
  export type MetricsKind = 'general' | 'timers' | 'extra';
2
+ export type MetricType = 'general' | 'timers' | 'extra';
2
3
  export type MetricsType = 'volume' | 'startup' | 'watch' | 'pause' | 'buffering' | 'session' | 'latency' | 'buffersize' | 'duration' | 'currentTime' | 'bitrateWeightedMean' | 'bitrateMostUsed' | 'bandwidth' | 'watchedPercentage' | 'bufferingPercentage';
4
+ export type MetricName = 'volume' | 'startup' | 'watch' | 'pause' | 'buffering' | 'session' | 'latency' | 'buffersize' | 'duration' | 'currentTime' | 'bitrateWeightedMean' | 'bitrateMostUsed' | 'bandwidth' | 'watchedPercentage' | 'bufferingPercentage' | 'fps';
5
+ export type MetricKind = 'volume' | 'time' | 'precisetime' | 'percentage' | 'bitrate' | 'bandwidth';
3
6
  export type MetricsValue = number;
4
7
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/plugins/clappr-nerd-stats/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AACzD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,aAAa,GAAG,qBAAqB,GAAG,iBAAiB,GAAG,WAAW,GAAG,mBAAmB,GAAG,qBAAqB,CAAC;AAC7P,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/plugins/clappr-nerd-stats/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AACxD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AACvD,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,SAAS,GACT,OAAO,GACP,OAAO,GACP,WAAW,GACX,SAAS,GACT,SAAS,GACT,YAAY,GACZ,UAAU,GACV,aAAa,GACb,qBAAqB,GACrB,iBAAiB,GACjB,WAAW,GACX,mBAAmB,GACnB,qBAAqB,CAAA;AACzB,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,SAAS,GACT,OAAO,GACP,OAAO,GACP,WAAW,GACX,SAAS,GACT,SAAS,GACT,YAAY,GACZ,UAAU,GACV,aAAa,GACb,qBAAqB,GACrB,iBAAiB,GACjB,WAAW,GACX,mBAAmB,GACnB,qBAAqB,GACrB,KAAK,CAAA;AACT,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,MAAM,GACN,aAAa,GACb,YAAY,GACZ,SAAS,GACT,WAAW,CAAA;AACf,MAAM,MAAM,YAAY,GAAG,MAAM,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { ZeptoResult } from "../../types";
2
+ import { SpeedtestMetrics } from "./speedtest/types";
3
+ export declare const getDownloadQuality: (speedValue: number) => number;
4
+ export declare const getPingQuality: (pingValue: number) => number;
5
+ export declare const generateQualityHtml: (quality: number) => string;
6
+ export declare const drawSummary: (customMetrics: SpeedtestMetrics, vodContainer: ZeptoResult, liveContainer: ZeptoResult) => void;
7
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/plugins/clappr-nerd-stats/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAUpD,eAAO,MAAM,kBAAkB,eAAgB,MAAM,KAAG,MAYvD,CAAA;AAED,eAAO,MAAM,cAAc,cAAe,MAAM,KAAG,MAYlD,CAAA;AAED,eAAO,MAAM,mBAAmB,YAAa,MAAM,KAAG,MAerD,CAAA;AAED,eAAO,MAAM,WAAW,kBACP,gBAAgB,gBACjB,WAAW,iBACV,WAAW,SAe3B,CAAA"}
@@ -0,0 +1,67 @@
1
+ const qualityClasses = [
2
+ 'speedtest-quality-value-1',
3
+ 'speedtest-quality-value-2',
4
+ 'speedtest-quality-value-3',
5
+ 'speedtest-quality-value-4',
6
+ 'speedtest-quality-value-5',
7
+ ];
8
+ export const getDownloadQuality = (speedValue) => {
9
+ if (speedValue < 3) {
10
+ return 1;
11
+ }
12
+ else if (speedValue < 7) {
13
+ return 2;
14
+ }
15
+ else if (speedValue < 13) {
16
+ return 3;
17
+ }
18
+ else if (speedValue < 25) {
19
+ return 4;
20
+ }
21
+ else {
22
+ return 5;
23
+ }
24
+ };
25
+ export const getPingQuality = (pingValue) => {
26
+ if (pingValue < 20) {
27
+ return 5;
28
+ }
29
+ else if (pingValue < 50) {
30
+ return 4;
31
+ }
32
+ else if (pingValue < 100) {
33
+ return 3;
34
+ }
35
+ else if (pingValue < 150) {
36
+ return 2;
37
+ }
38
+ else {
39
+ return 1;
40
+ }
41
+ };
42
+ export const generateQualityHtml = (quality) => {
43
+ const html = [];
44
+ const qualityClassName = qualityClasses[quality - 1];
45
+ for (let i = 0; i < qualityClasses.length; i++) {
46
+ if (i < quality) {
47
+ html.push(`<div class="speedtest-quality-content-item ${qualityClassName}"></div>`);
48
+ }
49
+ else {
50
+ html.push('<div class="speedtest-quality-content-item"></div>');
51
+ }
52
+ }
53
+ return html.join('');
54
+ };
55
+ export const drawSummary = (customMetrics, vodContainer, liveContainer) => {
56
+ const { connectionSpeed, ping } = customMetrics;
57
+ if (!connectionSpeed || !ping) {
58
+ return;
59
+ }
60
+ const downloadQuality = getDownloadQuality(connectionSpeed);
61
+ const pingQuality = getPingQuality(ping);
62
+ const liveQuality = Math.min(downloadQuality, pingQuality);
63
+ const vodHtml = generateQualityHtml(downloadQuality);
64
+ const liveHtml = generateQualityHtml(liveQuality);
65
+ vodContainer.html(vodHtml);
66
+ liveContainer.html(liveHtml);
67
+ };