@gcorevideo/player 2.22.15 → 2.22.17
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.
- package/assets/clips/clips.ejs +1 -0
- package/assets/clips/clips.scss +23 -3
- package/assets/level-selector/list.ejs +9 -3
- package/assets/media-control/media-control.ejs +1 -9
- package/assets/media-control/media-control.scss +0 -25
- package/assets/media-control/width370.scss +4 -4
- package/dist/core.js +6 -8
- package/dist/index.css +855 -855
- package/dist/index.js +609 -664
- package/dist/player.d.ts +426 -302
- package/dist/plugins/index.css +551 -551
- package/dist/plugins/index.js +648 -703
- package/docs/api/{player.audioselector.md → player.audiotracks.md} +3 -3
- package/docs/api/player.clapprstats.exportmetrics.md +1 -1
- package/docs/api/player.clapprstats.md +5 -15
- package/docs/api/player.clapprstatssettings.md +13 -0
- package/docs/api/{player.contextmenupluginsettings.preventshowcontextmenu.md → player.clips.destroy.md} +7 -3
- package/docs/api/{player.contextmenupluginsettings.label.md → player.clips.disable.md} +7 -3
- package/docs/api/player.clips.enable.md +18 -0
- package/docs/api/player.clips.md +170 -0
- package/docs/api/player.clips.render.md +18 -0
- package/docs/api/player.clips.supportedversion.md +16 -0
- package/docs/api/player.clips.version.md +14 -0
- package/docs/api/player.clipspluginsettings.md +2 -2
- package/docs/api/player.clipspluginsettings.text.md +1 -1
- package/docs/api/player.contextmenu.md +2 -0
- package/docs/api/player.contextmenupluginsettings.md +2 -40
- package/docs/api/{player.contextmenupluginsettings.url.md → player.contextmenupluginsettings.options.md} +3 -3
- package/docs/api/player.md +101 -37
- package/docs/api/player.mediacontrol.md +9 -15
- package/docs/api/{player.mediacontrol.getelement.md → player.mediacontrol.mount.md} +20 -7
- package/docs/api/player.mediacontrolelement.md +4 -2
- package/docs/api/player.mediacontrollayerelement.md +16 -0
- package/docs/api/player.mediacontrolleftelement.md +16 -0
- package/docs/api/player.mediacontrolrightelement.md +16 -0
- package/docs/api/player.mediacontrolsettings.md +23 -0
- package/docs/api/player.menuoption.md +21 -0
- package/docs/api/{player.clapprnerdstats._constructor_.md → player.nerdstats._constructor_.md} +3 -3
- package/docs/api/{player.clapprnerdstats.md → player.nerdstats.md} +5 -5
- package/docs/api/player.playbackrate.md +1 -1
- package/docs/api/player.playerconfig.md +1 -1
- package/docs/api/player.playerconfig.playbacktype.md +1 -1
- package/docs/api/player.qualitylevel.height.md +1 -1
- package/docs/api/player.qualitylevel.level.md +1 -1
- package/docs/api/player.qualitylevel.md +4 -4
- package/docs/api/player.qualitylevel.width.md +1 -1
- package/docs/api/{player.levelselector.events.md → player.qualitylevels.events.md} +2 -2
- package/docs/api/{player.levelselector.md → player.qualitylevels.md} +6 -6
- package/docs/api/{player.levelselectorpluginsettings.labels.md → player.qualitylevelspluginsettings.labels.md} +2 -2
- package/docs/api/{player.levelselectorpluginsettings.md → player.qualitylevelspluginsettings.md} +6 -6
- package/docs/api/{player.levelselectorpluginsettings.restrictresolution.md → player.qualitylevelspluginsettings.restrictresolution.md} +2 -2
- package/docs/api/player.timeposition.current.md +1 -1
- package/docs/api/player.timeposition.md +2 -2
- package/docs/api/player.timeposition.total.md +1 -1
- package/docs/api/player.timeprogress.md +6 -4
- package/docs/api/player.timevalue.md +1 -1
- package/lib/index.plugins.d.ts +2 -1
- package/lib/index.plugins.d.ts.map +1 -1
- package/lib/index.plugins.js +2 -1
- package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/playback/dash-playback/DashPlayback.js +5 -7
- package/lib/playback.types.d.ts +22 -9
- package/lib/playback.types.d.ts.map +1 -1
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +4 -0
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -1
- package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +20 -23
- package/lib/plugins/clappr-nerd-stats/NerdStats.d.ts +83 -0
- package/lib/plugins/clappr-nerd-stats/NerdStats.d.ts.map +1 -0
- package/lib/plugins/clappr-nerd-stats/NerdStats.js +339 -0
- package/lib/plugins/clappr-stats/ClapprStats.d.ts +27 -32
- package/lib/plugins/clappr-stats/ClapprStats.d.ts.map +1 -1
- package/lib/plugins/clappr-stats/ClapprStats.js +94 -202
- package/lib/plugins/clappr-stats/types.d.ts +65 -24
- package/lib/plugins/clappr-stats/types.d.ts.map +1 -1
- package/lib/plugins/clappr-stats/types.js +37 -2
- package/lib/plugins/clappr-stats/utils.d.ts.map +1 -1
- package/lib/plugins/clappr-stats/utils.js +1 -2
- package/lib/plugins/clips/Clips.d.ts +21 -16
- package/lib/plugins/clips/Clips.d.ts.map +1 -1
- package/lib/plugins/clips/Clips.js +96 -98
- package/lib/plugins/clips/types.d.ts +19 -0
- package/lib/plugins/clips/types.d.ts.map +1 -0
- package/lib/plugins/clips/types.js +1 -0
- package/lib/plugins/clips/utils.d.ts +4 -0
- package/lib/plugins/clips/utils.d.ts.map +1 -0
- package/lib/plugins/clips/utils.js +36 -0
- package/lib/plugins/media-control/MediaControl.d.ts +4 -7
- package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
- package/lib/plugins/media-control/MediaControl.js +19 -31
- package/lib/plugins/utils.d.ts +9 -1
- package/lib/plugins/utils.d.ts.map +1 -1
- package/lib/plugins/utils.js +9 -10
- package/lib/plugins/vast-ads/loaderxml.js +2 -2
- package/lib/testUtils.d.ts +2 -1
- package/lib/testUtils.d.ts.map +1 -1
- package/lib/testUtils.js +5 -7
- package/package.json +1 -1
- package/src/index.plugins.ts +2 -1
- package/src/playback/dash-playback/DashPlayback.ts +5 -8
- package/src/playback.types.ts +23 -8
- package/src/plugins/clappr-nerd-stats/{ClapprNerdStats.ts → NerdStats.ts} +25 -30
- package/src/plugins/clappr-stats/ClapprStats.ts +242 -306
- package/src/plugins/clappr-stats/__tests__/ClapprStats.test.ts +133 -0
- package/src/plugins/clappr-stats/types.ts +72 -25
- package/src/plugins/clappr-stats/utils.ts +1 -2
- package/src/plugins/clips/Clips.ts +116 -135
- package/src/plugins/clips/__tests__/Clips.test.ts +72 -0
- package/src/plugins/clips/__tests__/__snapshots__/Clips.test.ts.snap +14 -0
- package/src/plugins/clips/types.ts +22 -0
- package/src/plugins/clips/utils.ts +54 -0
- package/src/plugins/error-screen/__tests__/ErrorScreen.test.ts +3 -4
- package/src/plugins/level-selector/__tests__/__snapshots__/QualityLevels.test.ts.snap +18 -18
- package/src/plugins/media-control/MediaControl.ts +31 -58
- package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +7 -35
- package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +1 -0
- package/src/plugins/utils.ts +9 -7
- package/src/plugins/vast-ads/loaderxml.ts +2 -2
- package/src/testUtils.ts +5 -7
- package/temp/player.api.json +693 -471
- package/tsconfig.tsbuildinfo +1 -1
- package/docs/api/player.clapprstats.setupdatemetrics.md +0 -56
- package/docs/api/player.clipsplugin.gettext.md +0 -58
- package/docs/api/player.clipsplugin.md +0 -59
- package/docs/api/player.mediacontrol.handlecustomarea.md +0 -52
package/dist/plugins/index.js
CHANGED
|
@@ -9765,13 +9765,13 @@ function ifError(err) {
|
|
|
9765
9765
|
|
|
9766
9766
|
// assert(process.env.CLAPPR_VERSION, 'CLAPPR_VERSION is required');
|
|
9767
9767
|
// export const CLAPPR_VERSION: string = process.env.CLAPPR_VERSION || '0.11.3';
|
|
9768
|
-
const CLAPPR_VERSION = '0.11.3';
|
|
9768
|
+
const CLAPPR_VERSION$1 = '0.11.3';
|
|
9769
9769
|
|
|
9770
9770
|
const pluginHtml$7 = "<button data-audiotracks-button class='gcore-skin-button-color' id=\"audiotracks-button\">\n <span class='audio-text'><%= title %></span> <span class=\"audio-arrow\"><%= icon %></span>\n</button>\n<ul class='gcore-skin-bg-color menu hidden' id=\"audiotracks-select\">\n <% for (const track of tracks) { %>\n <li>\n <a href=\"#\" class='gcore-skin-text-color' data-audiotracks-select=\"<%= track.id %>\">\n <%= track.label %>\n </a>\n </li>\n <% }; %>\n</ul>\n";
|
|
9771
9771
|
|
|
9772
9772
|
const audioArrow = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg width=\"9px\" height=\"6px\" viewBox=\"0 0 9 6\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <!-- Generator: Sketch 49 (51002) - http://www.bohemiancoding.com/sketch -->\n <title>quality-arrow</title>\n <desc>Created with Sketch.</desc>\n <defs></defs>\n <g id=\"quality-arrow\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <path\n d=\"M5.07079194,5.78553848 C4.91457318,5.94277844 4.70551573,6.00941824 4.50028717,5.99893557 C4.2950586,6.00941824 4.08676693,5.94277844 3.92978239,5.78553848 L0.221118462,1.2997069 C-0.0737061539,1.00469478 -0.0737061539,0.526236029 0.221118462,0.231972666 C0.515177299,-0.0630394586 1.23500883,0.00734414472 1.64852907,0.00734414472 L7.77475484,0.00734414472 C8.21201421,0.00734414472 8.48539703,-0.0630394586 8.77945587,0.231972666 C9.07351471,0.526236029 9.07351471,1.00469478 8.77945587,1.2997069 L5.07079194,5.78553848 Z\"\n fill=\"#FFFFFE\"></path>\n </g>\n</svg>\n";
|
|
9773
9773
|
|
|
9774
|
-
const VERSION$
|
|
9774
|
+
const VERSION$7 = '2.22.4';
|
|
9775
9775
|
// const T = 'plugins.audiotracks'
|
|
9776
9776
|
/**
|
|
9777
9777
|
* `PLUGIN` that makes possible to switch audio tracks via the media control UI.
|
|
@@ -9796,13 +9796,13 @@ class AudioTracks extends UICorePlugin {
|
|
|
9796
9796
|
* @internal
|
|
9797
9797
|
*/
|
|
9798
9798
|
get supportedVersion() {
|
|
9799
|
-
return { min: CLAPPR_VERSION };
|
|
9799
|
+
return { min: CLAPPR_VERSION$1 };
|
|
9800
9800
|
}
|
|
9801
9801
|
/**
|
|
9802
9802
|
* @internal
|
|
9803
9803
|
*/
|
|
9804
9804
|
static get version() {
|
|
9805
|
-
return VERSION$
|
|
9805
|
+
return VERSION$7;
|
|
9806
9806
|
}
|
|
9807
9807
|
static template = tmpl(pluginHtml$7);
|
|
9808
9808
|
/**
|
|
@@ -9965,7 +9965,7 @@ class BigMuteButton extends UICorePlugin {
|
|
|
9965
9965
|
* @internal
|
|
9966
9966
|
*/
|
|
9967
9967
|
get supportedVersion() {
|
|
9968
|
-
return { min: CLAPPR_VERSION };
|
|
9968
|
+
return { min: CLAPPR_VERSION$1 };
|
|
9969
9969
|
}
|
|
9970
9970
|
static template = tmpl(pluginHtml$6);
|
|
9971
9971
|
/**
|
|
@@ -10086,7 +10086,7 @@ const gearIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"n
|
|
|
10086
10086
|
|
|
10087
10087
|
const gearHdIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_28_1567)\">\n <path\n d=\"M19.14 12.94C19.18 12.64 19.2 12.33 19.2 12C19.2 11.68 19.18 11.36 19.13 11.06L21.16 9.47999C21.34 9.33999 21.39 9.06999 21.28 8.86999L19.36 5.54999C19.24 5.32999 18.99 5.25999 18.77 5.32999L16.38 6.28999C15.88 5.90999 15.35 5.58999 14.76 5.34999L14.4 2.80999C14.36 2.56999 14.16 2.39999 13.92 2.39999H10.08C9.83999 2.39999 9.64999 2.56999 9.60999 2.80999L9.24999 5.34999C8.65999 5.58999 8.11999 5.91999 7.62999 6.28999L5.23999 5.32999C5.01999 5.24999 4.76999 5.32999 4.64999 5.54999L2.73999 8.86999C2.61999 9.07999 2.65999 9.33999 2.85999 9.47999L4.88999 11.06C4.83999 11.36 4.79999 11.69 4.79999 12C4.79999 12.31 4.81999 12.64 4.86999 12.94L2.83999 14.52C2.65999 14.66 2.60999 14.93 2.71999 15.13L4.63999 18.45C4.75999 18.67 5.00999 18.74 5.22999 18.67L7.61999 17.71C8.11999 18.09 8.64999 18.41 9.23999 18.65L9.59999 21.19C9.64999 21.43 9.83999 21.6 10.08 21.6H13.92C14.16 21.6 14.36 21.43 14.39 21.19L14.75 18.65C15.34 18.41 15.88 18.09 16.37 17.71L18.76 18.67C18.98 18.75 19.23 18.67 19.35 18.45L21.27 15.13C21.39 14.91 21.34 14.66 21.15 14.52L19.14 12.94ZM12 15.6C10.02 15.6 8.39999 13.98 8.39999 12C8.39999 10.02 10.02 8.39999 12 8.39999C13.98 8.39999 15.6 10.02 15.6 12C15.6 13.98 13.98 15.6 12 15.6Z\"\n fill=\"#C9C9C9\"/>\n <rect x=\"13\" width=\"11\" height=\"7\" rx=\"1\" fill=\"#F6413B\"/>\n <path\n d=\"M14.6962 6V1.63636H15.3546V3.53267H17.53V1.63636H18.1905V6H17.53V4.0973H15.3546V6H14.6962ZM20.562 6H19.1493V1.63636H20.6067C21.0343 1.63636 21.4015 1.72372 21.7083 1.89844C22.0151 2.07173 22.2502 2.32102 22.4135 2.64631C22.5783 2.97017 22.6607 3.35866 22.6607 3.81179C22.6607 4.26634 22.5776 4.65696 22.4114 4.98366C22.2466 5.31037 22.008 5.56179 21.6955 5.73793C21.383 5.91264 21.0051 6 20.562 6ZM19.8077 5.42472H20.5257C20.8581 5.42472 21.1344 5.36222 21.3546 5.23722C21.5748 5.1108 21.7395 4.92827 21.8489 4.68963C21.9583 4.44957 22.013 4.15696 22.013 3.81179C22.013 3.46946 21.9583 3.17898 21.8489 2.94034C21.7409 2.7017 21.5797 2.5206 21.3652 2.39702C21.1507 2.27344 20.8844 2.21165 20.5662 2.21165H19.8077V5.42472Z\"\n fill=\"#C9C9C9\"/>\n </g>\n <defs>\n <clipPath id=\"clip0_28_1567\">\n <rect width=\"24\" height=\"24\" fill=\"white\"/>\n </clipPath>\n </defs>\n</svg>\n";
|
|
10088
10088
|
|
|
10089
|
-
const VERSION$
|
|
10089
|
+
const VERSION$6 = '2.19.12';
|
|
10090
10090
|
/**
|
|
10091
10091
|
* Events triggered by the plugin
|
|
10092
10092
|
* @beta
|
|
@@ -10179,13 +10179,13 @@ class BottomGear extends UICorePlugin {
|
|
|
10179
10179
|
* @internal
|
|
10180
10180
|
*/
|
|
10181
10181
|
get supportedVersion() {
|
|
10182
|
-
return { min: CLAPPR_VERSION };
|
|
10182
|
+
return { min: CLAPPR_VERSION$1 };
|
|
10183
10183
|
}
|
|
10184
10184
|
/**
|
|
10185
10185
|
* @internal
|
|
10186
10186
|
*/
|
|
10187
10187
|
static get version() {
|
|
10188
|
-
return VERSION$
|
|
10188
|
+
return VERSION$6;
|
|
10189
10189
|
}
|
|
10190
10190
|
static template = tmpl(pluginHtml$5);
|
|
10191
10191
|
/**
|
|
@@ -10310,6 +10310,339 @@ class BottomGear extends UICorePlugin {
|
|
|
10310
10310
|
}
|
|
10311
10311
|
}
|
|
10312
10312
|
|
|
10313
|
+
/**
|
|
10314
|
+
* @beta
|
|
10315
|
+
*/
|
|
10316
|
+
var Chronograph;
|
|
10317
|
+
(function (Chronograph) {
|
|
10318
|
+
Chronograph["Startup"] = "startup";
|
|
10319
|
+
Chronograph["Watch"] = "watch";
|
|
10320
|
+
Chronograph["Pause"] = "pause";
|
|
10321
|
+
Chronograph["Buffering"] = "buffering";
|
|
10322
|
+
Chronograph["Session"] = "session";
|
|
10323
|
+
// Latency = 'latency',
|
|
10324
|
+
})(Chronograph || (Chronograph = {}));
|
|
10325
|
+
/**
|
|
10326
|
+
* @beta
|
|
10327
|
+
*/
|
|
10328
|
+
var Counter;
|
|
10329
|
+
(function (Counter) {
|
|
10330
|
+
Counter["Play"] = "play";
|
|
10331
|
+
Counter["Pause"] = "pause";
|
|
10332
|
+
Counter["Error"] = "error";
|
|
10333
|
+
Counter["Buffering"] = "buffering";
|
|
10334
|
+
Counter["DecodedFrames"] = "decodedFrames";
|
|
10335
|
+
Counter["DroppedFrames"] = "droppedFrames";
|
|
10336
|
+
Counter["Fps"] = "fps";
|
|
10337
|
+
Counter["ChangeLevel"] = "changeLevel";
|
|
10338
|
+
Counter["Seek"] = "seek";
|
|
10339
|
+
Counter["Fullscreen"] = "fullscreen";
|
|
10340
|
+
Counter["DvrUsage"] = "dvrUsage";
|
|
10341
|
+
})(Counter || (Counter = {}));
|
|
10342
|
+
/**
|
|
10343
|
+
* @beta
|
|
10344
|
+
*/
|
|
10345
|
+
var ClapprStatsEvents;
|
|
10346
|
+
(function (ClapprStatsEvents) {
|
|
10347
|
+
/**
|
|
10348
|
+
* Emitted periodically with current measurements.
|
|
10349
|
+
*/
|
|
10350
|
+
ClapprStatsEvents["REPORT"] = "clappr:stats:report";
|
|
10351
|
+
/**
|
|
10352
|
+
* Emitted when the playback reaches a certain percentage of the total duration.
|
|
10353
|
+
*/
|
|
10354
|
+
// PERCENTAGE = 'clappr:stats:percentage',
|
|
10355
|
+
})(ClapprStatsEvents || (ClapprStatsEvents = {}));
|
|
10356
|
+
|
|
10357
|
+
function newMetrics$1() {
|
|
10358
|
+
return {
|
|
10359
|
+
counters: {
|
|
10360
|
+
play: 0,
|
|
10361
|
+
pause: 0,
|
|
10362
|
+
error: 0,
|
|
10363
|
+
buffering: 0,
|
|
10364
|
+
decodedFrames: 0,
|
|
10365
|
+
droppedFrames: 0,
|
|
10366
|
+
fps: 0,
|
|
10367
|
+
changeLevel: 0,
|
|
10368
|
+
seek: 0,
|
|
10369
|
+
fullscreen: 0,
|
|
10370
|
+
dvrUsage: 0,
|
|
10371
|
+
},
|
|
10372
|
+
chrono: {
|
|
10373
|
+
startup: 0,
|
|
10374
|
+
watch: 0,
|
|
10375
|
+
pause: 0,
|
|
10376
|
+
buffering: 0,
|
|
10377
|
+
session: 0,
|
|
10378
|
+
},
|
|
10379
|
+
extra: {
|
|
10380
|
+
playbackName: '',
|
|
10381
|
+
playbackType: '',
|
|
10382
|
+
bitratesHistory: [],
|
|
10383
|
+
bitrateWeightedMean: 0,
|
|
10384
|
+
bitrateMostUsed: 0,
|
|
10385
|
+
buffersize: 0,
|
|
10386
|
+
watchHistory: [],
|
|
10387
|
+
watchedPercentage: 0,
|
|
10388
|
+
bufferingPercentage: 0,
|
|
10389
|
+
bandwidth: 0,
|
|
10390
|
+
duration: 0,
|
|
10391
|
+
currentTime: 0,
|
|
10392
|
+
},
|
|
10393
|
+
custom: {},
|
|
10394
|
+
};
|
|
10395
|
+
}
|
|
10396
|
+
|
|
10397
|
+
/**
|
|
10398
|
+
* `PLUGIN` that measures data about playback, which can be useful for analyzing performance and UX.
|
|
10399
|
+
* @beta
|
|
10400
|
+
* @remarks
|
|
10401
|
+
* This plugin does not render anything and is supposed to be extended or used together with other plugins that actually render something.
|
|
10402
|
+
*
|
|
10403
|
+
* Configuration options - {@link ClapprStatsSettings}
|
|
10404
|
+
*
|
|
10405
|
+
* Events - {@link ClapprStatsEvents}
|
|
10406
|
+
*/
|
|
10407
|
+
class ClapprStats extends ContainerPlugin {
|
|
10408
|
+
timerId = null;
|
|
10409
|
+
lastDecodedFramesCount = 0;
|
|
10410
|
+
metrics = newMetrics$1();
|
|
10411
|
+
timers = {
|
|
10412
|
+
[Chronograph.Startup]: 0,
|
|
10413
|
+
[Chronograph.Watch]: 0,
|
|
10414
|
+
[Chronograph.Pause]: 0,
|
|
10415
|
+
[Chronograph.Buffering]: 0,
|
|
10416
|
+
[Chronograph.Session]: 0,
|
|
10417
|
+
};
|
|
10418
|
+
runEach;
|
|
10419
|
+
/**
|
|
10420
|
+
* @internal
|
|
10421
|
+
*/
|
|
10422
|
+
get name() {
|
|
10423
|
+
return 'clappr_stats';
|
|
10424
|
+
}
|
|
10425
|
+
/**
|
|
10426
|
+
* @internal
|
|
10427
|
+
*/
|
|
10428
|
+
get supportedVersion() {
|
|
10429
|
+
return { min: CLAPPR_VERSION$1 };
|
|
10430
|
+
}
|
|
10431
|
+
get playbackName() {
|
|
10432
|
+
return String(this.container.playback.name || '');
|
|
10433
|
+
}
|
|
10434
|
+
get playbackType() {
|
|
10435
|
+
return this.container.getPlaybackType();
|
|
10436
|
+
}
|
|
10437
|
+
now() {
|
|
10438
|
+
const hasPerformanceSupport = window.performance && typeof window.performance.now === 'function';
|
|
10439
|
+
return hasPerformanceSupport
|
|
10440
|
+
? window.performance.now()
|
|
10441
|
+
: new Date().getTime();
|
|
10442
|
+
}
|
|
10443
|
+
inc(counter) {
|
|
10444
|
+
this.metrics.counters[counter] += 1;
|
|
10445
|
+
}
|
|
10446
|
+
// _timerHasStarted(timer) {
|
|
10447
|
+
// return this[`_start${timer}`] !== undefined;
|
|
10448
|
+
// }
|
|
10449
|
+
start(timer) {
|
|
10450
|
+
// this[`_start${timer}`] = this._now();
|
|
10451
|
+
this.timers[timer] = this.now();
|
|
10452
|
+
}
|
|
10453
|
+
stop(timer) {
|
|
10454
|
+
// this._metrics.timers[timer] += this._now() - this[`_start${timer}`];
|
|
10455
|
+
this.metrics.chrono[timer] += this.now() - this.timers[timer];
|
|
10456
|
+
}
|
|
10457
|
+
constructor(container) {
|
|
10458
|
+
super(container);
|
|
10459
|
+
this.runEach = container.options.clapprStats?.runEach ?? 5000;
|
|
10460
|
+
}
|
|
10461
|
+
/**
|
|
10462
|
+
* @internal
|
|
10463
|
+
*/
|
|
10464
|
+
bindEvents() {
|
|
10465
|
+
this.listenTo(this.container, Events.CONTAINER_BITRATE, this.onBitrate);
|
|
10466
|
+
this.listenTo(this.container, Events.CONTAINER_STOP, this.stopReporting);
|
|
10467
|
+
this.listenTo(this.container, Events.CONTAINER_ENDED, this.stopReporting);
|
|
10468
|
+
this.listenToOnce(this.container.playback, Events.PLAYBACK_PLAY_INTENT, this.startTimers);
|
|
10469
|
+
this.listenToOnce(this.container, Events.CONTAINER_PLAY, this.onFirstPlaying);
|
|
10470
|
+
this.listenTo(this.container, Events.CONTAINER_PLAY, this.onPlay);
|
|
10471
|
+
this.listenTo(this.container, Events.CONTAINER_PAUSE, this.onPause);
|
|
10472
|
+
this.listenToOnce(this.container, Events.CONTAINER_STATE_BUFFERING, this.onBuffering);
|
|
10473
|
+
this.listenTo(this.container, Events.CONTAINER_SEEK, this.onSeek);
|
|
10474
|
+
this.listenTo(this.container, Events.CONTAINER_ERROR, () => this.inc(Counter.Error));
|
|
10475
|
+
this.listenTo(this.container, Events.CONTAINER_FULLSCREEN, () => this.inc(Counter.Fullscreen));
|
|
10476
|
+
this.listenTo(this.container, Events.CONTAINER_PLAYBACKDVRSTATECHANGED, (dvrInUse) => {
|
|
10477
|
+
dvrInUse && this.inc(Counter.DvrUsage);
|
|
10478
|
+
});
|
|
10479
|
+
this.listenTo(this.container.playback, Events.PLAYBACK_PROGRESS, this.onProgress);
|
|
10480
|
+
this.listenTo(this.container.playback, Events.PLAYBACK_TIMEUPDATE, this.onTimeUpdate);
|
|
10481
|
+
}
|
|
10482
|
+
/**
|
|
10483
|
+
* @internal
|
|
10484
|
+
*/
|
|
10485
|
+
destroy() {
|
|
10486
|
+
this.stopReporting();
|
|
10487
|
+
super.destroy();
|
|
10488
|
+
}
|
|
10489
|
+
/**
|
|
10490
|
+
* Returns the collected metrics.
|
|
10491
|
+
* @returns Measurements collected so far
|
|
10492
|
+
*/
|
|
10493
|
+
exportMetrics() {
|
|
10494
|
+
return structuredClone(this.metrics);
|
|
10495
|
+
}
|
|
10496
|
+
onBitrate(newBitrate) {
|
|
10497
|
+
const bitrate = newBitrate.bitrate;
|
|
10498
|
+
const now = this.now();
|
|
10499
|
+
if (this.metrics.extra.bitratesHistory.length > 0) {
|
|
10500
|
+
const last = this.metrics.extra.bitratesHistory[this.metrics.extra.bitratesHistory.length - 1];
|
|
10501
|
+
last.end = now;
|
|
10502
|
+
last.time = now - last.start;
|
|
10503
|
+
}
|
|
10504
|
+
this.metrics.extra.bitratesHistory.push({ start: this.now(), bitrate });
|
|
10505
|
+
this.inc(Counter.ChangeLevel);
|
|
10506
|
+
}
|
|
10507
|
+
stopReporting() {
|
|
10508
|
+
this.buildReport();
|
|
10509
|
+
if (this.timerId !== null) {
|
|
10510
|
+
clearInterval(this.timerId);
|
|
10511
|
+
this.timerId = null;
|
|
10512
|
+
}
|
|
10513
|
+
}
|
|
10514
|
+
startTimers() {
|
|
10515
|
+
this.timerId = setInterval(this.buildReport.bind(this), this.runEach);
|
|
10516
|
+
this.start(Chronograph.Session);
|
|
10517
|
+
this.start(Chronograph.Startup);
|
|
10518
|
+
}
|
|
10519
|
+
onFirstPlaying() {
|
|
10520
|
+
this.listenTo(this.container, Events.CONTAINER_TIMEUPDATE, this.onContainerUpdateWhilePlaying);
|
|
10521
|
+
this.start(Chronograph.Watch);
|
|
10522
|
+
this.stop(Chronograph.Startup);
|
|
10523
|
+
}
|
|
10524
|
+
playAfterPause() {
|
|
10525
|
+
this.listenTo(this.container, Events.CONTAINER_TIMEUPDATE, this.onContainerUpdateWhilePlaying);
|
|
10526
|
+
this.stop(Chronograph.Pause);
|
|
10527
|
+
this.start(Chronograph.Watch);
|
|
10528
|
+
}
|
|
10529
|
+
onPlay() {
|
|
10530
|
+
this.inc(Counter.Play);
|
|
10531
|
+
}
|
|
10532
|
+
onPause() {
|
|
10533
|
+
this.stop(Chronograph.Watch);
|
|
10534
|
+
this.start(Chronograph.Pause);
|
|
10535
|
+
this.inc(Counter.Pause);
|
|
10536
|
+
this.listenToOnce(this.container, Events.CONTAINER_PLAY, this.playAfterPause);
|
|
10537
|
+
this.stopListening(this.container, Events.CONTAINER_TIMEUPDATE, this.onContainerUpdateWhilePlaying);
|
|
10538
|
+
}
|
|
10539
|
+
onSeek(e) {
|
|
10540
|
+
this.inc(Counter.Seek);
|
|
10541
|
+
this.metrics.extra.watchHistory.push([e * 1000, e * 1000]);
|
|
10542
|
+
}
|
|
10543
|
+
onTimeUpdate(e) {
|
|
10544
|
+
const current = e.current * 1000, total = e.total * 1000, l = this.metrics.extra.watchHistory.length;
|
|
10545
|
+
this.metrics.extra.duration = total;
|
|
10546
|
+
this.metrics.extra.currentTime = current;
|
|
10547
|
+
// TODO what if it's a live stream?
|
|
10548
|
+
this.metrics.extra.watchedPercentage = (current / total) * 100;
|
|
10549
|
+
if (l === 0) {
|
|
10550
|
+
this.metrics.extra.watchHistory.push([current, current]);
|
|
10551
|
+
}
|
|
10552
|
+
else {
|
|
10553
|
+
this.metrics.extra.watchHistory[l - 1][1] = current;
|
|
10554
|
+
}
|
|
10555
|
+
if (this.metrics.extra.bitratesHistory.length > 0) {
|
|
10556
|
+
const lastBitrate = this.metrics.extra.bitratesHistory[this.metrics.extra.bitratesHistory.length - 1];
|
|
10557
|
+
if (!lastBitrate.end) {
|
|
10558
|
+
lastBitrate.time = this.now() - lastBitrate.start;
|
|
10559
|
+
}
|
|
10560
|
+
}
|
|
10561
|
+
this.onCompletion();
|
|
10562
|
+
}
|
|
10563
|
+
onContainerUpdateWhilePlaying() {
|
|
10564
|
+
if (this.container.playback.isPlaying()) {
|
|
10565
|
+
this.stop(Chronograph.Watch);
|
|
10566
|
+
this.start(Chronograph.Watch);
|
|
10567
|
+
}
|
|
10568
|
+
}
|
|
10569
|
+
onBuffering() {
|
|
10570
|
+
this.inc(Counter.Buffering);
|
|
10571
|
+
this.start(Chronograph.Buffering);
|
|
10572
|
+
this.listenToOnce(this.container, Events.CONTAINER_STATE_BUFFERFULL, this.onBufferfull);
|
|
10573
|
+
}
|
|
10574
|
+
onBufferfull() {
|
|
10575
|
+
this.stop(Chronograph.Buffering);
|
|
10576
|
+
this.listenToOnce(this.container, Events.CONTAINER_STATE_BUFFERING, this.onBuffering);
|
|
10577
|
+
}
|
|
10578
|
+
onProgress(progress) {
|
|
10579
|
+
this.metrics.extra.buffersize = progress.current * 1000;
|
|
10580
|
+
}
|
|
10581
|
+
onCompletion() {
|
|
10582
|
+
// Decide if this is needed
|
|
10583
|
+
// const currentPercentage = this.metrics.extra.watchedPercentage;
|
|
10584
|
+
// this.trigger(ClapprStatsEvents.PERCENTAGE, currentPercentage);
|
|
10585
|
+
}
|
|
10586
|
+
buildReport() {
|
|
10587
|
+
this.stop(Chronograph.Session);
|
|
10588
|
+
this.start(Chronograph.Session);
|
|
10589
|
+
this.metrics.extra.playbackName = this.playbackName;
|
|
10590
|
+
this.metrics.extra.playbackType = this.playbackType;
|
|
10591
|
+
this.calcBitrates();
|
|
10592
|
+
this.calcBufferingPercentage();
|
|
10593
|
+
// TODO calc FPS properly, e.g., on TIMEUPDATE event
|
|
10594
|
+
this.fetchFPS();
|
|
10595
|
+
this.trigger(ClapprStatsEvents.REPORT, structuredClone(this.metrics));
|
|
10596
|
+
}
|
|
10597
|
+
fetchFPS() {
|
|
10598
|
+
// TODO check if the playback and media sources support video, then use the common method
|
|
10599
|
+
// flashls ??? - hls.droppedFramesl hls.stream.bufferLength (seconds)
|
|
10600
|
+
// hls ??? (use the same?)
|
|
10601
|
+
const fetchFPS = {
|
|
10602
|
+
html5_video: this.html5FetchFPS,
|
|
10603
|
+
hls: this.html5FetchFPS,
|
|
10604
|
+
dash: this.html5FetchFPS,
|
|
10605
|
+
};
|
|
10606
|
+
if (this.playbackName in fetchFPS) {
|
|
10607
|
+
fetchFPS[this.playbackName].call(this);
|
|
10608
|
+
}
|
|
10609
|
+
}
|
|
10610
|
+
// TODO sort out
|
|
10611
|
+
calcBitrates() {
|
|
10612
|
+
const { bitratesHistory } = this.metrics.extra;
|
|
10613
|
+
if (bitratesHistory.length === 0) {
|
|
10614
|
+
return;
|
|
10615
|
+
}
|
|
10616
|
+
let totalTime = 0;
|
|
10617
|
+
let weightedTotal = 0;
|
|
10618
|
+
for (const { bitrate, time = 0 } of bitratesHistory) {
|
|
10619
|
+
totalTime += time;
|
|
10620
|
+
weightedTotal += bitrate * time;
|
|
10621
|
+
}
|
|
10622
|
+
this.metrics.extra.bitrateWeightedMean = weightedTotal / totalTime;
|
|
10623
|
+
this.metrics.extra.bitrateMostUsed = bitratesHistory.reduce((mostUsed, current) => (current.time || 0) > (mostUsed.time || 0) ? current : mostUsed, { time: 0, bitrate: 0, start: 0, end: 0 }).bitrate;
|
|
10624
|
+
}
|
|
10625
|
+
calcBufferingPercentage() {
|
|
10626
|
+
if (this.metrics.extra.duration > 0) {
|
|
10627
|
+
this.metrics.extra.bufferingPercentage =
|
|
10628
|
+
(this.metrics.chrono.buffering / this.metrics.extra.duration) * 100;
|
|
10629
|
+
}
|
|
10630
|
+
}
|
|
10631
|
+
html5FetchFPS() {
|
|
10632
|
+
const videoTag = this.container.playback.el;
|
|
10633
|
+
const getFirstValidValue = (...args) => args.find((val) => val !== undefined);
|
|
10634
|
+
const decodedFrames = getFirstValidValue(videoTag.webkitDecodedFrameCount, videoTag.mozDecodedFrames, 0);
|
|
10635
|
+
const droppedFrames = getFirstValidValue(videoTag.webkitDroppedFrameCount, videoTag.mozParsedFrames && videoTag.mozDecodedFrames
|
|
10636
|
+
? videoTag.mozParsedFrames - videoTag.mozDecodedFrames
|
|
10637
|
+
: 0, 0);
|
|
10638
|
+
const delta = decodedFrames - (this.lastDecodedFramesCount || 0);
|
|
10639
|
+
this.metrics.counters.decodedFrames = decodedFrames;
|
|
10640
|
+
this.metrics.counters.droppedFrames = droppedFrames;
|
|
10641
|
+
this.metrics.counters.fps = delta / (this.runEach / 1000); // TODO use time delta instead of runEach
|
|
10642
|
+
this.lastDecodedFramesCount = decodedFrames;
|
|
10643
|
+
}
|
|
10644
|
+
}
|
|
10645
|
+
|
|
10313
10646
|
function getDefaultExportFromCjs (x) {
|
|
10314
10647
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
10315
10648
|
}
|
|
@@ -11381,57 +11714,7 @@ function requireMousetrap () {
|
|
|
11381
11714
|
var mousetrapExports = requireMousetrap();
|
|
11382
11715
|
const Mousetrap = /*@__PURE__*/getDefaultExportFromCjs(mousetrapExports);
|
|
11383
11716
|
|
|
11384
|
-
|
|
11385
|
-
* @beta
|
|
11386
|
-
*/
|
|
11387
|
-
var ClapprStatsEvents;
|
|
11388
|
-
(function (ClapprStatsEvents) {
|
|
11389
|
-
ClapprStatsEvents["REPORT_EVENT"] = "clappr:stats:report";
|
|
11390
|
-
ClapprStatsEvents["PERCENTAGE_EVENT"] = "clappr:stats:percentage";
|
|
11391
|
-
})(ClapprStatsEvents || (ClapprStatsEvents = {}));
|
|
11392
|
-
|
|
11393
|
-
function newMetrics$1() {
|
|
11394
|
-
return {
|
|
11395
|
-
counters: {
|
|
11396
|
-
play: 0,
|
|
11397
|
-
pause: 0,
|
|
11398
|
-
error: 0,
|
|
11399
|
-
buffering: 0,
|
|
11400
|
-
decodedFrames: 0,
|
|
11401
|
-
droppedFrames: 0,
|
|
11402
|
-
fps: 0,
|
|
11403
|
-
changeLevel: 0,
|
|
11404
|
-
seek: 0,
|
|
11405
|
-
fullscreen: 0,
|
|
11406
|
-
dvrUsage: 0,
|
|
11407
|
-
},
|
|
11408
|
-
timers: {
|
|
11409
|
-
startup: 0,
|
|
11410
|
-
watch: 0,
|
|
11411
|
-
pause: 0,
|
|
11412
|
-
buffering: 0,
|
|
11413
|
-
session: 0,
|
|
11414
|
-
latency: 0,
|
|
11415
|
-
},
|
|
11416
|
-
extra: {
|
|
11417
|
-
playbackName: '',
|
|
11418
|
-
playbackType: '',
|
|
11419
|
-
bitratesHistory: [],
|
|
11420
|
-
bitrateWeightedMean: 0,
|
|
11421
|
-
bitrateMostUsed: 0,
|
|
11422
|
-
buffersize: 0,
|
|
11423
|
-
watchHistory: [],
|
|
11424
|
-
watchedPercentage: 0,
|
|
11425
|
-
bufferingPercentage: 0,
|
|
11426
|
-
bandwidth: 0,
|
|
11427
|
-
duration: 0,
|
|
11428
|
-
currentTime: 0,
|
|
11429
|
-
},
|
|
11430
|
-
custom: {},
|
|
11431
|
-
};
|
|
11432
|
-
}
|
|
11433
|
-
|
|
11434
|
-
var humanFormat$2 = {exports: {}};
|
|
11717
|
+
var humanFormat$2 = {exports: {}};
|
|
11435
11718
|
|
|
11436
11719
|
var humanFormat$1 = humanFormat$2.exports;
|
|
11437
11720
|
|
|
@@ -12461,7 +12744,7 @@ const drawSummary = (customMetrics, vodContainer, liveContainer) => {
|
|
|
12461
12744
|
* When clicked, it shows an overlay window with the information about the network speed, latency, etc,
|
|
12462
12745
|
* and recommended quality level.
|
|
12463
12746
|
*/
|
|
12464
|
-
class
|
|
12747
|
+
class NerdStats extends UICorePlugin {
|
|
12465
12748
|
container = null;
|
|
12466
12749
|
customMetrics = {
|
|
12467
12750
|
connectionSpeed: 0,
|
|
@@ -12483,7 +12766,7 @@ class ClapprNerdStats extends UICorePlugin {
|
|
|
12483
12766
|
* @internal
|
|
12484
12767
|
*/
|
|
12485
12768
|
get supportedVersion() {
|
|
12486
|
-
return { min: CLAPPR_VERSION };
|
|
12769
|
+
return { min: CLAPPR_VERSION$1 };
|
|
12487
12770
|
}
|
|
12488
12771
|
static template = tmpl(pluginHtml$4);
|
|
12489
12772
|
/**
|
|
@@ -12544,517 +12827,161 @@ class ClapprNerdStats extends UICorePlugin {
|
|
|
12544
12827
|
this.listenTo(bottomGear, GearEvents.RENDERED, this.addToBottomGear);
|
|
12545
12828
|
this.container = this.core.activeContainer;
|
|
12546
12829
|
const clapprStats = this.container?.getPlugin('clappr_stats');
|
|
12547
|
-
|
|
12548
|
-
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
|
|
12553
|
-
|
|
12554
|
-
|
|
12555
|
-
|
|
12556
|
-
|
|
12557
|
-
|
|
12558
|
-
|
|
12559
|
-
|
|
12560
|
-
|
|
12830
|
+
assert(clapprStats, 'clappr-stats not available. Please, include it as a plugin of your Clappr instance.\n' +
|
|
12831
|
+
'For more info, visit: https://github.com/clappr/clappr-stats.');
|
|
12832
|
+
Mousetrap.bind(this.shortcut, this.toggle);
|
|
12833
|
+
this.listenTo(this.core, Events.CORE_RESIZE, this.onPlayerResize);
|
|
12834
|
+
this.listenTo(clapprStats, ClapprStatsEvents.REPORT, this.updateMetrics);
|
|
12835
|
+
this.updateMetrics(clapprStats.exportMetrics());
|
|
12836
|
+
this.render();
|
|
12837
|
+
}
|
|
12838
|
+
/**
|
|
12839
|
+
* @internal
|
|
12840
|
+
*/
|
|
12841
|
+
destroy() {
|
|
12842
|
+
Mousetrap.unbind(this.shortcut);
|
|
12843
|
+
return super.destroy();
|
|
12561
12844
|
}
|
|
12562
|
-
toggle() {
|
|
12845
|
+
toggle = () => {
|
|
12563
12846
|
if (this.showing) {
|
|
12564
12847
|
this.hide();
|
|
12565
12848
|
}
|
|
12566
12849
|
else {
|
|
12567
12850
|
this.show();
|
|
12568
12851
|
}
|
|
12569
|
-
}
|
|
12852
|
+
};
|
|
12570
12853
|
show() {
|
|
12571
12854
|
this.core.$el.find(this.statsBoxElem).show();
|
|
12572
12855
|
this.showing = true;
|
|
12573
12856
|
this.refreshSpeedTest();
|
|
12574
|
-
initSpeedTest(this.customMetrics)
|
|
12575
|
-
.then(() => {
|
|
12576
|
-
startSpeedtest();
|
|
12577
|
-
})
|
|
12578
|
-
.catch((e) => {
|
|
12579
|
-
this.disable();
|
|
12580
|
-
});
|
|
12581
|
-
}
|
|
12582
|
-
hide() {
|
|
12583
|
-
this.core.$el.find(this.statsBoxElem).hide();
|
|
12584
|
-
this.showing = false;
|
|
12585
|
-
stopSpeedtest();
|
|
12586
|
-
}
|
|
12587
|
-
onPlayerResize() {
|
|
12588
|
-
this.setStatsBoxSize();
|
|
12589
|
-
}
|
|
12590
|
-
addGeneralMetrics() {
|
|
12591
|
-
this.metrics.general = {
|
|
12592
|
-
displayResolution: this.playerWidth + 'x' + this.playerHeight,
|
|
12593
|
-
volume: this.container?.volume,
|
|
12594
|
-
};
|
|
12595
|
-
}
|
|
12596
|
-
addCustomMetrics() {
|
|
12597
|
-
this.metrics.custom = this.customMetrics;
|
|
12598
|
-
const videoQualityNames = [
|
|
12599
|
-
'SD (480p)',
|
|
12600
|
-
'HD (720p)',
|
|
12601
|
-
'Full HD (1080p)',
|
|
12602
|
-
'2K (1440p)',
|
|
12603
|
-
'4K (2160p)',
|
|
12604
|
-
];
|
|
12605
|
-
const { connectionSpeed, ping } = this.customMetrics;
|
|
12606
|
-
if (!connectionSpeed || !ping) {
|
|
12607
|
-
const calculatingText = 'Calculating... Please wait.';
|
|
12608
|
-
this.metrics.custom.vodQuality = calculatingText;
|
|
12609
|
-
this.metrics.custom.liveQuality = calculatingText;
|
|
12610
|
-
return;
|
|
12611
|
-
}
|
|
12612
|
-
const downloadQuality = getDownloadQuality(connectionSpeed);
|
|
12613
|
-
const pingQuality = getPingQuality(ping);
|
|
12614
|
-
const liveQuality = Math.min(downloadQuality, pingQuality);
|
|
12615
|
-
const prefix = 'Optimal for ';
|
|
12616
|
-
this.metrics.custom.vodQuality =
|
|
12617
|
-
prefix + videoQualityNames[downloadQuality - 1];
|
|
12618
|
-
this.metrics.custom.liveQuality =
|
|
12619
|
-
prefix + videoQualityNames[liveQuality - 1];
|
|
12620
|
-
}
|
|
12621
|
-
updateMetrics(metrics) {
|
|
12622
|
-
Object.assign(this.metrics, metrics);
|
|
12623
|
-
this.addGeneralMetrics();
|
|
12624
|
-
this.addCustomMetrics();
|
|
12625
|
-
const scrollTop = this.core.$el.find(this.statsBoxElem).scrollTop();
|
|
12626
|
-
this.$el.html(ClapprNerdStats.template({
|
|
12627
|
-
metrics: Formatter.format(this.metrics),
|
|
12628
|
-
iconPosition: this.iconPosition,
|
|
12629
|
-
}));
|
|
12630
|
-
this.setStatsBoxSize();
|
|
12631
|
-
drawSpeedTestResults();
|
|
12632
|
-
drawSummary(this.metrics?.custom, this.$el.find('.speedtest-quality-content[data-streaming-type="vod"]'), this.$el.find('.speedtest-quality-content[data-streaming-type="live"]'));
|
|
12633
|
-
this.core.$el.find(this.statsBoxElem).scrollTop(scrollTop);
|
|
12634
|
-
if (!this.showing) {
|
|
12635
|
-
this.hide();
|
|
12636
|
-
}
|
|
12637
|
-
}
|
|
12638
|
-
setStatsBoxSize() {
|
|
12639
|
-
if (this.playerWidth >= this.statsBoxWidthThreshold) {
|
|
12640
|
-
this.$el.find(this.statsBoxElem).addClass('wide');
|
|
12641
|
-
this.$el.find(this.statsBoxElem).removeClass('narrow');
|
|
12642
|
-
}
|
|
12643
|
-
else {
|
|
12644
|
-
this.$el.find(this.statsBoxElem).removeClass('wide');
|
|
12645
|
-
this.$el.find(this.statsBoxElem).addClass('narrow');
|
|
12646
|
-
}
|
|
12647
|
-
}
|
|
12648
|
-
/**
|
|
12649
|
-
* @internal
|
|
12650
|
-
*/
|
|
12651
|
-
render() {
|
|
12652
|
-
// TODO append to the container
|
|
12653
|
-
this.core.$el.append(this.$el[0]);
|
|
12654
|
-
this.hide();
|
|
12655
|
-
return this;
|
|
12656
|
-
}
|
|
12657
|
-
addToBottomGear() {
|
|
12658
|
-
const gear = this.core.getPlugin('bottom_gear');
|
|
12659
|
-
gear
|
|
12660
|
-
.addItem('nerd')
|
|
12661
|
-
.html(ClapprNerdStats.buttonTemplate({
|
|
12662
|
-
icon: statsIcon,
|
|
12663
|
-
i18n: this.core.i18n,
|
|
12664
|
-
}))
|
|
12665
|
-
.on('click', (e) => {
|
|
12666
|
-
e.stopPropagation();
|
|
12667
|
-
this.toggle();
|
|
12668
|
-
});
|
|
12669
|
-
}
|
|
12670
|
-
clearCustomMetrics() {
|
|
12671
|
-
const clapprStats = this.container?.getPlugin('clappr_stats');
|
|
12672
|
-
this.customMetrics.connectionSpeed = 0;
|
|
12673
|
-
this.customMetrics.ping = 0;
|
|
12674
|
-
this.customMetrics.jitter = 0;
|
|
12675
|
-
if (clapprStats) {
|
|
12676
|
-
this.updateMetrics(clapprStats.exportMetrics());
|
|
12677
|
-
}
|
|
12678
|
-
}
|
|
12679
|
-
refreshSpeedTest() {
|
|
12680
|
-
stopSpeedtest();
|
|
12681
|
-
setTimeout(() => {
|
|
12682
|
-
this.clearCustomMetrics();
|
|
12683
|
-
clearSpeedTestResults();
|
|
12684
|
-
drawSpeedTestResults();
|
|
12685
|
-
}, 200);
|
|
12686
|
-
setTimeout(() => {
|
|
12687
|
-
startSpeedtest();
|
|
12688
|
-
}, 800);
|
|
12689
|
-
}
|
|
12690
|
-
}
|
|
12691
|
-
function newMetrics() {
|
|
12692
|
-
return {
|
|
12693
|
-
...newMetrics$1(),
|
|
12694
|
-
general: {},
|
|
12695
|
-
custom: {
|
|
12696
|
-
connectionSpeed: 0,
|
|
12697
|
-
ping: 0,
|
|
12698
|
-
jitter: 0,
|
|
12699
|
-
},
|
|
12700
|
-
};
|
|
12701
|
-
}
|
|
12702
|
-
|
|
12703
|
-
// TODO: fix
|
|
12704
|
-
const updateMetrics = () => { };
|
|
12705
|
-
/**
|
|
12706
|
-
* `PLUGIN` that collects useful statistics about playback performance.
|
|
12707
|
-
* @beta
|
|
12708
|
-
* @remarks
|
|
12709
|
-
* This plugin does not render anything and is supposed to be extended or used together with other plugins that actually render something.
|
|
12710
|
-
*/
|
|
12711
|
-
class ClapprStats extends ContainerPlugin {
|
|
12712
|
-
bwMeasureCount = 0;
|
|
12713
|
-
intervalId = null;
|
|
12714
|
-
lastDecodedFramesCount = 0;
|
|
12715
|
-
metrics = newMetrics$1();
|
|
12716
|
-
completion;
|
|
12717
|
-
_onReport;
|
|
12718
|
-
runBandwidthTestEvery;
|
|
12719
|
-
runEach;
|
|
12720
|
-
timers = {
|
|
12721
|
-
startup: 0,
|
|
12722
|
-
watch: 0,
|
|
12723
|
-
pause: 0,
|
|
12724
|
-
buffering: 0,
|
|
12725
|
-
session: 0,
|
|
12726
|
-
latency: 0,
|
|
12727
|
-
};
|
|
12728
|
-
updateFn = updateMetrics;
|
|
12729
|
-
urisToMeasureBandwidth;
|
|
12730
|
-
uriToMeasureLatency;
|
|
12731
|
-
/**
|
|
12732
|
-
* @internal
|
|
12733
|
-
*/
|
|
12734
|
-
get name() {
|
|
12735
|
-
return 'clappr_stats';
|
|
12736
|
-
}
|
|
12737
|
-
/**
|
|
12738
|
-
* @internal
|
|
12739
|
-
*/
|
|
12740
|
-
get supportedVersion() {
|
|
12741
|
-
return { min: CLAPPR_VERSION };
|
|
12742
|
-
}
|
|
12743
|
-
get _playbackName() {
|
|
12744
|
-
return String(this.container.playback.name || '');
|
|
12745
|
-
}
|
|
12746
|
-
get _playbackType() {
|
|
12747
|
-
return this.container.getPlaybackType();
|
|
12748
|
-
}
|
|
12749
|
-
_now() {
|
|
12750
|
-
const hasPerformanceSupport = window.performance && typeof (window.performance.now) === 'function';
|
|
12751
|
-
return (hasPerformanceSupport) ? window.performance.now() : new Date().getTime();
|
|
12752
|
-
}
|
|
12753
|
-
_inc(counter) {
|
|
12754
|
-
this.metrics.counters[counter] += 1;
|
|
12755
|
-
}
|
|
12756
|
-
// _timerHasStarted(timer) {
|
|
12757
|
-
// return this[`_start${timer}`] !== undefined;
|
|
12758
|
-
// }
|
|
12759
|
-
start(timer) {
|
|
12760
|
-
// this[`_start${timer}`] = this._now();
|
|
12761
|
-
this.timers[timer] = this._now();
|
|
12762
|
-
}
|
|
12763
|
-
_stop(timer) {
|
|
12764
|
-
// this._metrics.timers[timer] += this._now() - this[`_start${timer}`];
|
|
12765
|
-
this.metrics.timers[timer] += this._now() - this.timers[timer];
|
|
12766
|
-
}
|
|
12767
|
-
/**
|
|
12768
|
-
* Registers a callback to receive the metrics.
|
|
12769
|
-
* @param updateMetricsFn - The callback to receive the metrics
|
|
12770
|
-
*/
|
|
12771
|
-
setUpdateMetrics(updateMetricsFn) {
|
|
12772
|
-
// TODO use events instead
|
|
12773
|
-
this.updateFn = updateMetricsFn;
|
|
12774
|
-
}
|
|
12775
|
-
_defaultReport(metrics) {
|
|
12776
|
-
this.updateFn(metrics);
|
|
12777
|
-
}
|
|
12778
|
-
constructor(container) {
|
|
12779
|
-
super(container);
|
|
12780
|
-
this.runEach = container.options.clapprStats?.runEach ?? 5000;
|
|
12781
|
-
this._onReport = container.options.clapprStats?.onReport ?? this._defaultReport;
|
|
12782
|
-
this.uriToMeasureLatency = container.options.clapprStats?.uriToMeasureLatency;
|
|
12783
|
-
this.urisToMeasureBandwidth = container.options.clapprStats?.urisToMeasureBandwidth;
|
|
12784
|
-
this.runBandwidthTestEvery = container.options.clapprStats?.runBandwidthTestEvery ?? 10;
|
|
12785
|
-
this.completion = {
|
|
12786
|
-
watch: container.options.clapprStats?.onCompletion ?? [],
|
|
12787
|
-
calls: []
|
|
12788
|
-
};
|
|
12789
|
-
}
|
|
12790
|
-
/**
|
|
12791
|
-
* @internal
|
|
12792
|
-
*/
|
|
12793
|
-
bindEvents() {
|
|
12794
|
-
this.listenTo(this.container, Events.CONTAINER_BITRATE, this.onBitrate);
|
|
12795
|
-
this.listenTo(this.container, Events.CONTAINER_STOP, this.stopReporting);
|
|
12796
|
-
this.listenTo(this.container, Events.CONTAINER_ENDED, this.stopReporting);
|
|
12797
|
-
this.listenToOnce(this.container.playback, Events.PLAYBACK_PLAY_INTENT, this.startTimers);
|
|
12798
|
-
this.listenToOnce(this.container, Events.CONTAINER_PLAY, this.onFirstPlaying);
|
|
12799
|
-
this.listenTo(this.container, Events.CONTAINER_PLAY, this.onPlay);
|
|
12800
|
-
this.listenTo(this.container, Events.CONTAINER_PAUSE, this.onPause);
|
|
12801
|
-
this.listenToOnce(this.container, Events.CONTAINER_STATE_BUFFERING, this.onBuffering);
|
|
12802
|
-
this.listenTo(this.container, Events.CONTAINER_SEEK, this.onSeek);
|
|
12803
|
-
this.listenTo(this.container, Events.CONTAINER_ERROR, () => this._inc('error'));
|
|
12804
|
-
this.listenTo(this.container, Events.CONTAINER_FULLSCREEN, () => this._inc('fullscreen'));
|
|
12805
|
-
this.listenTo(this.container, Events.CONTAINER_PLAYBACKDVRSTATECHANGED, (dvrInUse) => {
|
|
12806
|
-
dvrInUse && this._inc('dvrUsage');
|
|
12807
|
-
});
|
|
12808
|
-
this.listenTo(this.container.playback, Events.PLAYBACK_PROGRESS, this.onProgress);
|
|
12809
|
-
this.listenTo(this.container.playback, Events.PLAYBACK_TIMEUPDATE, this.onTimeUpdate);
|
|
12810
|
-
}
|
|
12811
|
-
/**
|
|
12812
|
-
* @internal
|
|
12813
|
-
*/
|
|
12814
|
-
destroy() {
|
|
12815
|
-
this.stopReporting();
|
|
12816
|
-
super.destroy();
|
|
12817
|
-
}
|
|
12818
|
-
/**
|
|
12819
|
-
* Returns the collected metrics.
|
|
12820
|
-
* @returns Currently collected metrics
|
|
12821
|
-
*/
|
|
12822
|
-
exportMetrics() {
|
|
12823
|
-
return structuredClone(this.metrics);
|
|
12824
|
-
}
|
|
12825
|
-
onBitrate(newBitrate) {
|
|
12826
|
-
const bitrate = newBitrate.bitrate;
|
|
12827
|
-
const now = this._now();
|
|
12828
|
-
if (this.metrics.extra.bitratesHistory.length > 0) {
|
|
12829
|
-
const beforeLast = this.metrics.extra.bitratesHistory[this.metrics.extra.bitratesHistory.length - 1];
|
|
12830
|
-
beforeLast.end = now;
|
|
12831
|
-
beforeLast.time = now - beforeLast.start;
|
|
12832
|
-
}
|
|
12833
|
-
this.metrics.extra.bitratesHistory.push({ start: this._now(), bitrate: bitrate });
|
|
12834
|
-
this._inc('changeLevel');
|
|
12835
|
-
}
|
|
12836
|
-
stopReporting() {
|
|
12837
|
-
this._buildReport();
|
|
12838
|
-
if (this.intervalId !== null) {
|
|
12839
|
-
clearInterval(this.intervalId);
|
|
12840
|
-
this.intervalId = null;
|
|
12841
|
-
}
|
|
12842
|
-
this._newMetrics();
|
|
12843
|
-
// TODO
|
|
12844
|
-
// @ts-ignore
|
|
12845
|
-
this.stopListening();
|
|
12846
|
-
this.bindEvents();
|
|
12847
|
-
}
|
|
12848
|
-
startTimers() {
|
|
12849
|
-
this.intervalId = setInterval(this._buildReport.bind(this), this.runEach);
|
|
12850
|
-
this.start('session');
|
|
12851
|
-
this.start('startup');
|
|
12852
|
-
}
|
|
12853
|
-
onFirstPlaying() {
|
|
12854
|
-
this.listenTo(this.container, Events.CONTAINER_TIMEUPDATE, this.onContainerUpdateWhilePlaying);
|
|
12855
|
-
this.start('watch');
|
|
12856
|
-
this._stop('startup');
|
|
12857
|
-
}
|
|
12858
|
-
playAfterPause() {
|
|
12859
|
-
this.listenTo(this.container, Events.CONTAINER_TIMEUPDATE, this.onContainerUpdateWhilePlaying);
|
|
12860
|
-
this._stop('pause');
|
|
12861
|
-
this.start('watch');
|
|
12862
|
-
}
|
|
12863
|
-
onPlay() {
|
|
12864
|
-
this._inc('play');
|
|
12865
|
-
}
|
|
12866
|
-
onPause() {
|
|
12867
|
-
this._stop('watch');
|
|
12868
|
-
this.start('pause');
|
|
12869
|
-
this._inc('pause');
|
|
12870
|
-
this.listenToOnce(this.container, Events.CONTAINER_PLAY, this.playAfterPause);
|
|
12871
|
-
this.stopListening(this.container, Events.CONTAINER_TIMEUPDATE, this.onContainerUpdateWhilePlaying);
|
|
12872
|
-
}
|
|
12873
|
-
onSeek(e) {
|
|
12874
|
-
this._inc('seek');
|
|
12875
|
-
this.metrics.extra.watchHistory.push([e * 1000, e * 1000]);
|
|
12876
|
-
}
|
|
12877
|
-
onTimeUpdate(e) {
|
|
12878
|
-
const current = e.current * 1000, total = e.total * 1000, l = this.metrics.extra.watchHistory.length;
|
|
12879
|
-
this.metrics.extra.duration = total;
|
|
12880
|
-
this.metrics.extra.currentTime = current;
|
|
12881
|
-
this.metrics.extra.watchedPercentage = (current / total) * 100;
|
|
12882
|
-
if (l === 0) {
|
|
12883
|
-
this.metrics.extra.watchHistory.push([current, current]);
|
|
12884
|
-
}
|
|
12885
|
-
else {
|
|
12886
|
-
this.metrics.extra.watchHistory[l - 1][1] = current;
|
|
12887
|
-
}
|
|
12888
|
-
if (this.metrics.extra.bitratesHistory.length > 0) {
|
|
12889
|
-
const lastBitrate = this.metrics.extra.bitratesHistory[this.metrics.extra.bitratesHistory.length - 1];
|
|
12890
|
-
if (!lastBitrate.end) {
|
|
12891
|
-
lastBitrate.time = this._now() - lastBitrate.start;
|
|
12892
|
-
}
|
|
12893
|
-
}
|
|
12894
|
-
this._onCompletion();
|
|
12895
|
-
}
|
|
12896
|
-
onContainerUpdateWhilePlaying() {
|
|
12897
|
-
if (this.container.playback.isPlaying()) {
|
|
12898
|
-
this._stop('watch');
|
|
12899
|
-
this.start('watch');
|
|
12900
|
-
}
|
|
12901
|
-
}
|
|
12902
|
-
onBuffering() {
|
|
12903
|
-
this._inc('buffering');
|
|
12904
|
-
this.start('buffering');
|
|
12905
|
-
this.listenToOnce(this.container, Events.CONTAINER_STATE_BUFFERFULL, this.onBufferfull);
|
|
12857
|
+
initSpeedTest(this.customMetrics)
|
|
12858
|
+
.then(() => {
|
|
12859
|
+
startSpeedtest();
|
|
12860
|
+
})
|
|
12861
|
+
.catch((e) => {
|
|
12862
|
+
this.disable();
|
|
12863
|
+
});
|
|
12906
12864
|
}
|
|
12907
|
-
|
|
12908
|
-
this.
|
|
12909
|
-
this.
|
|
12865
|
+
hide() {
|
|
12866
|
+
this.core.$el.find(this.statsBoxElem).hide();
|
|
12867
|
+
this.showing = false;
|
|
12868
|
+
stopSpeedtest();
|
|
12910
12869
|
}
|
|
12911
|
-
|
|
12912
|
-
this.
|
|
12870
|
+
onPlayerResize() {
|
|
12871
|
+
this.setStatsBoxSize();
|
|
12913
12872
|
}
|
|
12914
|
-
|
|
12915
|
-
this.metrics =
|
|
12916
|
-
|
|
12917
|
-
|
|
12918
|
-
const currentPercentage = this.metrics.extra.watchedPercentage;
|
|
12919
|
-
const allPercentages = this.completion.watch;
|
|
12920
|
-
const isCalled = this.completion.calls.indexOf(currentPercentage) !== -1;
|
|
12921
|
-
if (allPercentages.indexOf(currentPercentage) !== -1 && !isCalled) {
|
|
12922
|
-
Log.info(this.name + ' PERCENTAGE_EVENT: ' + currentPercentage);
|
|
12923
|
-
this.completion.calls.push(currentPercentage);
|
|
12924
|
-
this.trigger(ClapprStatsEvents.PERCENTAGE_EVENT, currentPercentage);
|
|
12925
|
-
}
|
|
12926
|
-
}
|
|
12927
|
-
_buildReport() {
|
|
12928
|
-
this._stop('session');
|
|
12929
|
-
this.start('session');
|
|
12930
|
-
this.metrics.extra.playbackName = this._playbackName;
|
|
12931
|
-
this.metrics.extra.playbackType = this._playbackType;
|
|
12932
|
-
this._calculateBitrates();
|
|
12933
|
-
this._calculatePercentages();
|
|
12934
|
-
this._fetchFPS();
|
|
12935
|
-
this._measureLatency();
|
|
12936
|
-
this._measureBandwidth();
|
|
12937
|
-
this._onReport(this.metrics);
|
|
12938
|
-
this.trigger(ClapprStatsEvents.REPORT_EVENT, structuredClone(this.metrics));
|
|
12939
|
-
}
|
|
12940
|
-
_fetchFPS() {
|
|
12941
|
-
// flashls ??? - hls.droppedFramesl hls.stream.bufferLength (seconds)
|
|
12942
|
-
// hls ??? (use the same?)
|
|
12943
|
-
const fetchFPS = {
|
|
12944
|
-
'html5_video': this._html5FetchFPS,
|
|
12945
|
-
'hls': this._html5FetchFPS,
|
|
12946
|
-
'dash_shaka_playback': this._html5FetchFPS
|
|
12873
|
+
addGeneralMetrics() {
|
|
12874
|
+
this.metrics.general = {
|
|
12875
|
+
displayResolution: this.playerWidth + 'x' + this.playerHeight,
|
|
12876
|
+
volume: this.container?.volume,
|
|
12947
12877
|
};
|
|
12948
|
-
if (this._playbackName in fetchFPS) {
|
|
12949
|
-
fetchFPS[this._playbackName].call(this);
|
|
12950
|
-
}
|
|
12951
12878
|
}
|
|
12952
|
-
|
|
12953
|
-
|
|
12954
|
-
|
|
12879
|
+
addCustomMetrics() {
|
|
12880
|
+
this.metrics.custom = this.customMetrics;
|
|
12881
|
+
const videoQualityNames = [
|
|
12882
|
+
'SD (480p)',
|
|
12883
|
+
'HD (720p)',
|
|
12884
|
+
'Full HD (1080p)',
|
|
12885
|
+
'2K (1440p)',
|
|
12886
|
+
'4K (2160p)',
|
|
12887
|
+
];
|
|
12888
|
+
const { connectionSpeed, ping } = this.customMetrics;
|
|
12889
|
+
if (!connectionSpeed || !ping) {
|
|
12890
|
+
const calculatingText = 'Calculating... Please wait.';
|
|
12891
|
+
this.metrics.custom.vodQuality = calculatingText;
|
|
12892
|
+
this.metrics.custom.liveQuality = calculatingText;
|
|
12955
12893
|
return;
|
|
12956
12894
|
}
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12960
|
-
|
|
12961
|
-
|
|
12895
|
+
const downloadQuality = getDownloadQuality(connectionSpeed);
|
|
12896
|
+
const pingQuality = getPingQuality(ping);
|
|
12897
|
+
const liveQuality = Math.min(downloadQuality, pingQuality);
|
|
12898
|
+
const prefix = 'Optimal for ';
|
|
12899
|
+
this.metrics.custom.vodQuality =
|
|
12900
|
+
prefix + videoQualityNames[downloadQuality - 1];
|
|
12901
|
+
this.metrics.custom.liveQuality =
|
|
12902
|
+
prefix + videoQualityNames[liveQuality - 1];
|
|
12903
|
+
}
|
|
12904
|
+
updateMetrics(metrics) {
|
|
12905
|
+
Object.assign(this.metrics, metrics);
|
|
12906
|
+
this.addGeneralMetrics();
|
|
12907
|
+
this.addCustomMetrics();
|
|
12908
|
+
const scrollTop = this.core.$el.find(this.statsBoxElem).scrollTop();
|
|
12909
|
+
this.$el.html(NerdStats.template({
|
|
12910
|
+
metrics: Formatter.format(this.metrics),
|
|
12911
|
+
iconPosition: this.iconPosition,
|
|
12912
|
+
}));
|
|
12913
|
+
this.setStatsBoxSize();
|
|
12914
|
+
drawSpeedTestResults();
|
|
12915
|
+
drawSummary(this.metrics?.custom, this.$el.find('.speedtest-quality-content[data-streaming-type="vod"]'), this.$el.find('.speedtest-quality-content[data-streaming-type="live"]'));
|
|
12916
|
+
this.core.$el.find(this.statsBoxElem).scrollTop(scrollTop);
|
|
12917
|
+
if (!this.showing) {
|
|
12918
|
+
this.hide();
|
|
12962
12919
|
}
|
|
12963
|
-
this.metrics.extra.bitrateWeightedMean = weightedTotal / totalTime;
|
|
12964
|
-
this.metrics.extra.bitrateMostUsed = bitratesHistory.reduce((mostUsed, current) => (current.time || 0) > (mostUsed.time || 0) ? current : mostUsed, { time: 0, bitrate: 0, start: 0, end: 0 }).bitrate;
|
|
12965
12920
|
}
|
|
12966
|
-
|
|
12967
|
-
if (this.
|
|
12968
|
-
this.
|
|
12921
|
+
setStatsBoxSize() {
|
|
12922
|
+
if (this.playerWidth >= this.statsBoxWidthThreshold) {
|
|
12923
|
+
this.$el.find(this.statsBoxElem).addClass('wide');
|
|
12924
|
+
this.$el.find(this.statsBoxElem).removeClass('narrow');
|
|
12925
|
+
}
|
|
12926
|
+
else {
|
|
12927
|
+
this.$el.find(this.statsBoxElem).removeClass('wide');
|
|
12928
|
+
this.$el.find(this.statsBoxElem).addClass('narrow');
|
|
12969
12929
|
}
|
|
12970
12930
|
}
|
|
12971
|
-
|
|
12972
|
-
|
|
12973
|
-
|
|
12974
|
-
|
|
12975
|
-
|
|
12976
|
-
|
|
12977
|
-
this.
|
|
12978
|
-
this
|
|
12979
|
-
this.metrics.counters.fps = decodedFramesLastTime / (this.runEach / 1000);
|
|
12980
|
-
this.lastDecodedFramesCount = decodedFrames;
|
|
12931
|
+
/**
|
|
12932
|
+
* @internal
|
|
12933
|
+
*/
|
|
12934
|
+
render() {
|
|
12935
|
+
// TODO append to the container
|
|
12936
|
+
this.core.$el.append(this.$el[0]);
|
|
12937
|
+
this.hide();
|
|
12938
|
+
return this;
|
|
12981
12939
|
}
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
|
|
12995
|
-
|
|
12996
|
-
|
|
12997
|
-
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
this.metrics.timers.latency = rtt;
|
|
13003
|
-
};
|
|
13004
|
-
ld();
|
|
13005
|
-
}
|
|
13006
|
-
}
|
|
13007
|
-
// originally from https://www.smashingmagazine.com/2011/11/analyzing-network-characteristics-using-javascript-and-the-dom-part-1/
|
|
13008
|
-
_measureBandwidth() {
|
|
13009
|
-
if (this.urisToMeasureBandwidth && (this.bwMeasureCount % this.runBandwidthTestEvery === 0)) {
|
|
13010
|
-
let i = 0;
|
|
13011
|
-
const ld = (e) => {
|
|
13012
|
-
if (i > 0) {
|
|
13013
|
-
const prev = this.urisToMeasureBandwidth[i - 1];
|
|
13014
|
-
prev.end = this._now();
|
|
13015
|
-
if (prev.timer !== null) {
|
|
13016
|
-
clearTimeout(prev.timer);
|
|
13017
|
-
}
|
|
13018
|
-
}
|
|
13019
|
-
if (i >= this.urisToMeasureBandwidth.length || (i > 0 && this.urisToMeasureBandwidth[i - 1].expired)) {
|
|
13020
|
-
assert(e, 'incorrect invocation in _measureBandwidth');
|
|
13021
|
-
done(e);
|
|
13022
|
-
}
|
|
13023
|
-
else {
|
|
13024
|
-
const xhr = new XMLHttpRequest();
|
|
13025
|
-
xhr.open('GET', this.urisToMeasureBandwidth[i].url, true);
|
|
13026
|
-
xhr.responseType = 'arraybuffer';
|
|
13027
|
-
xhr.onload = xhr.onabort = ld;
|
|
13028
|
-
this.urisToMeasureBandwidth[i].start = this._now();
|
|
13029
|
-
this.urisToMeasureBandwidth[i].timer = setTimeout((j) => {
|
|
13030
|
-
this.urisToMeasureBandwidth[j].expired = true;
|
|
13031
|
-
xhr.abort();
|
|
13032
|
-
}, this.urisToMeasureBandwidth[i].timeout, i);
|
|
13033
|
-
xhr.send();
|
|
13034
|
-
}
|
|
13035
|
-
i++;
|
|
13036
|
-
};
|
|
13037
|
-
const done = (e) => {
|
|
13038
|
-
const timeSpent = (this.urisToMeasureBandwidth[i - 1].end - this.urisToMeasureBandwidth[i - 1].start) / 1000;
|
|
13039
|
-
const bandwidthBps = (e.loaded * 8) / timeSpent;
|
|
13040
|
-
this.metrics.extra.bandwidth = bandwidthBps;
|
|
13041
|
-
this.urisToMeasureBandwidth.forEach((x) => {
|
|
13042
|
-
x.start = 0;
|
|
13043
|
-
x.end = 0;
|
|
13044
|
-
x.expired = false;
|
|
13045
|
-
if (x.timer !== null) {
|
|
13046
|
-
clearTimeout(x.timer);
|
|
13047
|
-
x.timer = null;
|
|
13048
|
-
}
|
|
13049
|
-
});
|
|
13050
|
-
};
|
|
13051
|
-
ld();
|
|
12940
|
+
addToBottomGear() {
|
|
12941
|
+
const gear = this.core.getPlugin('bottom_gear');
|
|
12942
|
+
gear
|
|
12943
|
+
.addItem('nerd_stats')
|
|
12944
|
+
.html(NerdStats.buttonTemplate({
|
|
12945
|
+
icon: statsIcon,
|
|
12946
|
+
i18n: this.core.i18n,
|
|
12947
|
+
}))
|
|
12948
|
+
.on('click', (e) => {
|
|
12949
|
+
e.stopPropagation();
|
|
12950
|
+
this.toggle();
|
|
12951
|
+
});
|
|
12952
|
+
}
|
|
12953
|
+
clearCustomMetrics() {
|
|
12954
|
+
const clapprStats = this.container?.getPlugin('clappr_stats');
|
|
12955
|
+
this.customMetrics.connectionSpeed = 0;
|
|
12956
|
+
this.customMetrics.ping = 0;
|
|
12957
|
+
this.customMetrics.jitter = 0;
|
|
12958
|
+
if (clapprStats) {
|
|
12959
|
+
this.updateMetrics(clapprStats.exportMetrics());
|
|
13052
12960
|
}
|
|
13053
|
-
this.bwMeasureCount++;
|
|
13054
12961
|
}
|
|
12962
|
+
refreshSpeedTest() {
|
|
12963
|
+
stopSpeedtest();
|
|
12964
|
+
setTimeout(() => {
|
|
12965
|
+
this.clearCustomMetrics();
|
|
12966
|
+
clearSpeedTestResults();
|
|
12967
|
+
drawSpeedTestResults();
|
|
12968
|
+
}, 200);
|
|
12969
|
+
setTimeout(() => {
|
|
12970
|
+
startSpeedtest();
|
|
12971
|
+
}, 800);
|
|
12972
|
+
}
|
|
12973
|
+
}
|
|
12974
|
+
function newMetrics() {
|
|
12975
|
+
return {
|
|
12976
|
+
...newMetrics$1(),
|
|
12977
|
+
general: {},
|
|
12978
|
+
custom: {
|
|
12979
|
+
connectionSpeed: 0,
|
|
12980
|
+
ping: 0,
|
|
12981
|
+
jitter: 0,
|
|
12982
|
+
},
|
|
12983
|
+
};
|
|
13055
12984
|
}
|
|
13056
|
-
// ClapprStats.REPORT_EVENT = 'clappr:stats:report';
|
|
13057
|
-
// ClapprStats.PERCENTAGE_EVENT = 'clappr:stats:percentage';
|
|
13058
12985
|
|
|
13059
12986
|
// This work is based on the original work of the following authors:
|
|
13060
12987
|
// Copyright 2014 Globo.com Player authors. All rights reserved.
|
|
@@ -13077,7 +13004,7 @@ class ClickToPause extends ContainerPlugin {
|
|
|
13077
13004
|
* @internal
|
|
13078
13005
|
*/
|
|
13079
13006
|
get supportedVersion() {
|
|
13080
|
-
return { min: CLAPPR_VERSION };
|
|
13007
|
+
return { min: CLAPPR_VERSION$1 };
|
|
13081
13008
|
}
|
|
13082
13009
|
/**
|
|
13083
13010
|
* @internal
|
|
@@ -13127,7 +13054,15 @@ class ClickToPause extends ContainerPlugin {
|
|
|
13127
13054
|
}
|
|
13128
13055
|
}
|
|
13129
13056
|
|
|
13130
|
-
|
|
13057
|
+
/**
|
|
13058
|
+
* Parse a time string in the format "hh:mm:ss" or "mm:ss" or "ss" to seconds.
|
|
13059
|
+
* @param str - The time string to parse.
|
|
13060
|
+
* @returns The time in seconds.
|
|
13061
|
+
* @example "01:01:00" -> 3660
|
|
13062
|
+
* @example "01:00" -> 60
|
|
13063
|
+
* @example "33" -> 33
|
|
13064
|
+
*/
|
|
13065
|
+
function parseClipTime(str) {
|
|
13131
13066
|
if (!str) {
|
|
13132
13067
|
return 0;
|
|
13133
13068
|
}
|
|
@@ -13136,21 +13071,12 @@ function strtimeToMiliseconds(str) {
|
|
|
13136
13071
|
if (arr.length >= 3) {
|
|
13137
13072
|
h = parseInt(arr[arr.length - 3]) * 60 * 60;
|
|
13138
13073
|
}
|
|
13139
|
-
else {
|
|
13140
|
-
h = 0;
|
|
13141
|
-
}
|
|
13142
13074
|
if (arr.length >= 2) {
|
|
13143
13075
|
m = parseInt(arr[arr.length - 2]) * 60;
|
|
13144
13076
|
}
|
|
13145
|
-
else {
|
|
13146
|
-
m = 0;
|
|
13147
|
-
}
|
|
13148
13077
|
if (arr.length >= 1) {
|
|
13149
13078
|
s = parseInt(arr[arr.length - 1]);
|
|
13150
13079
|
}
|
|
13151
|
-
else {
|
|
13152
|
-
s = 0;
|
|
13153
|
-
}
|
|
13154
13080
|
return (h + m + s);
|
|
13155
13081
|
}
|
|
13156
13082
|
function getPageX(event) {
|
|
@@ -13163,22 +13089,64 @@ function getPageX(event) {
|
|
|
13163
13089
|
return 0;
|
|
13164
13090
|
}
|
|
13165
13091
|
|
|
13092
|
+
function parseClips(text) {
|
|
13093
|
+
const clipsArr = text
|
|
13094
|
+
.split('\n')
|
|
13095
|
+
.map((val) => {
|
|
13096
|
+
const matchRes = val.match(/(((\d+:)?\d+:)?\d+) (.+)/i);
|
|
13097
|
+
return matchRes
|
|
13098
|
+
? {
|
|
13099
|
+
start: parseClipTime(matchRes[1]),
|
|
13100
|
+
text: matchRes[4],
|
|
13101
|
+
}
|
|
13102
|
+
: null;
|
|
13103
|
+
})
|
|
13104
|
+
.filter((clip) => clip !== null)
|
|
13105
|
+
.sort((a, b) => a.start - b.start);
|
|
13106
|
+
return clipsArr.map((clip, index) => ({
|
|
13107
|
+
start: clip.start,
|
|
13108
|
+
text: clip.text,
|
|
13109
|
+
end: index < clipsArr.length - 1 ? clipsArr[index + 1].start : 0,
|
|
13110
|
+
}));
|
|
13111
|
+
}
|
|
13112
|
+
function buildSvg(clips, duration, barWidth) {
|
|
13113
|
+
let svg = '<svg width="0" height="0">\n' + '<defs>\n' + '<clipPath id="myClip">\n';
|
|
13114
|
+
let rightEdge = 0;
|
|
13115
|
+
clips.forEach((val) => {
|
|
13116
|
+
const end = val.end || duration;
|
|
13117
|
+
const chunkWidth = Math.round(((end - val.start) * barWidth) / duration);
|
|
13118
|
+
svg += `<rect x="${rightEdge}" y="0" width="${chunkWidth - 2}" height="30"/>\n`;
|
|
13119
|
+
rightEdge += chunkWidth;
|
|
13120
|
+
});
|
|
13121
|
+
if (rightEdge < barWidth) {
|
|
13122
|
+
svg += `<rect x="${rightEdge}" y="0" width="${barWidth - rightEdge}" height="30"/>\n`;
|
|
13123
|
+
}
|
|
13124
|
+
svg += '</clipPath>' + '</defs>' + '</svg>';
|
|
13125
|
+
return svg;
|
|
13126
|
+
}
|
|
13127
|
+
|
|
13128
|
+
const clipsHTML = "<div class=\"media-clip-text\" id=\"clips-text\"></div>";
|
|
13129
|
+
|
|
13130
|
+
const VERSION$5 = '2.22.16';
|
|
13131
|
+
const CLAPPR_VERSION = '0.11.4';
|
|
13166
13132
|
/**
|
|
13167
|
-
* `PLUGIN` that
|
|
13133
|
+
* `PLUGIN` that allows marking up the timeline of the video
|
|
13168
13134
|
* @beta
|
|
13169
13135
|
* @remarks
|
|
13136
|
+
* The plugin decorates the seekbar with notches to indicate the clips of the video and displays current clip text in the left panel
|
|
13137
|
+
*
|
|
13170
13138
|
* Depends on:
|
|
13171
13139
|
*
|
|
13172
13140
|
* - {@link MediaControl}
|
|
13173
13141
|
*
|
|
13174
13142
|
* Configuration options - {@link ClipsPluginSettings}
|
|
13175
13143
|
*/
|
|
13176
|
-
class
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
_oldContainer;
|
|
13144
|
+
class Clips extends UICorePlugin {
|
|
13145
|
+
barStyle = null;
|
|
13146
|
+
clips = [];
|
|
13147
|
+
oldContainer;
|
|
13181
13148
|
svgMask = null;
|
|
13149
|
+
static template = tmpl(clipsHTML);
|
|
13182
13150
|
/**
|
|
13183
13151
|
* @internal
|
|
13184
13152
|
*/
|
|
@@ -13190,130 +13158,117 @@ class ClipsPlugin extends UICorePlugin {
|
|
|
13190
13158
|
*/
|
|
13191
13159
|
get attributes() {
|
|
13192
13160
|
return {
|
|
13193
|
-
class:
|
|
13161
|
+
class: 'media-control-clips',
|
|
13194
13162
|
};
|
|
13195
13163
|
}
|
|
13164
|
+
get version() {
|
|
13165
|
+
return VERSION$5;
|
|
13166
|
+
}
|
|
13167
|
+
get supportedVersion() {
|
|
13168
|
+
return { min: CLAPPR_VERSION };
|
|
13169
|
+
}
|
|
13196
13170
|
/**
|
|
13197
13171
|
* @internal
|
|
13198
13172
|
*/
|
|
13199
13173
|
bindEvents() {
|
|
13200
|
-
|
|
13201
|
-
assert(mediaControl, 'media_control plugin is required');
|
|
13202
|
-
this.listenToOnce(this.core, Events.CORE_READY, this._onCoreReady);
|
|
13203
|
-
// TODO listen to CORE_ACTIVE_CONTAINER_CHANGED
|
|
13204
|
-
this.listenTo(mediaControl, Events.MEDIACONTROL_CONTAINERCHANGED, this._onMediaControlContainerChanged);
|
|
13174
|
+
this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady);
|
|
13205
13175
|
this.listenTo(this.core, Events.CORE_RESIZE, this.playerResize);
|
|
13176
|
+
this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onContainerChanged);
|
|
13206
13177
|
}
|
|
13207
|
-
|
|
13178
|
+
render() {
|
|
13208
13179
|
if (!this.options.clips) {
|
|
13209
|
-
this
|
|
13210
|
-
return;
|
|
13180
|
+
return this;
|
|
13211
13181
|
}
|
|
13212
|
-
this.
|
|
13213
|
-
|
|
13214
|
-
|
|
13215
|
-
this._bindContainerEvents();
|
|
13182
|
+
this.$el.html(Clips.template());
|
|
13183
|
+
this.$el.hide();
|
|
13184
|
+
return this;
|
|
13216
13185
|
}
|
|
13217
|
-
|
|
13218
|
-
this.
|
|
13219
|
-
|
|
13220
|
-
this.
|
|
13186
|
+
destroy() {
|
|
13187
|
+
if (this.barStyle) {
|
|
13188
|
+
this.barStyle.remove();
|
|
13189
|
+
this.barStyle = null;
|
|
13221
13190
|
}
|
|
13191
|
+
return super.destroy();
|
|
13222
13192
|
}
|
|
13223
|
-
|
|
13224
|
-
if (this.
|
|
13225
|
-
this.
|
|
13193
|
+
disable() {
|
|
13194
|
+
if (this.barStyle) {
|
|
13195
|
+
this.barStyle.remove();
|
|
13196
|
+
this.barStyle = null;
|
|
13226
13197
|
}
|
|
13198
|
+
return super.disable();
|
|
13199
|
+
}
|
|
13200
|
+
enable() {
|
|
13201
|
+
this.render();
|
|
13202
|
+
return super.enable();
|
|
13203
|
+
}
|
|
13204
|
+
onCoreReady() {
|
|
13205
|
+
const mediaControl = this.core.getPlugin('media_control');
|
|
13206
|
+
assert(mediaControl, 'media_control plugin is required');
|
|
13207
|
+
this.parseClips(this.options.clips.text);
|
|
13208
|
+
this.listenTo(mediaControl, Events.MEDIACONTROL_RENDERED, this.onMcRender);
|
|
13209
|
+
}
|
|
13210
|
+
onMcRender() {
|
|
13227
13211
|
const mediaControl = this.core.getPlugin('media_control');
|
|
13228
|
-
|
|
13229
|
-
|
|
13230
|
-
|
|
13212
|
+
mediaControl.mount('clips', this.$el);
|
|
13213
|
+
}
|
|
13214
|
+
onContainerChanged() {
|
|
13215
|
+
// TODO figure out the conditions of changing the container (without destroying the previous one)
|
|
13216
|
+
if (this.oldContainer) {
|
|
13217
|
+
this.stopListening(this.oldContainer, Events.CONTAINER_TIMEUPDATE, this.onTimeUpdate);
|
|
13218
|
+
}
|
|
13219
|
+
this.oldContainer = this.core.activeContainer;
|
|
13220
|
+
if (this.svgMask) {
|
|
13221
|
+
this.svgMask.remove();
|
|
13222
|
+
this.svgMask = null;
|
|
13223
|
+
}
|
|
13224
|
+
this.listenTo(this.core.activeContainer, Events.CONTAINER_TIMEUPDATE, this.onTimeUpdate);
|
|
13225
|
+
}
|
|
13226
|
+
playerResize() {
|
|
13227
|
+
const duration = this.core.activeContainer.getDuration();
|
|
13228
|
+
if (duration) {
|
|
13229
|
+
this.makeSvg(duration);
|
|
13230
|
+
}
|
|
13231
13231
|
}
|
|
13232
13232
|
onTimeUpdate(event) {
|
|
13233
|
-
if (!this.
|
|
13234
|
-
this.duration = event.total;
|
|
13233
|
+
if (!this.svgMask) {
|
|
13235
13234
|
this.makeSvg(event.total);
|
|
13236
|
-
this.durationGetting = true;
|
|
13237
13235
|
}
|
|
13238
|
-
for (const value of this.clips
|
|
13239
|
-
if (event.current >= value.start &&
|
|
13236
|
+
for (const value of this.clips) {
|
|
13237
|
+
if ((event.current >= value.start && !value.end) ||
|
|
13238
|
+
event.current < value.end) {
|
|
13240
13239
|
this.setClipText(value.text);
|
|
13241
13240
|
break;
|
|
13242
13241
|
}
|
|
13243
13242
|
}
|
|
13244
13243
|
}
|
|
13245
|
-
parseClips() {
|
|
13246
|
-
|
|
13247
|
-
const clipsArr = textArr
|
|
13248
|
-
.map((val) => {
|
|
13249
|
-
const matchRes = val.match(/(\d+:\d+|:\d+) (.+)/i);
|
|
13250
|
-
return matchRes
|
|
13251
|
-
? {
|
|
13252
|
-
start: strtimeToMiliseconds(matchRes[1]),
|
|
13253
|
-
text: matchRes[2],
|
|
13254
|
-
}
|
|
13255
|
-
: null;
|
|
13256
|
-
})
|
|
13257
|
-
.filter((clip) => clip !== null);
|
|
13258
|
-
clipsArr.sort((a, b) => a.start - b.start);
|
|
13259
|
-
clipsArr.forEach((clip, index) => {
|
|
13260
|
-
this.clips.set(clip.start, {
|
|
13261
|
-
index,
|
|
13262
|
-
start: clip.start,
|
|
13263
|
-
text: clip.text,
|
|
13264
|
-
end: clipsArr[index + 1] ? clipsArr[index + 1].start : null,
|
|
13265
|
-
});
|
|
13266
|
-
});
|
|
13267
|
-
}
|
|
13268
|
-
/**
|
|
13269
|
-
* Returns the text of the current clip.
|
|
13270
|
-
* @param time - The current time of the player.
|
|
13271
|
-
* @returns The text of the current clip.
|
|
13272
|
-
*/
|
|
13273
|
-
getText(time) {
|
|
13274
|
-
for (const [key, value] of this.clips.entries()) {
|
|
13275
|
-
if (time >= value.start && time < value.end) {
|
|
13276
|
-
return value.text;
|
|
13277
|
-
}
|
|
13278
|
-
}
|
|
13279
|
-
return '';
|
|
13244
|
+
parseClips(text) {
|
|
13245
|
+
this.clips = parseClips(text);
|
|
13280
13246
|
}
|
|
13281
13247
|
makeSvg(duration) {
|
|
13282
|
-
|
|
13283
|
-
const widthOfSeek = this.core.activeContainer.$el.width();
|
|
13284
|
-
let finishValue = 0;
|
|
13285
|
-
this.clips.forEach((val) => {
|
|
13286
|
-
let end = val.end;
|
|
13287
|
-
if (!end) {
|
|
13288
|
-
end = val.end = duration;
|
|
13289
|
-
}
|
|
13290
|
-
const widthChunk = ((end - val.start) * widthOfSeek) / duration;
|
|
13291
|
-
svg += `<rect x="${finishValue}" y="0" width="${widthChunk - 2}" height="30"/>\n`;
|
|
13292
|
-
finishValue += widthChunk;
|
|
13293
|
-
});
|
|
13294
|
-
svg += `<rect x="${finishValue}" y="0" width="${widthOfSeek - finishValue}" height="30"/>\n`;
|
|
13295
|
-
svg += '</clipPath>' + '</defs>' + '</svg>';
|
|
13248
|
+
const svg = buildSvg(this.clips, duration, this.core.activeContainer.$el.width());
|
|
13296
13249
|
this.setSVGMask(svg);
|
|
13297
13250
|
}
|
|
13298
13251
|
setSVGMask(svg) {
|
|
13299
|
-
// this.core.mediaControl.setSVGMask(svg);
|
|
13300
13252
|
if (this.svgMask) {
|
|
13301
13253
|
this.svgMask.remove();
|
|
13302
13254
|
}
|
|
13303
|
-
const mediaControl = this.core.getPlugin('media_control');
|
|
13304
|
-
const $seekBarContainer = mediaControl.getElement('seekBarContainer');
|
|
13305
|
-
if ($seekBarContainer?.get(0)) {
|
|
13306
|
-
$seekBarContainer.addClass('clips');
|
|
13307
|
-
}
|
|
13308
13255
|
this.svgMask = $(svg);
|
|
13309
|
-
|
|
13256
|
+
this.$el.append(this.svgMask);
|
|
13257
|
+
if (!this.barStyle) {
|
|
13258
|
+
this.barStyle = document.createElement('style');
|
|
13259
|
+
this.barStyle.textContent = `
|
|
13260
|
+
.bar-container[data-seekbar] {
|
|
13261
|
+
clip-path: url("#myClip");
|
|
13262
|
+
}`;
|
|
13263
|
+
this.$el.append(this.barStyle);
|
|
13264
|
+
}
|
|
13310
13265
|
}
|
|
13311
13266
|
setClipText(text) {
|
|
13312
|
-
|
|
13313
|
-
|
|
13314
|
-
|
|
13315
|
-
|
|
13316
|
-
|
|
13267
|
+
if (text) {
|
|
13268
|
+
this.$el.show().find('#clips-text').text(text);
|
|
13269
|
+
}
|
|
13270
|
+
else {
|
|
13271
|
+
this.$el.hide();
|
|
13317
13272
|
}
|
|
13318
13273
|
}
|
|
13319
13274
|
}
|
|
@@ -13340,7 +13295,7 @@ class ContextMenu extends UIContainerPlugin {
|
|
|
13340
13295
|
* @internal
|
|
13341
13296
|
*/
|
|
13342
13297
|
get supportedVersion() {
|
|
13343
|
-
return { min: CLAPPR_VERSION };
|
|
13298
|
+
return { min: CLAPPR_VERSION$1 };
|
|
13344
13299
|
}
|
|
13345
13300
|
/**
|
|
13346
13301
|
* @internal
|
|
@@ -13461,7 +13416,7 @@ class DvrControls extends UICorePlugin {
|
|
|
13461
13416
|
* @internal
|
|
13462
13417
|
*/
|
|
13463
13418
|
get supportedVersion() {
|
|
13464
|
-
return { min: CLAPPR_VERSION };
|
|
13419
|
+
return { min: CLAPPR_VERSION$1 };
|
|
13465
13420
|
}
|
|
13466
13421
|
/**
|
|
13467
13422
|
* @internal
|
|
@@ -13567,7 +13522,7 @@ class ErrorScreen extends UICorePlugin {
|
|
|
13567
13522
|
* @internal
|
|
13568
13523
|
*/
|
|
13569
13524
|
get supportedVersion() {
|
|
13570
|
-
return { min: CLAPPR_VERSION };
|
|
13525
|
+
return { min: CLAPPR_VERSION$1 };
|
|
13571
13526
|
}
|
|
13572
13527
|
static template = tmpl(templateHtml);
|
|
13573
13528
|
/**
|
|
@@ -13688,7 +13643,7 @@ class Favicon extends CorePlugin {
|
|
|
13688
13643
|
* @internal
|
|
13689
13644
|
*/
|
|
13690
13645
|
get supportedVersion() {
|
|
13691
|
-
return { min: CLAPPR_VERSION };
|
|
13646
|
+
return { min: CLAPPR_VERSION$1 };
|
|
13692
13647
|
}
|
|
13693
13648
|
/**
|
|
13694
13649
|
* @internal
|
|
@@ -13780,7 +13735,7 @@ class GoogleAnalytics extends ContainerPlugin {
|
|
|
13780
13735
|
return 'google_analytics';
|
|
13781
13736
|
}
|
|
13782
13737
|
get supportedVersion() {
|
|
13783
|
-
return { min: CLAPPR_VERSION };
|
|
13738
|
+
return { min: CLAPPR_VERSION$1 };
|
|
13784
13739
|
}
|
|
13785
13740
|
constructor(container) {
|
|
13786
13741
|
super(container);
|
|
@@ -13927,7 +13882,7 @@ class Logo extends UIContainerPlugin {
|
|
|
13927
13882
|
return 'logo';
|
|
13928
13883
|
}
|
|
13929
13884
|
get supportedVersion() {
|
|
13930
|
-
return { min: CLAPPR_VERSION };
|
|
13885
|
+
return { min: CLAPPR_VERSION$1 };
|
|
13931
13886
|
}
|
|
13932
13887
|
get template() {
|
|
13933
13888
|
return tmpl(logoHTML);
|
|
@@ -14316,7 +14271,7 @@ const FullscreenIOS = {
|
|
|
14316
14271
|
},
|
|
14317
14272
|
};
|
|
14318
14273
|
|
|
14319
|
-
const mediaControlHTML = "<div class=\"media-control-background\" data-background></div>\n\n<div class=\"media-control-layer gcore-skin-bg-color\" data-controls>\n <% var renderBar = function(name) { %>\n <div class=\"bar-container\" data-<%= name %>>\n <div class=\"bar-background\" data-<%= name %>>\n <div class=\"bar-fill-1\" data-<%= name %>></div>\n <div class=\"bar-fill-2 gcore-skin-main-color\" data-<%= name %>></div>\n <div class=\"bar-hover\" data-<%= name %>></div>\n </div>\n </div>\n <div class=\"bar-scrubber\" data-<%= name %>>\n <div class=\"bar-scrubber-icon gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n <% }; %>\n <% var renderSegmentedBar = function(name, segments) {\n segments = segments || 10; %>\n <div class=\"bar-container\" data-<%= name %>>\n <div class=\"bar-background\" data-<%= name %>>\n <div class=\"bar-fill-1 gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n <div class=\"bar-scrubber\" data-<%= name %>>\n <div class=\"bar-scrubber-icon gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n </div>\n <% }; %>\n <% var renderDrawer = function(name, renderContent) { %>\n <div class=\"drawer-container\" data-<%= name %>>\n <div class=\"drawer-icon-container\" data-<%= name %>>\n <div class=\"drawer-icon media-control-icon gcore-skin-button-color\" data-<%= name %>></div>\n <span class=\"drawer-text\" data-<%= name %>></span>\n </div>\n <% renderContent(name); %>\n </div>\n <% }; %>\n <% var renderIndicator = function(name) { %>\n <div class=\"media-control-indicator gcore-skin-text-color\" data-<%= name %>></div>\n <% }; %>\n <% var renderQuality = function(name) { %>\n <div class=\"media-control-quality\" data-<%= name %>></div>\n <% }; %>\n <% var renderNerd = function(name) { %>\n <div class=\"media-control-nerd\" data-<%= name %>></div>\n <% }; %>\n <% var renderMultiCamera = function(name) { %>\n <div class=\"media-control-multicamera\" data-<%= name %>></div>\n <% }; %>\n <% var
|
|
14274
|
+
const mediaControlHTML = "<div class=\"media-control-background\" data-background></div>\n\n<div class=\"media-control-layer gcore-skin-bg-color\" data-controls>\n <% var renderBar = function(name) { %>\n <div class=\"bar-container\" data-<%= name %>>\n <div class=\"bar-background\" data-<%= name %>>\n <div class=\"bar-fill-1\" data-<%= name %>></div>\n <div class=\"bar-fill-2 gcore-skin-main-color\" data-<%= name %>></div>\n <div class=\"bar-hover\" data-<%= name %>></div>\n </div>\n </div>\n <div class=\"bar-scrubber\" data-<%= name %>>\n <div class=\"bar-scrubber-icon gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n <% }; %>\n <% var renderSegmentedBar = function(name, segments) {\n segments = segments || 10; %>\n <div class=\"bar-container\" data-<%= name %>>\n <div class=\"bar-background\" data-<%= name %>>\n <div class=\"bar-fill-1 gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n <div class=\"bar-scrubber\" data-<%= name %>>\n <div class=\"bar-scrubber-icon gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n </div>\n <% }; %>\n <% var renderDrawer = function(name, renderContent) { %>\n <div class=\"drawer-container\" data-<%= name %>>\n <div class=\"drawer-icon-container\" data-<%= name %>>\n <div class=\"drawer-icon media-control-icon gcore-skin-button-color\" data-<%= name %>></div>\n <span class=\"drawer-text\" data-<%= name %>></span>\n </div>\n <% renderContent(name); %>\n </div>\n <% }; %>\n <% var renderIndicator = function(name) { %>\n <div class=\"media-control-indicator gcore-skin-text-color\" data-<%= name %>></div>\n <% }; %>\n <% var renderQuality = function(name) { %>\n <div class=\"media-control-quality\" data-<%= name %>></div>\n <% }; %>\n <% var renderNerd = function(name) { %>\n <div class=\"media-control-nerd\" data-<%= name %>></div>\n <% }; %>\n <% var renderMultiCamera = function(name) { %>\n <div class=\"media-control-multicamera\" data-<%= name %>></div>\n <% }; %>\n <% var renderVR = function(name) { %>\n <div class=\"media-control-vr\" data-<%= name %>></div>\n <% }; %>\n <% var renderButton = function(name) { %>\n <button type=\"button\" class=\"media-control-button media-control-icon gcore-skin-button-color\" data-<%= name %>\n aria-label=\"<%= name %>\"></button>\n <% }; %>\n\n <% var templates = {\n bar: renderBar,\n segmentedBar: renderSegmentedBar,\n };\n var render = function (settingsList) {\n settingsList.forEach(function (setting) {\n\n if (setting === \"seekbar\") {\n renderBar(setting);\n } else if (setting === \"volume\") {\n renderDrawer(setting, settings.volumeBarTemplate ? templates[settings.volumeBarTemplate] : function (name) {\n return renderSegmentedBar(name);\n });\n } else if (setting === \"duration\" || setting === \"position\" || setting === \"clips\") {\n renderIndicator(setting);\n } else if (setting === \"quality\") {\n renderQuality(setting)\n } else if (setting === \"nerd\") {\n renderNerd(setting)\n } else if (setting === \"multicamera\") {\n renderMultiCamera(setting)\n } else if (setting === \"vr\") {\n renderVR(setting)\n } else if ([\"playpause\", \"playstop\", \"fullscreen\"].includes(setting)) {\n renderButton(setting);\n }\n });\n }; %>\n <% if (settings.left && settings.left.length) { %>\n <div class=\"media-control-left-panel\" data-media-control>\n <% render(settings.left); %>\n </div>\n <% } %>\n <% if (settings.default && settings.default.length) { %>\n <div class=\"media-control-center-panel\" data-media-control>\n <% render(settings.default); %>\n </div>\n <% } %>\n <% if (settings.right && settings.right.length) { %>\n <div class=\"media-control-right-panel\" data-media-control>\n <% render(settings.right); %>\n </div>\n <% } %>\n</div>\n";
|
|
14320
14275
|
|
|
14321
14276
|
const volumeMaxIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.187 7.71405C13.759 8.06405 13.697 8.69307 14.046 9.12107C14.662 9.87207 15 10.8941 15 11.9961C15 13.0991 14.662 14.1201 14.046 14.8711C13.697 15.2991 13.759 15.9291 14.187 16.2781C14.373 16.4311 14.597 16.5051 14.82 16.5051C15.109 16.5051 15.396 16.3801 15.594 16.1391C16.501 15.0301 17 13.5601 17 11.9961C17 10.4331 16.501 8.96207 15.594 7.85407C15.245 7.42707 14.614 7.36405 14.187 7.71405ZM19.772 5.14408C19.443 4.70008 18.816 4.60907 18.374 4.94007C17.931 5.27007 17.839 5.89605 18.169 6.33905C19.367 7.94705 20 9.90307 20 11.9961C20 14.0891 19.367 16.0451 18.169 17.6531C17.839 18.0971 17.931 18.7231 18.374 19.0531C18.553 19.1871 18.762 19.2511 18.97 19.2511C19.275 19.2511 19.576 19.1121 19.772 18.8491C21.23 16.8921 22 14.5231 22 11.9961C22 9.47007 21.23 7.10108 19.772 5.14408ZM12 3.85108V20.1421C12 20.4881 11.793 20.7971 11.473 20.9291C11.368 20.9721 11.258 20.9921 11.149 20.9921C10.926 20.9921 10.708 20.9031 10.544 20.7371L6.317 16.4431C6.038 16.1591 5.648 15.9961 5.249 15.9961H3.5C2.673 15.9961 2 15.3231 2 14.4961V9.49607C2 8.66907 2.673 7.99607 3.5 7.99607H5.249C5.648 7.99607 6.038 7.83308 6.317 7.54908L10.544 3.25507C10.787 3.00807 11.151 2.93206 11.473 3.06406C11.793 3.19506 12 3.50408 12 3.85108Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
|
|
14322
14277
|
|
|
@@ -14406,8 +14361,6 @@ class MediaControl extends UICorePlugin {
|
|
|
14406
14361
|
userDisabled = false;
|
|
14407
14362
|
userKeepVisible = false;
|
|
14408
14363
|
verticalVolume = false;
|
|
14409
|
-
$clipText = null;
|
|
14410
|
-
$clipTextContainer = null;
|
|
14411
14364
|
$duration = null;
|
|
14412
14365
|
$fullscreenToggle = null;
|
|
14413
14366
|
$multiCameraSelector = null;
|
|
@@ -14436,7 +14389,7 @@ class MediaControl extends UICorePlugin {
|
|
|
14436
14389
|
* @internal
|
|
14437
14390
|
*/
|
|
14438
14391
|
get supportedVersion() {
|
|
14439
|
-
return { min: CLAPPR_VERSION };
|
|
14392
|
+
return { min: CLAPPR_VERSION$1 };
|
|
14440
14393
|
}
|
|
14441
14394
|
get disabled() {
|
|
14442
14395
|
const playbackIsNOOP = this.core.activeContainer &&
|
|
@@ -14598,7 +14551,7 @@ class MediaControl extends UICorePlugin {
|
|
|
14598
14551
|
this.userDisabled = true; // TODO distinguish between user and system (e.g., unplayable) disabled?
|
|
14599
14552
|
this.hide();
|
|
14600
14553
|
this.unbindKeyEvents();
|
|
14601
|
-
this.$el.hide();
|
|
14554
|
+
this.$el.hide(); // TODO why?
|
|
14602
14555
|
}
|
|
14603
14556
|
/**
|
|
14604
14557
|
* Reenables the plugin disabled earlier with the {@link MediaControl.disable} method
|
|
@@ -15054,16 +15007,16 @@ class MediaControl extends UICorePlugin {
|
|
|
15054
15007
|
default: [],
|
|
15055
15008
|
right: [],
|
|
15056
15009
|
}, this.core.activeContainer.settings);
|
|
15010
|
+
newSettings.left.push('clips'); // TODO
|
|
15057
15011
|
// TODO make order controlled via CSS
|
|
15058
|
-
newSettings.left = orderByOrderPattern([...newSettings.left, '
|
|
15012
|
+
newSettings.left = orderByOrderPattern([...newSettings.left, 'volume', 'clips'], LEFT_ORDER);
|
|
15059
15013
|
if (this.core.activePlayback.getPlaybackType() === Playback.LIVE &&
|
|
15060
15014
|
this.core.activePlayback.dvrEnabled) {
|
|
15061
15015
|
newSettings.left.push('dvr');
|
|
15062
15016
|
}
|
|
15063
15017
|
// actual order of the items appear rendered is controlled by CSS
|
|
15064
15018
|
newSettings.right = DEFAULT_SETTINGS.right; // TODO get from the options
|
|
15065
|
-
if ((!this.fullScreenOnVideoTagSupported &&
|
|
15066
|
-
!fullscreenEnabled()) ||
|
|
15019
|
+
if ((!this.fullScreenOnVideoTagSupported && !fullscreenEnabled()) ||
|
|
15067
15020
|
this.options.fullscreenDisable) {
|
|
15068
15021
|
trace(`${T$a} updateSettings removing fullscreen`, {
|
|
15069
15022
|
supported: this.fullScreenOnVideoTagSupported,
|
|
@@ -15109,8 +15062,6 @@ class MediaControl extends UICorePlugin {
|
|
|
15109
15062
|
this.$volumeBarFill = this.$el.find('.bar-fill-1[data-volume]');
|
|
15110
15063
|
this.$volumeBarScrubber = this.$el.find('.bar-scrubber[data-volume]');
|
|
15111
15064
|
this.$multiCameraSelector = this.$el.find('.media-control-multicamera[data-multicamera]');
|
|
15112
|
-
this.$clipText = this.$el.find('.media-clip-text[data-clipstext]'); // TODO
|
|
15113
|
-
this.$clipTextContainer = this.$el.find('.media-clip-container[data-clipstext]');
|
|
15114
15065
|
this.resetIndicators();
|
|
15115
15066
|
this.initializeIcons();
|
|
15116
15067
|
}
|
|
@@ -15125,25 +15076,14 @@ class MediaControl extends UICorePlugin {
|
|
|
15125
15076
|
* ```ts
|
|
15126
15077
|
* class MyPlugin extends UICorePlugin {
|
|
15127
15078
|
* override render() {
|
|
15128
|
-
*
|
|
15129
|
-
*
|
|
15130
|
-
* clipText?.el.text('Here we go')
|
|
15079
|
+
* this.$el.html('<div data-clips>Here we go</div>')
|
|
15080
|
+
* this.core.getPlugin('media_control').mount('clips', this.$el)
|
|
15131
15081
|
* return this
|
|
15132
15082
|
* }
|
|
15133
15083
|
* }
|
|
15134
15084
|
* ```
|
|
15135
15085
|
*/
|
|
15136
|
-
|
|
15137
|
-
switch (name) {
|
|
15138
|
-
case 'audiotracks':
|
|
15139
|
-
return null;
|
|
15140
|
-
case 'clipText':
|
|
15141
|
-
return this.$clipText;
|
|
15142
|
-
case 'seekBarContainer':
|
|
15143
|
-
return this.$seekBarContainer;
|
|
15144
|
-
}
|
|
15145
|
-
}
|
|
15146
|
-
putElement(name, element) {
|
|
15086
|
+
mount(name, element) {
|
|
15147
15087
|
const panel = this.getElementLocation(name);
|
|
15148
15088
|
if (panel) {
|
|
15149
15089
|
const current = panel.find(`[data-${name}]`);
|
|
@@ -15161,6 +15101,9 @@ class MediaControl extends UICorePlugin {
|
|
|
15161
15101
|
return;
|
|
15162
15102
|
}
|
|
15163
15103
|
}
|
|
15104
|
+
putElement(name, element) {
|
|
15105
|
+
this.mount(name, element);
|
|
15106
|
+
}
|
|
15164
15107
|
/**
|
|
15165
15108
|
* Toggle the visibility of a media control element
|
|
15166
15109
|
* @param name - The name of the media control element
|
|
@@ -15210,11 +15153,11 @@ class MediaControl extends UICorePlugin {
|
|
|
15210
15153
|
if (!this.settings.seekEnabled) {
|
|
15211
15154
|
return;
|
|
15212
15155
|
}
|
|
15213
|
-
const currentTime = this.
|
|
15214
|
-
const duration = this.
|
|
15156
|
+
const currentTime = this.core.activeContainer.getCurrentTime();
|
|
15157
|
+
const duration = this.core.activeContainer.getDuration();
|
|
15215
15158
|
let position = Math.min(Math.max(currentTime + delta, 0), duration);
|
|
15216
15159
|
position = Math.min((position * 100) / duration, 100);
|
|
15217
|
-
this.
|
|
15160
|
+
this.core.activeContainer.seekPercentage(position);
|
|
15218
15161
|
}
|
|
15219
15162
|
bindKeyAndShow(key, callback) {
|
|
15220
15163
|
// TODO or boolean return type
|
|
@@ -15332,7 +15275,10 @@ class MediaControl extends UICorePlugin {
|
|
|
15332
15275
|
* @internal
|
|
15333
15276
|
*/
|
|
15334
15277
|
render() {
|
|
15335
|
-
trace(`${T$a} render`, {
|
|
15278
|
+
trace(`${T$a} render`, {
|
|
15279
|
+
needsUpdate: this.hasUpdate,
|
|
15280
|
+
metadataLoaded: this.metadataLoaded,
|
|
15281
|
+
});
|
|
15336
15282
|
if (!this.hasUpdate || !this.metadataLoaded) {
|
|
15337
15283
|
return this;
|
|
15338
15284
|
}
|
|
@@ -15487,8 +15433,7 @@ MediaControl.extend = function (properties) {
|
|
|
15487
15433
|
return extend(MediaControl, properties);
|
|
15488
15434
|
};
|
|
15489
15435
|
function serializeSettings(s) {
|
|
15490
|
-
return s.left
|
|
15491
|
-
.slice()
|
|
15436
|
+
return s.left.slice()
|
|
15492
15437
|
.sort()
|
|
15493
15438
|
.concat(s.right.slice().sort())
|
|
15494
15439
|
.concat(s.default.slice().sort())
|
|
@@ -15520,7 +15465,7 @@ class MultiCamera extends UICorePlugin {
|
|
|
15520
15465
|
return 'multicamera';
|
|
15521
15466
|
}
|
|
15522
15467
|
get supportedVersion() {
|
|
15523
|
-
return { min: CLAPPR_VERSION };
|
|
15468
|
+
return { min: CLAPPR_VERSION$1 };
|
|
15524
15469
|
}
|
|
15525
15470
|
static get version() {
|
|
15526
15471
|
return VERSION$4;
|
|
@@ -15873,7 +15818,7 @@ class PictureInPicture extends UICorePlugin {
|
|
|
15873
15818
|
* @internal
|
|
15874
15819
|
*/
|
|
15875
15820
|
get supportedVersion() {
|
|
15876
|
-
return { min: CLAPPR_VERSION };
|
|
15821
|
+
return { min: CLAPPR_VERSION$1 };
|
|
15877
15822
|
}
|
|
15878
15823
|
/**
|
|
15879
15824
|
* @internal
|
|
@@ -16024,7 +15969,7 @@ class PlaybackRate extends UICorePlugin {
|
|
|
16024
15969
|
* @internal
|
|
16025
15970
|
*/
|
|
16026
15971
|
get supportedVersion() {
|
|
16027
|
-
return { min: CLAPPR_VERSION };
|
|
15972
|
+
return { min: CLAPPR_VERSION$1 };
|
|
16028
15973
|
}
|
|
16029
15974
|
static buttonTemplate = tmpl(buttonHtml$1);
|
|
16030
15975
|
static listTemplate = tmpl(listHtml$1);
|
|
@@ -16302,7 +16247,7 @@ class Poster extends UIContainerPlugin {
|
|
|
16302
16247
|
* @internal
|
|
16303
16248
|
*/
|
|
16304
16249
|
get supportedVersion() {
|
|
16305
|
-
return { min: CLAPPR_VERSION };
|
|
16250
|
+
return { min: CLAPPR_VERSION$1 };
|
|
16306
16251
|
}
|
|
16307
16252
|
static template = tmpl(posterHTML);
|
|
16308
16253
|
get shouldRender() {
|
|
@@ -16524,7 +16469,7 @@ class Poster extends UIContainerPlugin {
|
|
|
16524
16469
|
|
|
16525
16470
|
const buttonHtml = "<button class='gplayer-lite-btn gcore-skin-text-color gear-option' aria-haspopup=\"menu\">\n <span class=\"gear-option_icon<%= isHd ? '' : ' hidden' %>\"><%= hdIcon %></span>\n <span class=\"gear-option_label\"><%= i18n.t('quality') %></span>\n <span class='gear-option_value'><%= currentText %></span>\n <span class=\"gear-option_arrow-right-icon\"><%= arrowRightIcon %></span>\n</button>\n";
|
|
16526
16471
|
|
|
16527
|
-
const listHtml = "<button class=\"gplayer-lite-btn go-back gcore-skin-text-color\" id=\"level-selector-back-button\">\n <span class=\"arrow-left-icon\"><%= arrowLeftIcon %></span>\n <%= i18n.t('quality') %>\n</button>\n<ul class=\"gear-sub-menu quality-levels\" id=\"level-selector-menu\" role=\"menu\">\n <% if (!removeAuto) { %>\n <li>\n <a href=\"#\"
|
|
16472
|
+
const listHtml = "<button class=\"gplayer-lite-btn go-back gcore-skin-text-color\" id=\"level-selector-back-button\">\n <span class=\"arrow-left-icon\"><%= arrowLeftIcon %></span>\n <%= i18n.t('quality') %>\n</button>\n<ul class=\"gear-sub-menu quality-levels\" id=\"level-selector-menu\" role=\"menu\">\n <% if (!removeAuto) { %>\n <li>\n <a href=\"#\"\n class=\"gear-sub-menu_btn gcore-skin-text-color\"\n data-id=\"-1\"\n id=\"level_selector_auto\"\n aria-checked=\"<%= current === -1 %>\"\n role=\"menuitemradio\"\n >\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= i18n.t('auto') %>\n </a>\n </li>\n <% } %>\n <% for (const item of levels.slice().reverse()) {\n var disabled = maxLevel >= 0 && item.level > maxLevel\n var checked = item.level === current\n %>\n <li class=\"<%= disabled ? ' disabled' : ''%><%=checked ? ' current' : ''%>\">\n <a href=\"#\"\n class=\"gear-sub-menu_btn gcore-skin-text-color<%= checked ? ' gcore-skin-active' : '' %>\"\n data-id=\"<%= item.level %>\"\n aria-disabled=\"<%= disabled %>\"\n aria-checked=\"<%= checked %>\"\n role=\"menuitemradio\"\n id=\"level_selector_<%= item.width > item.height ? item.height : item.width %>\"\n >\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= labels[item.level] %>\n </a>\n </li>\n <% } %>\n</ul>\n";
|
|
16528
16473
|
|
|
16529
16474
|
const hdIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.9562 8.22232H13.9961V15.1873H14.9562C15.8914 15.1873 16.766 14.8253 17.4195 14.1676C18.0786 13.5037 18.4415 12.6281 18.4415 11.7026C18.4415 9.7837 16.8781 8.22253 14.9561 8.22253L14.9562 8.22232Z\"\n fill=\"#C9C9C9\"/>\n <path\n d=\"M22.0801 4H1.91994C0.859222 4 0 4.86406 0 5.91994V17.4878C0 18.5437 0.859222 19.4078 1.91994 19.4078H22.0801C23.1408 19.4078 24 18.5437 24 17.4878V5.91994C24 4.86406 23.1408 4 22.0801 4ZM10.3975 15.3473C10.3975 15.6124 10.1827 15.8272 9.91754 15.8272C9.65216 15.8272 9.43761 15.6122 9.43761 15.3473V12.0239H5.55956V15.3473C5.55956 15.6124 5.34481 15.8272 5.07963 15.8272C4.81425 15.8272 4.5997 15.6122 4.5997 15.3473L4.59949 7.74042C4.59949 7.47524 4.81425 7.26049 5.07943 7.26049C5.34481 7.26049 5.55936 7.47544 5.55936 7.74042V11.0636H9.43741V7.74042C9.43741 7.47524 9.65216 7.26049 9.91734 7.26049C10.1827 7.26049 10.3973 7.47544 10.3973 7.74042L10.3975 15.3473ZM18.1005 14.8438C17.2652 15.6844 16.1486 16.1472 14.9561 16.1472H13.5161C13.2507 16.1472 13.0361 15.9323 13.0361 15.6673V7.74263C13.0361 7.47745 13.2509 7.26269 13.5161 7.26269H14.9561C17.4072 7.26269 19.4013 9.25438 19.4013 11.7027C19.4013 12.8835 18.9392 13.9991 18.1005 14.844V14.8438Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
|
|
16530
16475
|
|
|
@@ -16574,7 +16519,7 @@ class QualityLevels extends UICorePlugin {
|
|
|
16574
16519
|
* @internal
|
|
16575
16520
|
*/
|
|
16576
16521
|
get supportedVersion() {
|
|
16577
|
-
return { min: CLAPPR_VERSION };
|
|
16522
|
+
return { min: CLAPPR_VERSION$1 };
|
|
16578
16523
|
}
|
|
16579
16524
|
/**
|
|
16580
16525
|
* @internal
|
|
@@ -16806,7 +16751,7 @@ class SeekTime extends UICorePlugin {
|
|
|
16806
16751
|
return 'seek_time';
|
|
16807
16752
|
}
|
|
16808
16753
|
get supportedVersion() {
|
|
16809
|
-
return { min: CLAPPR_VERSION };
|
|
16754
|
+
return { min: CLAPPR_VERSION$1 };
|
|
16810
16755
|
}
|
|
16811
16756
|
get template() {
|
|
16812
16757
|
return tmpl(seekTimeHTML);
|
|
@@ -16968,7 +16913,7 @@ class Share extends UICorePlugin {
|
|
|
16968
16913
|
return 'share';
|
|
16969
16914
|
}
|
|
16970
16915
|
get supportedVersion() {
|
|
16971
|
-
return { min: CLAPPR_VERSION };
|
|
16916
|
+
return { min: CLAPPR_VERSION$1 };
|
|
16972
16917
|
}
|
|
16973
16918
|
get template() {
|
|
16974
16919
|
return tmpl(pluginHtml$2);
|
|
@@ -17087,7 +17032,7 @@ class SkipTime extends UICorePlugin {
|
|
|
17087
17032
|
return 'skip_time';
|
|
17088
17033
|
}
|
|
17089
17034
|
get supportedVersion() {
|
|
17090
|
-
return { min: CLAPPR_VERSION };
|
|
17035
|
+
return { min: CLAPPR_VERSION$1 };
|
|
17091
17036
|
}
|
|
17092
17037
|
get container() {
|
|
17093
17038
|
return this.core && this.core.activeContainer;
|
|
@@ -17226,7 +17171,7 @@ class SpinnerThreeBounce extends UIContainerPlugin {
|
|
|
17226
17171
|
* @internal
|
|
17227
17172
|
*/
|
|
17228
17173
|
get supportedVersion() {
|
|
17229
|
-
return { min: CLAPPR_VERSION };
|
|
17174
|
+
return { min: CLAPPR_VERSION$1 };
|
|
17230
17175
|
}
|
|
17231
17176
|
/**
|
|
17232
17177
|
* @internal
|
|
@@ -17457,7 +17402,7 @@ class SourceController extends CorePlugin {
|
|
|
17457
17402
|
* @internal
|
|
17458
17403
|
*/
|
|
17459
17404
|
get supportedVersion() {
|
|
17460
|
-
return { min: CLAPPR_VERSION };
|
|
17405
|
+
return { min: CLAPPR_VERSION$1 };
|
|
17461
17406
|
}
|
|
17462
17407
|
/**
|
|
17463
17408
|
* @param core - The Clappr core instance.
|
|
@@ -17633,7 +17578,7 @@ class ClosedCaptions extends UICorePlugin {
|
|
|
17633
17578
|
* @internal
|
|
17634
17579
|
*/
|
|
17635
17580
|
get supportedVersion() {
|
|
17636
|
-
return { min: CLAPPR_VERSION };
|
|
17581
|
+
return { min: CLAPPR_VERSION$1 };
|
|
17637
17582
|
}
|
|
17638
17583
|
/**
|
|
17639
17584
|
* @internal
|
|
@@ -17969,7 +17914,7 @@ class Telemetry extends ContainerPlugin {
|
|
|
17969
17914
|
* The supported version of the plugin.
|
|
17970
17915
|
*/
|
|
17971
17916
|
get supportedVersion() {
|
|
17972
|
-
return { min: CLAPPR_VERSION };
|
|
17917
|
+
return { min: CLAPPR_VERSION$1 };
|
|
17973
17918
|
}
|
|
17974
17919
|
started = false;
|
|
17975
17920
|
timeStart = 0;
|
|
@@ -18255,7 +18200,7 @@ class Thumbnails extends UICorePlugin {
|
|
|
18255
18200
|
* @internal
|
|
18256
18201
|
*/
|
|
18257
18202
|
get supportedVersion() {
|
|
18258
|
-
return { min: CLAPPR_VERSION };
|
|
18203
|
+
return { min: CLAPPR_VERSION$1 };
|
|
18259
18204
|
}
|
|
18260
18205
|
/**
|
|
18261
18206
|
* @internal
|
|
@@ -18750,4 +18695,4 @@ class VolumeFade extends UICorePlugin {
|
|
|
18750
18695
|
}
|
|
18751
18696
|
}
|
|
18752
18697
|
|
|
18753
|
-
export { AudioTracks as AudioSelector, AudioTracks, BigMuteButton, BottomGear, ClapprNerdStats, ClapprStats, ClickToPause,
|
|
18698
|
+
export { AudioTracks as AudioSelector, AudioTracks, BigMuteButton, BottomGear, NerdStats as ClapprNerdStats, ClapprStats, ClickToPause, Clips, ClosedCaptions, ContextMenu, DvrControls, ErrorScreen, Favicon, GearEvents, GoogleAnalytics, QualityLevels as LevelSelector, Logo, MediaControl, MultiCamera, NerdStats, PictureInPicture, PlaybackRate, Poster, QualityLevels, SeekTime, Share, SkipTime, SourceController, SpinnerThreeBounce as Spinner, SpinnerEvents, SpinnerThreeBounce, ClosedCaptions as Subtitles, Telemetry, TelemetryEvent, Thumbnails, VolumeFade, VolumeFadeEvents };
|