@flashphoner/websdk 2.0.243 → 2.0.244
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 +141 -28
- package/examples/demo/streaming/hls-native/hls-native.js +142 -33
- package/examples/demo/streaming/hls-player/hls-player.js +171 -63
- package/examples/demo/streaming/hls-player/player-page.html +21 -3
- package/package.json +1 -1
package/docTemplate/README.md
CHANGED
|
@@ -2,6 +2,9 @@ const Browser = Flashphoner.Browser;
|
|
|
2
2
|
const STATS_INTERVAL = 1000;
|
|
3
3
|
let remoteVideo = null;
|
|
4
4
|
let hlsPlayer = null;
|
|
5
|
+
let playSrc = getUrlParam("src");
|
|
6
|
+
let autoplay = eval(getUrlParam("autoplay")) || false;
|
|
7
|
+
let llHlsEnabled = eval(getUrlParam("llhls")) || false;
|
|
5
8
|
let playbackStats = null;
|
|
6
9
|
|
|
7
10
|
const loadPlayerPage = function() {
|
|
@@ -22,17 +25,37 @@ const loadPage = function(page, containerId, onLoad) {
|
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
const initPage = function() {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
if (playSrc) {
|
|
29
|
+
setValue("fullLink", decodeURIComponent(playSrc));
|
|
30
|
+
} else if (autoplay) {
|
|
31
|
+
console.warn("No HLS URL set, autoplay disabled");
|
|
32
|
+
autoplay = false;
|
|
33
|
+
}
|
|
34
|
+
if (llHlsEnabled) {
|
|
35
|
+
setCheckbox("llHlsEnabled", llHlsEnabled);
|
|
36
|
+
}
|
|
29
37
|
remoteVideo = document.getElementById('remoteVideo');
|
|
30
|
-
remoteVideo.style ="background-color: lightgrey;";
|
|
31
38
|
if (Hls.isSupported()) {
|
|
32
39
|
console.log("Using HLS.JS " + Hls.version);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
if (autoplay) {
|
|
41
|
+
// There should not be any visible item on the page unless player
|
|
42
|
+
hideAllToAutoplay();
|
|
43
|
+
// The player should use all available page width
|
|
44
|
+
setUpPlayerItem(true);
|
|
45
|
+
// The player should be muted to automatically start playback
|
|
46
|
+
initVideoPlayer(remoteVideo, true);
|
|
47
|
+
playBtnClick();
|
|
48
|
+
} else {
|
|
49
|
+
setText("header", "HLS.JS Player Minimal");
|
|
50
|
+
showItem("llHlsMode");
|
|
51
|
+
displayCommonItems();
|
|
52
|
+
setUpButtons();
|
|
53
|
+
enablePlaybackStats();
|
|
54
|
+
// The player should have a maximum fixed size
|
|
55
|
+
setUpPlayerItem(false);
|
|
56
|
+
// The player can be unmuted because user should click Play button
|
|
57
|
+
initVideoPlayer(remoteVideo, false);
|
|
58
|
+
}
|
|
36
59
|
} else {
|
|
37
60
|
setText("notifyFlash", "Your browser doesn't support MSE technology required to play video");
|
|
38
61
|
disableItem("applyBtn");
|
|
@@ -42,21 +65,18 @@ const initPage = function() {
|
|
|
42
65
|
|
|
43
66
|
|
|
44
67
|
const playBtnClick = function() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
streamName = encodeURIComponent(streamName);
|
|
49
|
-
let videoSrc = getValue("urlServer") + '/' + streamName + '/' + streamName + '.m3u8';
|
|
50
|
-
let key = getValue('key');
|
|
51
|
-
let token = getValue("token");
|
|
52
|
-
if (key.length > 0 && token.length > 0) {
|
|
53
|
-
videoSrc += "?" + key + "=" + token;
|
|
54
|
-
}
|
|
68
|
+
let videoSrc = getVideoSrc(getValue("fullLink"));
|
|
69
|
+
if (videoSrc) {
|
|
70
|
+
llHlsEnabled = getCheckbox("llHlsEnabled");
|
|
55
71
|
hlsPlayer = new Hls(getHlsConfig(llHlsEnabled));
|
|
56
72
|
hlsPlayer.on(Hls.Events.MANIFEST_PARSED, function() {
|
|
57
73
|
console.log("Play with HLS.js");
|
|
58
74
|
remoteVideo.play();
|
|
59
75
|
});
|
|
76
|
+
remoteVideo.onplaying = () => {
|
|
77
|
+
console.log("playing event fired");
|
|
78
|
+
displayPermalink(videoSrc);
|
|
79
|
+
}
|
|
60
80
|
hlsPlayer.loadSource(videoSrc);
|
|
61
81
|
hlsPlayer.attachMedia(remoteVideo);
|
|
62
82
|
onStarted();
|
|
@@ -108,20 +128,25 @@ const stopBtnClick = function() {
|
|
|
108
128
|
|
|
109
129
|
|
|
110
130
|
const onStarted = function() {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
131
|
+
if (!autoplay) {
|
|
132
|
+
toggleInputs(false);
|
|
133
|
+
enableItem("applyBtn");
|
|
134
|
+
hideItem("permalink");
|
|
135
|
+
setText("applyBtn", "Stop");
|
|
136
|
+
setHandler("applyBtn", "click", stopBtnClick, playBtnClick);
|
|
137
|
+
startPlaybackStats();
|
|
138
|
+
}
|
|
116
139
|
}
|
|
117
140
|
|
|
118
141
|
|
|
119
142
|
function onStopped() {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
143
|
+
if (!autoplay) {
|
|
144
|
+
toggleInputs(true);
|
|
145
|
+
enableItem("applyBtn");
|
|
146
|
+
setText("applyBtn", "Play");
|
|
147
|
+
setHandler("applyBtn", "click", playBtnClick, stopBtnClick);
|
|
148
|
+
stopPlaybackStats();
|
|
149
|
+
}
|
|
125
150
|
}
|
|
126
151
|
|
|
127
152
|
|
|
@@ -166,6 +191,18 @@ const removeHighlight = function(input) {
|
|
|
166
191
|
}
|
|
167
192
|
}
|
|
168
193
|
|
|
194
|
+
const initVideoPlayer = function(video, muted) {
|
|
195
|
+
if (video) {
|
|
196
|
+
video.style.backgroundColor = "black";
|
|
197
|
+
video.muted = muted;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const setUpButtons = function() {
|
|
202
|
+
setHandler("applyBtn", "click", playBtnClick);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
|
|
169
206
|
const toggleInputs = function(enable) {
|
|
170
207
|
if (enable) {
|
|
171
208
|
enableItem("urlServer");
|
|
@@ -184,6 +221,82 @@ const toggleInputs = function(enable) {
|
|
|
184
221
|
}
|
|
185
222
|
}
|
|
186
223
|
|
|
224
|
+
const getVideoSrc = function(src) {
|
|
225
|
+
let videoSrc = src;
|
|
226
|
+
if (validateForm()) {
|
|
227
|
+
let streamName = getValue('playStream');
|
|
228
|
+
streamName = encodeURIComponent(streamName);
|
|
229
|
+
videoSrc = getValue("urlServer") + '/' + streamName + '/' + streamName + '.m3u8';
|
|
230
|
+
let key = getValue('key');
|
|
231
|
+
let token = getValue("token");
|
|
232
|
+
if (key.length > 0 && token.length > 0) {
|
|
233
|
+
videoSrc += "?" + key + "=" + token;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
setValue("fullLink", videoSrc);
|
|
237
|
+
return videoSrc;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const displayPermalink = function(src) {
|
|
241
|
+
if (!autoplay) {
|
|
242
|
+
const permalinkId = "permalink";
|
|
243
|
+
let videoSrc = encodeURIComponent(src);
|
|
244
|
+
let linkObject = document.getElementById(permalinkId);
|
|
245
|
+
let href = window.location.href.split("?")[0] + "?llhls=" + llHlsEnabled + "&src=" + videoSrc;
|
|
246
|
+
linkObject.href = href;
|
|
247
|
+
showItem(permalinkId);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const hideAllToAutoplay = function() {
|
|
252
|
+
hideItem("header");
|
|
253
|
+
hideItem("notifyFlash");
|
|
254
|
+
hideItem("fieldset");
|
|
255
|
+
hideItem("stats");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const displayCommonItems = function() {
|
|
259
|
+
setValue("urlServer", getHLSUrl());
|
|
260
|
+
hideItem("permalink");
|
|
261
|
+
enableItem("applyBtn");
|
|
262
|
+
setText("applyBtn", "Play");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const setUpPlayerItem = function(fillPage) {
|
|
266
|
+
let videoContainer = document.getElementById('videoContainer');
|
|
267
|
+
let playerPage = document.getElementById('playerPage');
|
|
268
|
+
|
|
269
|
+
if (fillPage) {
|
|
270
|
+
playerPage.classList.remove("container");
|
|
271
|
+
videoContainer.style.marginTop = "0px";
|
|
272
|
+
videoContainer.style.width = "100vw";
|
|
273
|
+
videoContainer.style.height = "100vh";
|
|
274
|
+
videoContainer.style.maxWidth = "available";
|
|
275
|
+
videoContainer.style.maxHeight = "available";
|
|
276
|
+
} else {
|
|
277
|
+
videoContainer.style.maxWidth = "852px";
|
|
278
|
+
videoContainer.style.maxHeight = "480px";
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const enablePlaybackStats = function() {
|
|
283
|
+
if (!autoplay && !playbackStats) {
|
|
284
|
+
playbackStats = PlaybackStats(STATS_INTERVAL);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const startPlaybackStats = function() {
|
|
289
|
+
if (!autoplay && playbackStats) {
|
|
290
|
+
playbackStats.start();
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const stopPlaybackStats = function() {
|
|
295
|
+
if (!autoplay && playbackStats) {
|
|
296
|
+
playbackStats.stop();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
187
300
|
const PlaybackStats = function(interval) {
|
|
188
301
|
const playbackStats = {
|
|
189
302
|
interval: interval || STATS_INTERVAL,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const Browser = Flashphoner.Browser;
|
|
2
2
|
const STATS_INTERVAL = 1000;
|
|
3
3
|
let remoteVideo = null;
|
|
4
|
+
let playSrc = getUrlParam("src");
|
|
5
|
+
let autoplay = eval(getUrlParam("autoplay")) || false;
|
|
4
6
|
let playbackStats = null;
|
|
5
7
|
|
|
6
8
|
const loadPlayerPage = function() {
|
|
@@ -21,19 +23,33 @@ const loadPage = function(page, containerId, onLoad) {
|
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
const initPage = function() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
remoteVideo.style ="background-color: lightgrey;";
|
|
30
|
-
if (Browser.isSafariWebRTC() && Browser.isiOS()) {
|
|
31
|
-
// iOS hack when using standard controls to leave fullscreen mode
|
|
32
|
-
setWebkitFullscreenHandlers(remoteVideo);
|
|
26
|
+
if (playSrc) {
|
|
27
|
+
setValue("fullLink", decodeURIComponent(playSrc));
|
|
28
|
+
} else if (autoplay) {
|
|
29
|
+
console.warn("No HLS URL set, autoplay disabled");
|
|
30
|
+
autoplay = false;
|
|
33
31
|
}
|
|
32
|
+
remoteVideo = document.getElementById('remoteVideo');
|
|
34
33
|
if (remoteVideo.canPlayType('application/vnd.apple.mpegurl') && Browser.isSafariWebRTC()) {
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
console.log("Using Native HLS player");
|
|
35
|
+
if (autoplay) {
|
|
36
|
+
// There should not be any visible item on the page unless player
|
|
37
|
+
hideAllToAutoplay();
|
|
38
|
+
// The player should use all available page width
|
|
39
|
+
setUpPlayerItem(true);
|
|
40
|
+
// The player should be muted to automatically start playback
|
|
41
|
+
initVideoPlayer(remoteVideo, true);
|
|
42
|
+
playBtnClick();
|
|
43
|
+
} else {
|
|
44
|
+
setText("header", "HLS Native Player Minimal");
|
|
45
|
+
displayCommonItems();
|
|
46
|
+
setUpButtons();
|
|
47
|
+
enablePlaybackStats();
|
|
48
|
+
// The player should have a maximum fixed size
|
|
49
|
+
setUpPlayerItem(false);
|
|
50
|
+
// The player can be unmuted because user should click Play button
|
|
51
|
+
initVideoPlayer(remoteVideo, false);
|
|
52
|
+
}
|
|
37
53
|
} else {
|
|
38
54
|
setText("notifyFlash", "Your browser doesn't support native HLS playback");
|
|
39
55
|
disableItem("applyBtn");
|
|
@@ -42,21 +58,18 @@ const initPage = function() {
|
|
|
42
58
|
}
|
|
43
59
|
|
|
44
60
|
const playBtnClick = function() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
let videoSrc = getValue("urlServer") + '/' + streamName + '/' + streamName + '.m3u8';
|
|
49
|
-
let key = getValue('key');
|
|
50
|
-
let token = getValue("token");
|
|
51
|
-
if (key.length > 0 && token.length > 0) {
|
|
52
|
-
videoSrc += "?" + key + "=" + token;
|
|
53
|
-
}
|
|
54
|
-
remoteVideo.src = videoSrc;
|
|
55
|
-
remoteVideo.addEventListener('loadedmetadata', function() {
|
|
61
|
+
let videoSrc = getVideoSrc(getValue("fullLink"));
|
|
62
|
+
if (videoSrc) {
|
|
63
|
+
remoteVideo.onloadedmetadata = () => {
|
|
56
64
|
console.log("Play native HLS");
|
|
57
65
|
remoteVideo.play();
|
|
58
66
|
onStarted();
|
|
59
|
-
}
|
|
67
|
+
};
|
|
68
|
+
remoteVideo.onplaying = () => {
|
|
69
|
+
console.log("playing event fired");
|
|
70
|
+
displayPermalink(videoSrc);
|
|
71
|
+
};
|
|
72
|
+
remoteVideo.src = videoSrc;
|
|
60
73
|
}
|
|
61
74
|
}
|
|
62
75
|
|
|
@@ -74,20 +87,25 @@ const stopBtnClick = function() {
|
|
|
74
87
|
|
|
75
88
|
|
|
76
89
|
const onStarted = function() {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
90
|
+
if (!autoplay) {
|
|
91
|
+
toggleInputs(false);
|
|
92
|
+
enableItem("applyBtn");
|
|
93
|
+
hideItem("permalink");
|
|
94
|
+
setText("applyBtn", "Stop");
|
|
95
|
+
setHandler("applyBtn", "click", stopBtnClick, playBtnClick);
|
|
96
|
+
startPlaybackStats();
|
|
97
|
+
}
|
|
82
98
|
}
|
|
83
99
|
|
|
84
100
|
|
|
85
101
|
const onStopped = function() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
if (!autoplay) {
|
|
103
|
+
toggleInputs(true);
|
|
104
|
+
enableItem("applyBtn");
|
|
105
|
+
setText("applyBtn", "Play");
|
|
106
|
+
setHandler("applyBtn", "click", playBtnClick, stopBtnClick);
|
|
107
|
+
stopPlaybackStats();
|
|
108
|
+
}
|
|
91
109
|
}
|
|
92
110
|
|
|
93
111
|
|
|
@@ -132,6 +150,21 @@ const removeHighlight = function(input) {
|
|
|
132
150
|
}
|
|
133
151
|
}
|
|
134
152
|
|
|
153
|
+
const initVideoPlayer = function(video, muted) {
|
|
154
|
+
if (video) {
|
|
155
|
+
video.style.backgroundColor = "black";
|
|
156
|
+
video.muted = muted;
|
|
157
|
+
if (Browser.isiOS()) {
|
|
158
|
+
// iOS hack when using standard controls to leave fullscreen mode
|
|
159
|
+
setWebkitFullscreenHandlers(video);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const setUpButtons = function() {
|
|
165
|
+
setHandler("applyBtn", "click", playBtnClick);
|
|
166
|
+
}
|
|
167
|
+
|
|
135
168
|
const toggleInputs = function(enable) {
|
|
136
169
|
if (enable) {
|
|
137
170
|
enableItem("urlServer");
|
|
@@ -148,6 +181,82 @@ const toggleInputs = function(enable) {
|
|
|
148
181
|
}
|
|
149
182
|
}
|
|
150
183
|
|
|
184
|
+
const getVideoSrc = function(src) {
|
|
185
|
+
let videoSrc = src;
|
|
186
|
+
if (validateForm()) {
|
|
187
|
+
let streamName = getValue('playStream');
|
|
188
|
+
streamName = encodeURIComponent(streamName);
|
|
189
|
+
videoSrc = getValue("urlServer") + '/' + streamName + '/' + streamName + '.m3u8';
|
|
190
|
+
let key = getValue('key');
|
|
191
|
+
let token = getValue("token");
|
|
192
|
+
if (key.length > 0 && token.length > 0) {
|
|
193
|
+
videoSrc += "?" + key + "=" + token;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
setValue("fullLink", videoSrc);
|
|
197
|
+
return videoSrc;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const displayPermalink = function(src) {
|
|
201
|
+
if (!autoplay) {
|
|
202
|
+
const permalinkId = "permalink";
|
|
203
|
+
let videoSrc = encodeURIComponent(src);
|
|
204
|
+
let linkObject = document.getElementById(permalinkId);
|
|
205
|
+
let href = window.location.href.split("?")[0] + "?src=" + videoSrc;
|
|
206
|
+
linkObject.href = href;
|
|
207
|
+
showItem(permalinkId);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const hideAllToAutoplay = function() {
|
|
212
|
+
hideItem("header");
|
|
213
|
+
hideItem("notifyFlash");
|
|
214
|
+
hideItem("fieldset");
|
|
215
|
+
hideItem("stats");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const displayCommonItems = function() {
|
|
219
|
+
setValue("urlServer", getHLSUrl());
|
|
220
|
+
hideItem("permalink");
|
|
221
|
+
enableItem("applyBtn");
|
|
222
|
+
setText("applyBtn", "Play");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const setUpPlayerItem = function(fillPage) {
|
|
226
|
+
let videoContainer = document.getElementById('videoContainer');
|
|
227
|
+
let playerPage = document.getElementById('playerPage');
|
|
228
|
+
|
|
229
|
+
if (fillPage) {
|
|
230
|
+
playerPage.classList.remove("container");
|
|
231
|
+
videoContainer.style.marginTop = "0px";
|
|
232
|
+
videoContainer.style.width = "100vw";
|
|
233
|
+
videoContainer.style.height = "100vh";
|
|
234
|
+
videoContainer.style.maxWidth = "available";
|
|
235
|
+
videoContainer.style.maxHeight = "available";
|
|
236
|
+
} else {
|
|
237
|
+
videoContainer.style.maxWidth = "852px";
|
|
238
|
+
videoContainer.style.maxHeight = "480px";
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const enablePlaybackStats = function() {
|
|
243
|
+
if (!autoplay && !playbackStats) {
|
|
244
|
+
playbackStats = PlaybackStats(STATS_INTERVAL);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const startPlaybackStats = function() {
|
|
249
|
+
if (!autoplay && playbackStats) {
|
|
250
|
+
playbackStats.start();
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const stopPlaybackStats = function() {
|
|
255
|
+
if (!autoplay && playbackStats) {
|
|
256
|
+
playbackStats.stop();
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
151
260
|
const PlaybackStats = function(interval) {
|
|
152
261
|
const playbackStats = {
|
|
153
262
|
interval: interval || STATS_INTERVAL,
|
|
@@ -10,13 +10,19 @@ const STATS_INTERVAL = 1000;
|
|
|
10
10
|
let player = null;
|
|
11
11
|
let liveUITimer = null;
|
|
12
12
|
let videojsVersion = getUrlParam("version");
|
|
13
|
+
let playSrc = getUrlParam("src");
|
|
14
|
+
let autoplay = eval(getUrlParam("autoplay")) || false;
|
|
13
15
|
let playbackStats = null;
|
|
14
16
|
|
|
15
17
|
const loadPlayerPage = function() {
|
|
16
18
|
if (videojsVersion) {
|
|
17
19
|
hideItem("videojsInputForm");
|
|
18
|
-
loadVideoJS(
|
|
20
|
+
loadVideoJS(videojsVersion);
|
|
19
21
|
} else {
|
|
22
|
+
if (autoplay) {
|
|
23
|
+
console.warn("No VideoJS version set, autoplay disabled");
|
|
24
|
+
autoplay = false;
|
|
25
|
+
}
|
|
20
26
|
let videojsInput = document.getElementById("videojsInput");
|
|
21
27
|
for (videojsType in VIDEOJS_VERSION_TYPE) {
|
|
22
28
|
let option = document.createElement("option");
|
|
@@ -44,13 +50,14 @@ const onVideojsBtnClick = function () {
|
|
|
44
50
|
|
|
45
51
|
const loadVideoJS = function (version) {
|
|
46
52
|
if (version) {
|
|
53
|
+
videojsVersion = version;
|
|
47
54
|
let playerPage = document.getElementById("playerPage");
|
|
48
55
|
loadFile(version + "/video.js", "text/javascript").then( data => {
|
|
49
56
|
console.log("HLS library loaded successfully", data);
|
|
50
57
|
loadFile(version + "/video-js.css", "stylesheet").then ( data => {
|
|
51
58
|
console.log("HLS library stylesheet loaded successfully", data);
|
|
52
59
|
hideItem("videojsInputForm");
|
|
53
|
-
loadPage("player-page.html", "playerPage", initPage
|
|
60
|
+
loadPage("player-page.html", "playerPage", initPage);
|
|
54
61
|
}).catch( err => {
|
|
55
62
|
playerPage.innerHTML = "Can't load VideoJS library stylesheet";
|
|
56
63
|
playerPage.setAttribute("class", "text-danger");
|
|
@@ -117,31 +124,37 @@ const loadPage = function(page, containerId, onLoad) {
|
|
|
117
124
|
}
|
|
118
125
|
|
|
119
126
|
const initPage = function() {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
setHandler("backBtn30", "click", backBtnClick);
|
|
127
|
-
setHandler("backBtnMax", "click", backBtnClick);
|
|
128
|
-
setHandler("liveBtn", "click", liveBtnClick);
|
|
127
|
+
if (playSrc) {
|
|
128
|
+
setValue("fullLink", decodeURIComponent(playSrc));
|
|
129
|
+
} else if (autoplay) {
|
|
130
|
+
console.warn("No HLS URL set, autoplay disabled");
|
|
131
|
+
autoplay = false;
|
|
132
|
+
}
|
|
129
133
|
let remoteVideo = document.getElementById('remoteVideo');
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
if (autoplay) {
|
|
135
|
+
// There should not be any visible item on the page unless player
|
|
136
|
+
hideAllToAutoplay();
|
|
137
|
+
// The player should use all available page width
|
|
138
|
+
setUpPlayerItem(true);
|
|
139
|
+
// The player should be muted to automatically start playback
|
|
140
|
+
player = initVideoJsPlayer(remoteVideo, true);
|
|
141
|
+
playBtnClick();
|
|
142
|
+
} else {
|
|
143
|
+
// No autoplay, all the forms and buttons should be visible
|
|
144
|
+
setText("header", "HLS VideoJS Player Minimal");
|
|
145
|
+
displayCommonItems();
|
|
146
|
+
setUpButtons();
|
|
147
|
+
enablePlaybackStats();
|
|
148
|
+
// The player should have a maximum fixed size
|
|
149
|
+
setUpPlayerItem(false);
|
|
150
|
+
// The player can be unmuted because user should click Play button
|
|
151
|
+
player = initVideoJsPlayer(remoteVideo, false);
|
|
152
|
+
}
|
|
133
153
|
}
|
|
134
154
|
|
|
135
155
|
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
|
-
}
|
|
156
|
+
let videoSrc = getVideoSrc(getValue("fullLink"));
|
|
157
|
+
if (videoSrc) {
|
|
145
158
|
player.on('loadedmetadata', function() {
|
|
146
159
|
console.log("Play with VideoJs");
|
|
147
160
|
player.play();
|
|
@@ -157,6 +170,7 @@ const playBtnClick = function() {
|
|
|
157
170
|
});
|
|
158
171
|
player.on('playing', function() {
|
|
159
172
|
console.log("playing event fired");
|
|
173
|
+
displayPermalink(videoSrc);
|
|
160
174
|
if (player.liveTracker) {
|
|
161
175
|
if (!player.liveTracker.isLive()) {
|
|
162
176
|
// A cratch to display live UI for the first subscriber
|
|
@@ -231,23 +245,27 @@ const liveBtnClick = function() {
|
|
|
231
245
|
}
|
|
232
246
|
|
|
233
247
|
const onStarted = function() {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
248
|
+
if (!autoplay) {
|
|
249
|
+
toggleInputs(false);
|
|
250
|
+
enableItem("applyBtn");
|
|
251
|
+
hideItem("permalink");
|
|
252
|
+
showItem("backward");
|
|
253
|
+
setText("applyBtn", "Stop");
|
|
254
|
+
setHandler("applyBtn", "click", stopBtnClick, playBtnClick);
|
|
255
|
+
startPlaybackStats();
|
|
256
|
+
}
|
|
241
257
|
}
|
|
242
258
|
|
|
243
259
|
|
|
244
260
|
const onStopped = function() {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
261
|
+
if (!autoplay) {
|
|
262
|
+
toggleInputs(true);
|
|
263
|
+
enableItem("applyBtn");
|
|
264
|
+
hideItem("backward");
|
|
265
|
+
setText("applyBtn", "Play");
|
|
266
|
+
setHandler("applyBtn", "click", playBtnClick, stopBtnClick);
|
|
267
|
+
stopPlaybackStats();
|
|
268
|
+
}
|
|
251
269
|
if(!document.getElementById('remoteVideo')) {
|
|
252
270
|
createRemoteVideo(document.getElementById('videoContainer'));
|
|
253
271
|
}
|
|
@@ -264,7 +282,7 @@ const createRemoteVideo = function(parent) {
|
|
|
264
282
|
remoteVideo.setAttribute("playsinline","");
|
|
265
283
|
remoteVideo.setAttribute("webkit-playsinline","");
|
|
266
284
|
parent.appendChild(remoteVideo);
|
|
267
|
-
player = initVideoJsPlayer(remoteVideo);
|
|
285
|
+
player = initVideoJsPlayer(remoteVideo, autoplay);
|
|
268
286
|
}
|
|
269
287
|
|
|
270
288
|
|
|
@@ -309,23 +327,28 @@ const removeHighlight = function(input) {
|
|
|
309
327
|
}
|
|
310
328
|
}
|
|
311
329
|
|
|
312
|
-
const initVideoJsPlayer = function(video) {
|
|
313
|
-
let videoJsPlayer =
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
330
|
+
const initVideoJsPlayer = function(video, muted) {
|
|
331
|
+
let videoJsPlayer = null;
|
|
332
|
+
if (video) {
|
|
333
|
+
video.className = "video-js vjs-default-skin";
|
|
334
|
+
videoJsPlayer = videojs(video, {
|
|
335
|
+
playsinline: true,
|
|
336
|
+
playbackRates: [0.1, 0.25, 0.5, 1, 1.5, 2],
|
|
337
|
+
liveui: true,
|
|
338
|
+
liveTracker: {
|
|
339
|
+
trackingThreshold: LIVE_THRESHOLD,
|
|
340
|
+
liveTolerance: LIVE_TOLERANCE
|
|
341
|
+
},
|
|
342
|
+
fill: true,
|
|
343
|
+
muted: muted
|
|
344
|
+
});
|
|
345
|
+
console.log("Using VideoJs " + videojs.VERSION);
|
|
346
|
+
if (Browser.isSafariWebRTC() && Browser.isiOS()) {
|
|
347
|
+
// iOS hack when using standard controls to leave fullscreen mode
|
|
348
|
+
let videoTag = getActualVideoTag();
|
|
349
|
+
if(videoTag) {
|
|
350
|
+
setWebkitFullscreenHandlers(videoTag, false);
|
|
351
|
+
}
|
|
329
352
|
}
|
|
330
353
|
}
|
|
331
354
|
return videoJsPlayer;
|
|
@@ -339,15 +362,25 @@ const getActualVideoTag = function() {
|
|
|
339
362
|
return null;
|
|
340
363
|
}
|
|
341
364
|
|
|
365
|
+
const setUpButtons = function() {
|
|
366
|
+
setHandler("applyBtn", "click", playBtnClick);
|
|
367
|
+
setHandler("backBtn10", "click", backBtnClick);
|
|
368
|
+
setHandler("backBtn30", "click", backBtnClick);
|
|
369
|
+
setHandler("backBtnMax", "click", backBtnClick);
|
|
370
|
+
setHandler("liveBtn", "click", liveBtnClick);
|
|
371
|
+
}
|
|
372
|
+
|
|
342
373
|
const toggleBackButtons = function(enable) {
|
|
343
|
-
if (
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
374
|
+
if (!autoplay) {
|
|
375
|
+
if (enable) {
|
|
376
|
+
enableItem("backBtn10");
|
|
377
|
+
enableItem("backBtn30");
|
|
378
|
+
enableItem("backBtnMax");
|
|
379
|
+
} else {
|
|
380
|
+
disableItem("backBtn10");
|
|
381
|
+
disableItem("backBtn30");
|
|
382
|
+
disableItem("backBtnMax");
|
|
383
|
+
}
|
|
351
384
|
}
|
|
352
385
|
}
|
|
353
386
|
|
|
@@ -367,6 +400,82 @@ const toggleInputs = function(enable) {
|
|
|
367
400
|
}
|
|
368
401
|
}
|
|
369
402
|
|
|
403
|
+
const getVideoSrc = function(src) {
|
|
404
|
+
let videoSrc = src;
|
|
405
|
+
if (validateForm()) {
|
|
406
|
+
let streamName = getValue('playStream');
|
|
407
|
+
streamName = encodeURIComponent(streamName);
|
|
408
|
+
videoSrc = getValue("urlServer") + '/' + streamName + '/' + streamName + '.m3u8';
|
|
409
|
+
let key = getValue('key');
|
|
410
|
+
let token = getValue("token");
|
|
411
|
+
if (key.length > 0 && token.length > 0) {
|
|
412
|
+
videoSrc += "?" + key + "=" + token;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
setValue("fullLink", videoSrc);
|
|
416
|
+
return videoSrc;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const displayPermalink = function(src) {
|
|
420
|
+
if (!autoplay) {
|
|
421
|
+
const permalinkId = "permalink";
|
|
422
|
+
let videoSrc = encodeURIComponent(src);
|
|
423
|
+
let linkObject = document.getElementById(permalinkId);
|
|
424
|
+
let href = window.location.href.split("?")[0] + "?version=" + videojsVersion + "&src=" + videoSrc;
|
|
425
|
+
linkObject.href = href;
|
|
426
|
+
showItem(permalinkId);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const hideAllToAutoplay = function() {
|
|
431
|
+
hideItem("header");
|
|
432
|
+
hideItem("notifyFlash");
|
|
433
|
+
hideItem("fieldset");
|
|
434
|
+
hideItem("stats");
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const displayCommonItems = function() {
|
|
438
|
+
setValue("urlServer", getHLSUrl());
|
|
439
|
+
hideItem("permalink");
|
|
440
|
+
enableItem("applyBtn");
|
|
441
|
+
setText("applyBtn", "Play");
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const setUpPlayerItem = function(fillPage) {
|
|
445
|
+
let videoContainer = document.getElementById('videoContainer');
|
|
446
|
+
let playerPage = document.getElementById('playerPage');
|
|
447
|
+
|
|
448
|
+
if (fillPage) {
|
|
449
|
+
playerPage.classList.remove("container");
|
|
450
|
+
videoContainer.style.marginTop = "0px";
|
|
451
|
+
videoContainer.style.width = "100vw";
|
|
452
|
+
videoContainer.style.height = "100vh";
|
|
453
|
+
videoContainer.style.maxWidth = "available";
|
|
454
|
+
videoContainer.style.maxHeight = "available";
|
|
455
|
+
} else {
|
|
456
|
+
videoContainer.style.maxWidth = "852px";
|
|
457
|
+
videoContainer.style.maxHeight = "480px";
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const enablePlaybackStats = function() {
|
|
462
|
+
if (!autoplay && !playbackStats) {
|
|
463
|
+
playbackStats = PlaybackStats(STATS_INTERVAL);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const startPlaybackStats = function() {
|
|
468
|
+
if (!autoplay && playbackStats) {
|
|
469
|
+
playbackStats.start();
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
const stopPlaybackStats = function() {
|
|
474
|
+
if (!autoplay && playbackStats) {
|
|
475
|
+
playbackStats.stop();
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
370
479
|
const PlaybackStats = function(interval) {
|
|
371
480
|
const playbackStats = {
|
|
372
481
|
interval: interval || STATS_INTERVAL,
|
|
@@ -374,7 +483,6 @@ const PlaybackStats = function(interval) {
|
|
|
374
483
|
stats: null,
|
|
375
484
|
start: function() {
|
|
376
485
|
let video = getActualVideoTag();
|
|
377
|
-
|
|
378
486
|
playbackStats.stop();
|
|
379
487
|
stats = HTML5Stats(video);
|
|
380
488
|
playbackStats.timer = setInterval(playbackStats.displayStats, playbackStats.interval);
|
|
@@ -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,6 +43,24 @@
|
|
|
43
43
|
</div>
|
|
44
44
|
</div>
|
|
45
45
|
</div>
|
|
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"/>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="row" style="margin-top:10px">
|
|
59
|
+
<div class="col-sm-12 text-center">
|
|
60
|
+
<a id="permalink" href="#">Permalink</a>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
46
64
|
<div class="row" style="margin-top: 20px">
|
|
47
65
|
<div class="col-sm-4 text-left">
|
|
48
66
|
<div id="llHlsMode" style="display: none;">
|
|
@@ -69,7 +87,7 @@
|
|
|
69
87
|
</div>
|
|
70
88
|
</div>
|
|
71
89
|
<div class="row">
|
|
72
|
-
<div id="videoContainer"
|
|
90
|
+
<div id="videoContainer" style="margin-top: 20px; width: available; height: 56.25vw">
|
|
73
91
|
<video id="remoteVideo"
|
|
74
92
|
width="100%"
|
|
75
93
|
height="100%"
|