@flashphoner/websdk 2.0.243 → 2.0.245
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/docTemplate/README.md +1 -1
- package/examples/demo/streaming/hls-js-player/hls-js-player.js +220 -29
- package/examples/demo/streaming/hls-native/hls-native.js +142 -33
- package/examples/demo/streaming/hls-player/hls-player.js +305 -74
- package/examples/demo/streaming/hls-player/player-page.html +47 -14
- package/examples/demo/streaming/hls-player/videojs7/videojs-contrib-quality-levels.js +308 -0
- package/package.json +1 -1
|
@@ -7,16 +7,29 @@ const LIVE_THRESHOLD = 5;
|
|
|
7
7
|
const LIVE_TOLERANCE = 5;
|
|
8
8
|
const LIVE_UI_INTERVAL = 1000;
|
|
9
9
|
const STATS_INTERVAL = 1000;
|
|
10
|
+
const QUALITY_COLORS = {
|
|
11
|
+
NONE: "",
|
|
12
|
+
AVAILABLE: "black",
|
|
13
|
+
SELECTED: "blue"
|
|
14
|
+
};
|
|
15
|
+
const QUALITY_AUTO = "Auto";
|
|
10
16
|
let player = null;
|
|
11
17
|
let liveUITimer = null;
|
|
12
18
|
let videojsVersion = getUrlParam("version");
|
|
19
|
+
let playSrc = getUrlParam("src");
|
|
20
|
+
let autoplay = eval(getUrlParam("autoplay")) || false;
|
|
13
21
|
let playbackStats = null;
|
|
22
|
+
let qualityLevels = [];
|
|
14
23
|
|
|
15
24
|
const loadPlayerPage = function() {
|
|
16
25
|
if (videojsVersion) {
|
|
17
26
|
hideItem("videojsInputForm");
|
|
18
|
-
loadVideoJS(
|
|
27
|
+
loadVideoJS(videojsVersion);
|
|
19
28
|
} else {
|
|
29
|
+
if (autoplay) {
|
|
30
|
+
console.warn("No VideoJS version set, autoplay disabled");
|
|
31
|
+
autoplay = false;
|
|
32
|
+
}
|
|
20
33
|
let videojsInput = document.getElementById("videojsInput");
|
|
21
34
|
for (videojsType in VIDEOJS_VERSION_TYPE) {
|
|
22
35
|
let option = document.createElement("option");
|
|
@@ -38,24 +51,17 @@ const loadPlayerPage = function() {
|
|
|
38
51
|
}
|
|
39
52
|
}
|
|
40
53
|
|
|
41
|
-
const onVideojsBtnClick = function
|
|
54
|
+
const onVideojsBtnClick = function() {
|
|
42
55
|
loadVideoJS(getValue("videojsInput"));
|
|
43
56
|
}
|
|
44
57
|
|
|
45
|
-
const loadVideoJS = function
|
|
58
|
+
const loadVideoJS = function(version) {
|
|
46
59
|
if (version) {
|
|
60
|
+
videojsVersion = version;
|
|
47
61
|
let playerPage = document.getElementById("playerPage");
|
|
48
62
|
loadFile(version + "/video.js", "text/javascript").then( data => {
|
|
49
63
|
console.log("HLS library loaded successfully", data);
|
|
50
|
-
|
|
51
|
-
console.log("HLS library stylesheet loaded successfully", data);
|
|
52
|
-
hideItem("videojsInputForm");
|
|
53
|
-
loadPage("player-page.html", "playerPage", initPage );
|
|
54
|
-
}).catch( err => {
|
|
55
|
-
playerPage.innerHTML = "Can't load VideoJS library stylesheet";
|
|
56
|
-
playerPage.setAttribute("class", "text-danger");
|
|
57
|
-
console.error(err);
|
|
58
|
-
})
|
|
64
|
+
loadStyles(version, playerPage);
|
|
59
65
|
}).catch( err => {
|
|
60
66
|
setText("videojsError", "Can't load VideoJS library");
|
|
61
67
|
console.error(err);
|
|
@@ -63,6 +69,37 @@ const loadVideoJS = function (version) {
|
|
|
63
69
|
}
|
|
64
70
|
}
|
|
65
71
|
|
|
72
|
+
const loadStyles = function(version, playerPage) {
|
|
73
|
+
if (version) {
|
|
74
|
+
loadFile(version + "/video-js.css", "stylesheet").then ( data => {
|
|
75
|
+
console.log("HLS library stylesheet loaded successfully", data);
|
|
76
|
+
if (version === VIDEOJS_VERSION_TYPE.VIDEOJS7) {
|
|
77
|
+
loadQualityPlugin(version, playerPage);
|
|
78
|
+
} else {
|
|
79
|
+
hideItem("videojsInputForm");
|
|
80
|
+
loadPage("player-page.html", "playerPage", initPage);
|
|
81
|
+
}
|
|
82
|
+
}).catch( err => {
|
|
83
|
+
playerPage.innerHTML = "Can't load VideoJS library stylesheet";
|
|
84
|
+
playerPage.setAttribute("class", "text-danger");
|
|
85
|
+
console.error(err);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const loadQualityPlugin = function(version, playerPage) {
|
|
91
|
+
if (version) {
|
|
92
|
+
loadFile(version + "/videojs-contrib-quality-levels.js", "text/javascript").then( data => {
|
|
93
|
+
console.log("HLS quality levels plugin loaded successfully", data);
|
|
94
|
+
hideItem("videojsInputForm");
|
|
95
|
+
loadPage("player-page.html", "playerPage", initPage);
|
|
96
|
+
}).catch( err => {
|
|
97
|
+
setText("videojsError", "Can't load VideoJS quality levels plugin");
|
|
98
|
+
console.error(err);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
66
103
|
const loadFile = function(url, type) {
|
|
67
104
|
return new Promise((resolve, reject) => {
|
|
68
105
|
try {
|
|
@@ -117,31 +154,37 @@ const loadPage = function(page, containerId, onLoad) {
|
|
|
117
154
|
}
|
|
118
155
|
|
|
119
156
|
const initPage = function() {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
setHandler("backBtn30", "click", backBtnClick);
|
|
127
|
-
setHandler("backBtnMax", "click", backBtnClick);
|
|
128
|
-
setHandler("liveBtn", "click", liveBtnClick);
|
|
157
|
+
if (playSrc) {
|
|
158
|
+
setValue("fullLink", decodeURIComponent(playSrc));
|
|
159
|
+
} else if (autoplay) {
|
|
160
|
+
console.warn("No HLS URL set, autoplay disabled");
|
|
161
|
+
autoplay = false;
|
|
162
|
+
}
|
|
129
163
|
let remoteVideo = document.getElementById('remoteVideo');
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
164
|
+
if (autoplay) {
|
|
165
|
+
// There should not be any visible item on the page unless player
|
|
166
|
+
hideAllToAutoplay();
|
|
167
|
+
// The player should use all available page width
|
|
168
|
+
setUpPlayerItem(true);
|
|
169
|
+
// The player should be muted to automatically start playback
|
|
170
|
+
player = initVideoJsPlayer(remoteVideo, true);
|
|
171
|
+
playBtnClick();
|
|
172
|
+
} else {
|
|
173
|
+
// No autoplay, all the forms and buttons should be visible
|
|
174
|
+
setText("header", "HLS VideoJS Player Minimal");
|
|
175
|
+
displayCommonItems();
|
|
176
|
+
setUpButtons();
|
|
177
|
+
enablePlaybackStats();
|
|
178
|
+
// The player should have a maximum fixed size
|
|
179
|
+
setUpPlayerItem(false);
|
|
180
|
+
// The player can be unmuted because user should click Play button
|
|
181
|
+
player = initVideoJsPlayer(remoteVideo, false);
|
|
182
|
+
}
|
|
133
183
|
}
|
|
134
184
|
|
|
135
185
|
const playBtnClick = function() {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
streamName = encodeURIComponent(streamName);
|
|
139
|
-
let videoSrc = getValue("urlServer") + '/' + streamName + '/' + streamName + '.m3u8';
|
|
140
|
-
let key = getValue('key');
|
|
141
|
-
let token = getValue("token");
|
|
142
|
-
if (key.length > 0 && token.length > 0) {
|
|
143
|
-
videoSrc += "?" + key + "=" + token;
|
|
144
|
-
}
|
|
186
|
+
let videoSrc = getVideoSrc(getValue("fullLink"));
|
|
187
|
+
if (videoSrc) {
|
|
145
188
|
player.on('loadedmetadata', function() {
|
|
146
189
|
console.log("Play with VideoJs");
|
|
147
190
|
player.play();
|
|
@@ -157,6 +200,7 @@ const playBtnClick = function() {
|
|
|
157
200
|
});
|
|
158
201
|
player.on('playing', function() {
|
|
159
202
|
console.log("playing event fired");
|
|
203
|
+
displayPermalink(videoSrc);
|
|
160
204
|
if (player.liveTracker) {
|
|
161
205
|
if (!player.liveTracker.isLive()) {
|
|
162
206
|
// A cratch to display live UI for the first subscriber
|
|
@@ -169,6 +213,8 @@ const playBtnClick = function() {
|
|
|
169
213
|
stopLiveUITimer();
|
|
170
214
|
}
|
|
171
215
|
}
|
|
216
|
+
initQualityLevels(player);
|
|
217
|
+
displayQualitySwitch();
|
|
172
218
|
});
|
|
173
219
|
player.src({
|
|
174
220
|
src: videoSrc,
|
|
@@ -231,23 +277,30 @@ const liveBtnClick = function() {
|
|
|
231
277
|
}
|
|
232
278
|
|
|
233
279
|
const onStarted = function() {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
280
|
+
if (!autoplay) {
|
|
281
|
+
toggleInputs(false);
|
|
282
|
+
enableItem("applyBtn");
|
|
283
|
+
hideItem("permalink");
|
|
284
|
+
showItem("backward");
|
|
285
|
+
setText("applyBtn", "Stop");
|
|
286
|
+
setHandler("applyBtn", "click", stopBtnClick, playBtnClick);
|
|
287
|
+
startPlaybackStats();
|
|
288
|
+
hideItem("quality");
|
|
289
|
+
}
|
|
241
290
|
}
|
|
242
291
|
|
|
243
292
|
|
|
244
293
|
const onStopped = function() {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
294
|
+
if (!autoplay) {
|
|
295
|
+
toggleInputs(true);
|
|
296
|
+
enableItem("applyBtn");
|
|
297
|
+
hideItem("backward");
|
|
298
|
+
setText("applyBtn", "Play");
|
|
299
|
+
setHandler("applyBtn", "click", playBtnClick, stopBtnClick);
|
|
300
|
+
stopPlaybackStats();
|
|
301
|
+
hideItem("quality");
|
|
302
|
+
disposeQualityLevels();
|
|
303
|
+
}
|
|
251
304
|
if(!document.getElementById('remoteVideo')) {
|
|
252
305
|
createRemoteVideo(document.getElementById('videoContainer'));
|
|
253
306
|
}
|
|
@@ -264,7 +317,7 @@ const createRemoteVideo = function(parent) {
|
|
|
264
317
|
remoteVideo.setAttribute("playsinline","");
|
|
265
318
|
remoteVideo.setAttribute("webkit-playsinline","");
|
|
266
319
|
parent.appendChild(remoteVideo);
|
|
267
|
-
player = initVideoJsPlayer(remoteVideo);
|
|
320
|
+
player = initVideoJsPlayer(remoteVideo, autoplay);
|
|
268
321
|
}
|
|
269
322
|
|
|
270
323
|
|
|
@@ -309,23 +362,33 @@ const removeHighlight = function(input) {
|
|
|
309
362
|
}
|
|
310
363
|
}
|
|
311
364
|
|
|
312
|
-
const initVideoJsPlayer = function(video) {
|
|
313
|
-
let videoJsPlayer =
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
365
|
+
const initVideoJsPlayer = function(video, muted) {
|
|
366
|
+
let videoJsPlayer = null;
|
|
367
|
+
if (video) {
|
|
368
|
+
video.className = "video-js vjs-default-skin";
|
|
369
|
+
videoJsPlayer = videojs(video, {
|
|
370
|
+
playsinline: true,
|
|
371
|
+
playbackRates: [0.1, 0.25, 0.5, 1, 1.5, 2],
|
|
372
|
+
liveui: true,
|
|
373
|
+
liveTracker: {
|
|
374
|
+
trackingThreshold: LIVE_THRESHOLD,
|
|
375
|
+
liveTolerance: LIVE_TOLERANCE
|
|
376
|
+
},
|
|
377
|
+
fill: true,
|
|
378
|
+
muted: muted,
|
|
379
|
+
html5: {
|
|
380
|
+
vhs: {
|
|
381
|
+
limitRenditionByPlayerDimensions: false
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
console.log("Using VideoJs " + videojs.VERSION);
|
|
386
|
+
if (Browser.isSafariWebRTC() && Browser.isiOS()) {
|
|
387
|
+
// iOS hack when using standard controls to leave fullscreen mode
|
|
388
|
+
let videoTag = getActualVideoTag();
|
|
389
|
+
if(videoTag) {
|
|
390
|
+
setWebkitFullscreenHandlers(videoTag, false);
|
|
391
|
+
}
|
|
329
392
|
}
|
|
330
393
|
}
|
|
331
394
|
return videoJsPlayer;
|
|
@@ -339,15 +402,25 @@ const getActualVideoTag = function() {
|
|
|
339
402
|
return null;
|
|
340
403
|
}
|
|
341
404
|
|
|
405
|
+
const setUpButtons = function() {
|
|
406
|
+
setHandler("applyBtn", "click", playBtnClick);
|
|
407
|
+
setHandler("backBtn10", "click", backBtnClick);
|
|
408
|
+
setHandler("backBtn30", "click", backBtnClick);
|
|
409
|
+
setHandler("backBtnMax", "click", backBtnClick);
|
|
410
|
+
setHandler("liveBtn", "click", liveBtnClick);
|
|
411
|
+
}
|
|
412
|
+
|
|
342
413
|
const toggleBackButtons = function(enable) {
|
|
343
|
-
if (
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
414
|
+
if (!autoplay) {
|
|
415
|
+
if (enable) {
|
|
416
|
+
enableItem("backBtn10");
|
|
417
|
+
enableItem("backBtn30");
|
|
418
|
+
enableItem("backBtnMax");
|
|
419
|
+
} else {
|
|
420
|
+
disableItem("backBtn10");
|
|
421
|
+
disableItem("backBtn30");
|
|
422
|
+
disableItem("backBtnMax");
|
|
423
|
+
}
|
|
351
424
|
}
|
|
352
425
|
}
|
|
353
426
|
|
|
@@ -367,6 +440,88 @@ const toggleInputs = function(enable) {
|
|
|
367
440
|
}
|
|
368
441
|
}
|
|
369
442
|
|
|
443
|
+
const getVideoSrc = function(src) {
|
|
444
|
+
let videoSrc = src;
|
|
445
|
+
if (validateForm()) {
|
|
446
|
+
let streamName = getValue('playStream');
|
|
447
|
+
streamName = encodeURIComponent(streamName);
|
|
448
|
+
videoSrc = getValue("urlServer") + '/' + streamName + '/' + streamName + '.m3u8';
|
|
449
|
+
let key = getValue('key');
|
|
450
|
+
let token = getValue("token");
|
|
451
|
+
if (key.length > 0 && token.length > 0) {
|
|
452
|
+
videoSrc += "?" + key + "=" + token;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
setValue("fullLink", videoSrc);
|
|
456
|
+
return videoSrc;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const displayPermalink = function(src) {
|
|
460
|
+
if (!autoplay) {
|
|
461
|
+
const permalinkId = "permalink";
|
|
462
|
+
let videoSrc = encodeURIComponent(src);
|
|
463
|
+
let linkObject = document.getElementById(permalinkId);
|
|
464
|
+
let href = window.location.href.split("?")[0] + "?version=" + videojsVersion + "&src=" + videoSrc;
|
|
465
|
+
linkObject.href = href;
|
|
466
|
+
showItem(permalinkId);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const displayQualitySwitch = function() {
|
|
471
|
+
if (!autoplay && qualityLevels.length) {
|
|
472
|
+
showItem("quality")
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const hideAllToAutoplay = function() {
|
|
477
|
+
hideItem("header");
|
|
478
|
+
hideItem("notifyFlash");
|
|
479
|
+
hideItem("fieldset");
|
|
480
|
+
hideItem("stats");
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const displayCommonItems = function() {
|
|
484
|
+
setValue("urlServer", getHLSUrl());
|
|
485
|
+
hideItem("permalink");
|
|
486
|
+
enableItem("applyBtn");
|
|
487
|
+
setText("applyBtn", "Play");
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const setUpPlayerItem = function(fillPage) {
|
|
491
|
+
let videoContainer = document.getElementById('videoContainer');
|
|
492
|
+
let playerPage = document.getElementById('playerPage');
|
|
493
|
+
|
|
494
|
+
if (fillPage) {
|
|
495
|
+
playerPage.classList.remove("container");
|
|
496
|
+
videoContainer.style.marginTop = "0px";
|
|
497
|
+
videoContainer.style.width = "100vw";
|
|
498
|
+
videoContainer.style.height = "100vh";
|
|
499
|
+
videoContainer.style.maxWidth = "available";
|
|
500
|
+
videoContainer.style.maxHeight = "available";
|
|
501
|
+
} else {
|
|
502
|
+
videoContainer.style.maxWidth = "852px";
|
|
503
|
+
videoContainer.style.maxHeight = "480px";
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const enablePlaybackStats = function() {
|
|
508
|
+
if (!autoplay && !playbackStats) {
|
|
509
|
+
playbackStats = PlaybackStats(STATS_INTERVAL);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const startPlaybackStats = function() {
|
|
514
|
+
if (!autoplay && playbackStats) {
|
|
515
|
+
playbackStats.start();
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const stopPlaybackStats = function() {
|
|
520
|
+
if (!autoplay && playbackStats) {
|
|
521
|
+
playbackStats.stop();
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
370
525
|
const PlaybackStats = function(interval) {
|
|
371
526
|
const playbackStats = {
|
|
372
527
|
interval: interval || STATS_INTERVAL,
|
|
@@ -374,7 +529,6 @@ const PlaybackStats = function(interval) {
|
|
|
374
529
|
stats: null,
|
|
375
530
|
start: function() {
|
|
376
531
|
let video = getActualVideoTag();
|
|
377
|
-
|
|
378
532
|
playbackStats.stop();
|
|
379
533
|
stats = HTML5Stats(video);
|
|
380
534
|
playbackStats.timer = setInterval(playbackStats.displayStats, playbackStats.interval);
|
|
@@ -412,4 +566,81 @@ const PlaybackStats = function(interval) {
|
|
|
412
566
|
}
|
|
413
567
|
};
|
|
414
568
|
return playbackStats;
|
|
415
|
-
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const initQualityLevels = function(player) {
|
|
572
|
+
if (player && !qualityLevels.length) {
|
|
573
|
+
let playerQualityLevels = player.qualityLevels();
|
|
574
|
+
if (playerQualityLevels) {
|
|
575
|
+
let qualityDiv = document.getElementById("qualityBtns");
|
|
576
|
+
let qualityLevel;
|
|
577
|
+
for (let i = 0; i < playerQualityLevels.length; i++) {
|
|
578
|
+
qualityLevel = QualityLevel(playerQualityLevels, playerQualityLevels[i].height, i, qualityDiv);
|
|
579
|
+
qualityLevels.push(qualityLevel);
|
|
580
|
+
}
|
|
581
|
+
if (qualityLevels.length) {
|
|
582
|
+
qualityLevel = QualityLevel(playerQualityLevels, QUALITY_AUTO, -1, qualityDiv);
|
|
583
|
+
qualityLevels.push(qualityLevel);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
const disposeQualityLevels = function() {
|
|
590
|
+
qualityLevels.forEach(level => {
|
|
591
|
+
if (level.button) {
|
|
592
|
+
level.button.remove();
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
qualityLevels = [];
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
const qualityBtnClick = function(button, playerQualityLevels, index) {
|
|
599
|
+
if (playerQualityLevels && playerQualityLevels.length) {
|
|
600
|
+
let currentIndex = playerQualityLevels.selectedIndex_;
|
|
601
|
+
for (let i = 0; i < playerQualityLevels.length; i++) {
|
|
602
|
+
let qualityLevel = playerQualityLevels[i];
|
|
603
|
+
if (index === -1 || i === index) {
|
|
604
|
+
qualityLevel.enabled = true;
|
|
605
|
+
} else if (i === index) {
|
|
606
|
+
qualityLevel.enabled = true;
|
|
607
|
+
currentIndex = index;
|
|
608
|
+
} else {
|
|
609
|
+
qualityLevel.enabled = false;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
playerQualityLevels.selectedIndex_ = currentIndex;
|
|
613
|
+
playerQualityLevels.trigger({ type: 'change', selectedIndex: currentIndex });
|
|
614
|
+
}
|
|
615
|
+
button.style.color = QUALITY_COLORS.SELECTED;
|
|
616
|
+
qualityLevels.forEach(item => {
|
|
617
|
+
if (item.button.id !== button.id) {
|
|
618
|
+
item.button.style.color = QUALITY_COLORS.AVAILABLE
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const QualityLevel = function(object, levelId, index, btnParent) {
|
|
624
|
+
const btnId = "qualityBtn";
|
|
625
|
+
let button = document.createElement("button");
|
|
626
|
+
if (levelId === QUALITY_AUTO && index === -1) {
|
|
627
|
+
button.id = btnId + QUALITY_AUTO;
|
|
628
|
+
button.innerHTML = QUALITY_AUTO;
|
|
629
|
+
} else {
|
|
630
|
+
button.id = btnId + index;
|
|
631
|
+
button.innerHTML = levelId;
|
|
632
|
+
}
|
|
633
|
+
button.type = "button";
|
|
634
|
+
button.className = "btn btn-default";
|
|
635
|
+
button.style.color = QUALITY_COLORS.AVAILABLE;
|
|
636
|
+
button.onclick = (event) => {
|
|
637
|
+
qualityBtnClick(button, object, index);
|
|
638
|
+
};
|
|
639
|
+
btnParent.appendChild(button);
|
|
640
|
+
const qualityLevel = {
|
|
641
|
+
level: levelId,
|
|
642
|
+
index: index,
|
|
643
|
+
button: button
|
|
644
|
+
};
|
|
645
|
+
return qualityLevel;
|
|
646
|
+
}
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
</div>
|
|
29
29
|
|
|
30
30
|
<div class="row" style="margin-top:10px">
|
|
31
|
-
<div class="form-group">
|
|
31
|
+
<div id="authForm" class="form-group">
|
|
32
32
|
<label class="control-label col-sm-1 fp-buttonVerticalAlign text-left"
|
|
33
|
-
for="
|
|
33
|
+
for="key">Auth</label>
|
|
34
34
|
|
|
35
35
|
<div class="col-sm-12">
|
|
36
36
|
<div class="col-sm-4 nopadding">
|
|
@@ -43,16 +43,52 @@
|
|
|
43
43
|
</div>
|
|
44
44
|
</div>
|
|
45
45
|
</div>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
|
|
47
|
+
<div class="row" style="margin-top:10px">
|
|
48
|
+
<div id="linkForm" class="form-group">
|
|
49
|
+
<label class="control-label col-sm-12 fp-buttonVerticalAlign text-left"
|
|
50
|
+
for="fullLink">Or set a full HLS stream URL</label>
|
|
51
|
+
|
|
52
|
+
<div class="col-sm-12">
|
|
53
|
+
<input type="text" class="form-control" id="fullLink" placeholder="Full HLS link"/>
|
|
51
54
|
</div>
|
|
52
55
|
</div>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="row" style="margin-top: 10px">
|
|
59
|
+
<div class="col-sm-4 text-left" id="llHlsMode" style="display: none;">
|
|
60
|
+
<input id="llHlsEnabled" class="form-check-input" type="checkbox" value="">
|
|
61
|
+
<label class="form-check-label" for="llHlsEnabled">Low latency HLS</label>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="row" style="margin-top: 5px">
|
|
65
|
+
<div class="col-sm-12 text-center">
|
|
66
|
+
<a id="permalink" href="#">Permalink</a>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="row" style="margin-top: 10px">
|
|
70
|
+
<div class="col-sm-12 text-center">
|
|
71
|
+
<button id="applyBtn" type="button" class="btn btn-default">Play</button>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div class="row" style="margin-top: 10px">
|
|
76
|
+
<div class="col-sm-12" id="quality" style="display: none;">
|
|
77
|
+
<div class="col-sm-4 text-right">
|
|
78
|
+
<label class="form-check-label" for="qualityBtns">Quality</label>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="col-sm-8 text-center">
|
|
81
|
+
<div class="input-group-btn" id="qualityBtns">
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="row" style="margin-top: 10px">
|
|
87
|
+
<div class="col-sm-12" id="backward" style="display: none;">
|
|
88
|
+
<div class="col-sm-4 text-right">
|
|
89
|
+
<label class="form-check-label" for="backBtnMax">Rewind back</label>
|
|
90
|
+
</div>
|
|
91
|
+
<div class="col-sm-8 text-center">
|
|
56
92
|
<div class="input-group-btn">
|
|
57
93
|
<button id="backBtnMax" type="button" class="btn btn-default">Max</button>
|
|
58
94
|
<button id="backBtn30" type="button" class="btn btn-default">30</button>
|
|
@@ -61,15 +97,12 @@
|
|
|
61
97
|
</div>
|
|
62
98
|
</div>
|
|
63
99
|
</div>
|
|
64
|
-
<div class="col-sm-3 text-right">
|
|
65
|
-
<button id="applyBtn" type="button" class="btn btn-default">Play</button>
|
|
66
|
-
</div>
|
|
67
100
|
</div>
|
|
68
101
|
</fieldset>
|
|
69
102
|
</div>
|
|
70
103
|
</div>
|
|
71
104
|
<div class="row">
|
|
72
|
-
<div id="videoContainer"
|
|
105
|
+
<div id="videoContainer" style="margin-top: 20px; width: available; height: 56.25vw">
|
|
73
106
|
<video id="remoteVideo"
|
|
74
107
|
width="100%"
|
|
75
108
|
height="100%"
|