-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvideojs-http-source-selector.js
268 lines (210 loc) · 8.69 KB
/
videojs-http-source-selector.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/**
* videojs-http-source-selector
* @version 1.1.6
* @copyright 2019 Justin Fujita <Justin@pivotshare.com>
* @license MIT
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
typeof define === 'function' && define.amd ? define(['video.js'], factory) :
(global = global || self, global['videojs-http-source-selector'] = factory(global.videojs));
}(this, function (videojs) { 'use strict';
videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;
var version = "1.1.6";
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
var MenuItem = videojs.getComponent('MenuItem');
var Component = videojs.getComponent('Component');
var SourceMenuItem =
/*#__PURE__*/
function (_MenuItem) {
_inheritsLoose(SourceMenuItem, _MenuItem);
function SourceMenuItem(player, options) {
options.selectable = true;
options.multiSelectable = false;
return _MenuItem.call(this, player, options) || this;
}
var _proto = SourceMenuItem.prototype;
_proto.handleClick = function handleClick() {
var selected = this.options_;
console.log("Changing quality to:", selected.label);
_MenuItem.prototype.handleClick.call(this);
var levels = this.player().qualityLevels();
for (var i = 0; i < levels.length; i++) {
if (selected.index == levels.length) {
// If this is the Auto option, enable all renditions for adaptive selection
levels[i].enabled = true;
} else if (selected.index == i) {
levels[i].enabled = true;
} else {
levels[i].enabled = false;
}
}
};
_proto.update = function update() {
var selectedIndex = this.player().qualityLevels().selectedIndex;
this.selected(this.options_.index == selectedIndex);
};
return SourceMenuItem;
}(MenuItem);
Component.registerComponent('SourceMenuItem', SourceMenuItem);
var MenuButton = videojs.getComponent('MenuButton');
var SourceMenuButton =
/*#__PURE__*/
function (_MenuButton) {
_inheritsLoose(SourceMenuButton, _MenuButton);
function SourceMenuButton(player, options) {
var _this;
_this = _MenuButton.call(this, player, options) || this;
MenuButton.apply(_assertThisInitialized(_this), arguments);
var qualityLevels = _this.player().qualityLevels(); // Handle options: We accept an options.default value of ( high || low )
// This determines a bias to set initial resolution selection.
if (options && options["default"]) {
if (options["default"] == 'low') {
for (var i = 0; i < qualityLevels.length; i++) {
qualityLevels[i].enabled = i == 0;
}
} else if (options["default"] = 'high') {
for (var i = 0; i < qualityLevels.length; i++) {
qualityLevels[i].enabled = i == qualityLevels.length - 1;
}
}
} // Bind update to qualityLevels changes
_this.player().qualityLevels().on(['change', 'addqualitylevel'], videojs.bind(_assertThisInitialized(_this), _this.update));
return _this;
}
var _proto = SourceMenuButton.prototype;
_proto.createEl = function createEl() {
return videojs.dom.createEl('div', {
className: 'vjs-http-source-selector vjs-menu-button vjs-menu-button-popup vjs-control vjs-button'
});
};
_proto.buildCSSClass = function buildCSSClass() {
return MenuButton.prototype.buildCSSClass.call(this) + ' vjs-icon-cog';
};
_proto.update = function update() {
return MenuButton.prototype.update.call(this);
};
_proto.createItems = function createItems() {
var menuItems = [];
var levels = this.player().qualityLevels();
var labels = [];
for (var i = 0; i < levels.length; i++) {
var index = levels.length - (i + 1);
var selected = index === levels.selectedIndex; // Display height if height metadata is provided with the stream, else use bitrate
var label = "" + index;
var sortVal = index;
if (levels[index].height) {
label = levels[index].height + "p";
sortVal = parseInt(levels[index].height, 10);
} else if (levels[index].bitrate) {
label = Math.floor(levels[index].bitrate / 1e3) + " kbps";
sortVal = parseInt(levels[index].bitrate, 10);
} // Skip duplicate labels
if (labels.indexOf(label) >= 0) {
continue;
}
labels.push(label);
menuItems.push(new SourceMenuItem(this.player_, {
label: label,
index: index,
selected: selected,
sortVal: sortVal
}));
} // If there are multiple quality levels, offer an 'auto' option
if (levels.length > 1) {
menuItems.push(new SourceMenuItem(this.player_, {
label: 'Auto',
index: levels.length,
selected: false,
sortVal: 99999
}));
} // Sort menu items by their label name with Auto always first
menuItems.sort(function (a, b) {
if (a.options_.sortVal < b.options_.sortVal) {
return 1;
} else if (a.options_.sortVal > b.options_.sortVal) {
return -1;
} else {
return 0;
}
});
return menuItems;
};
return SourceMenuButton;
}(MenuButton);
var defaults = {}; // Cross-compatibility for Video.js 5 and 6.
var registerPlugin = videojs.registerPlugin || videojs.plugin; // const dom = videojs.dom || videojs;
/**
* Function to invoke when the player is ready.
*
* This is a great place for your plugin to initialize itself. When this
* function is called, the player will have its DOM and child components
* in place.
*
* @function onPlayerReady
* @param {Player} player
* A Video.js player object.
*
* @param {Object} [options={}]
* A plain object containing options for the plugin.
*/
var onPlayerReady = function onPlayerReady(player, options) {
player.addClass('vjs-http-source-selector');
console.log("videojs-http-source-selector initialized!");
console.log("player.techName_:" + player.techName_); //This plugin only supports level selection for HLS playback
if (player.techName_ != 'Html5') {
return false;
}
/**
*
* We have to wait for the manifest to load before we can scan renditions for resolutions/bitrates to populate selections
*
**/
player.on(['loadedmetadata'], function (e) {
var qualityLevels = player.qualityLevels();
videojs.log('loadmetadata event'); // hack for plugin idempodency... prevents duplicate menubuttons from being inserted into the player if multiple player.httpSourceSelector() functions called.
if (player.videojs_http_source_selector_initialized == 'undefined' || player.videojs_http_source_selector_initialized == true) {
console.log("player.videojs_http_source_selector_initialized == true");
} else {
console.log("player.videojs_http_source_selector_initialized == false");
player.videojs_http_source_selector_initialized = true;
var controlBar = player.controlBar,
fullscreenToggle = controlBar.getChild('fullscreenToggle').el();
controlBar.el().insertBefore(controlBar.addChild('SourceMenuButton').el(), fullscreenToggle);
}
});
};
/**
* A video.js plugin.
*
* In the plugin function, the value of `this` is a video.js `Player`
* instance. You cannot rely on the player being in a "ready" state here,
* depending on how the plugin is invoked. This may or may not be important
* to you; if not, remove the wait for "ready"!
*
* @function httpSourceSelector
* @param {Object} [options={}]
* An object of options left to the plugin author to define.
*/
var httpSourceSelector = function httpSourceSelector(options) {
var _this = this;
this.ready(function () {
onPlayerReady(_this, videojs.mergeOptions(defaults, options)); //this.getChild('controlBar').addChild('SourceMenuButton', {});
});
videojs.registerComponent('SourceMenuButton', SourceMenuButton);
videojs.registerComponent('SourceMenuItem', SourceMenuItem);
}; // Register the plugin with video.js.
registerPlugin('httpSourceSelector', httpSourceSelector); // Include the version number.
httpSourceSelector.VERSION = version;
return httpSourceSelector;
}));