@flashphoner/websdk 2.0.242 → 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.
@@ -6,15 +6,23 @@ const VIDEOJS_VERSION_TYPE = {
6
6
  const LIVE_THRESHOLD = 5;
7
7
  const LIVE_TOLERANCE = 5;
8
8
  const LIVE_UI_INTERVAL = 1000;
9
+ const STATS_INTERVAL = 1000;
9
10
  let player = null;
10
11
  let liveUITimer = null;
11
12
  let videojsVersion = getUrlParam("version");
13
+ let playSrc = getUrlParam("src");
14
+ let autoplay = eval(getUrlParam("autoplay")) || false;
15
+ let playbackStats = null;
12
16
 
13
17
  const loadPlayerPage = function() {
14
18
  if (videojsVersion) {
15
19
  hideItem("videojsInputForm");
16
- loadVideoJS("videojs" + videojsVersion);
20
+ loadVideoJS(videojsVersion);
17
21
  } else {
22
+ if (autoplay) {
23
+ console.warn("No VideoJS version set, autoplay disabled");
24
+ autoplay = false;
25
+ }
18
26
  let videojsInput = document.getElementById("videojsInput");
19
27
  for (videojsType in VIDEOJS_VERSION_TYPE) {
20
28
  let option = document.createElement("option");
@@ -42,13 +50,14 @@ const onVideojsBtnClick = function () {
42
50
 
43
51
  const loadVideoJS = function (version) {
44
52
  if (version) {
53
+ videojsVersion = version;
45
54
  let playerPage = document.getElementById("playerPage");
46
55
  loadFile(version + "/video.js", "text/javascript").then( data => {
47
56
  console.log("HLS library loaded successfully", data);
48
57
  loadFile(version + "/video-js.css", "stylesheet").then ( data => {
49
58
  console.log("HLS library stylesheet loaded successfully", data);
50
59
  hideItem("videojsInputForm");
51
- loadPage("player-page.html", "playerPage", initPage );
60
+ loadPage("player-page.html", "playerPage", initPage);
52
61
  }).catch( err => {
53
62
  playerPage.innerHTML = "Can't load VideoJS library stylesheet";
54
63
  playerPage.setAttribute("class", "text-danger");
@@ -115,30 +124,37 @@ const loadPage = function(page, containerId, onLoad) {
115
124
  }
116
125
 
117
126
  const initPage = function() {
118
- setText("header", "HLS VideoJS Player Minimal");
119
- setValue("urlServer", getHLSUrl());
120
- enableItem("applyBtn");
121
- setText("applyBtn", "Play");
122
- setHandler("applyBtn", "click", playBtnClick);
123
- setHandler("backBtn10", "click", backBtnClick);
124
- setHandler("backBtn30", "click", backBtnClick);
125
- setHandler("backBtnMax", "click", backBtnClick);
126
- 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
+ }
127
133
  let remoteVideo = document.getElementById('remoteVideo');
128
- remoteVideo.className = "video-js vjs-default-skin";
129
- player = initVideoJsPlayer(remoteVideo);
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
+ }
130
153
  }
131
154
 
132
155
  const playBtnClick = function() {
133
- if (validateForm()) {
134
- let streamName = getValue('playStream');
135
- streamName = encodeURIComponent(streamName);
136
- let videoSrc = getValue("urlServer") + '/' + streamName + '/' + streamName + '.m3u8';
137
- let key = getValue('key');
138
- let token = getValue("token");
139
- if (key.length > 0 && token.length > 0) {
140
- videoSrc += "?" + key + "=" + token;
141
- }
156
+ let videoSrc = getVideoSrc(getValue("fullLink"));
157
+ if (videoSrc) {
142
158
  player.on('loadedmetadata', function() {
143
159
  console.log("Play with VideoJs");
144
160
  player.play();
@@ -154,6 +170,7 @@ const playBtnClick = function() {
154
170
  });
155
171
  player.on('playing', function() {
156
172
  console.log("playing event fired");
173
+ displayPermalink(videoSrc);
157
174
  if (player.liveTracker) {
158
175
  if (!player.liveTracker.isLive()) {
159
176
  // A cratch to display live UI for the first subscriber
@@ -228,21 +245,27 @@ const liveBtnClick = function() {
228
245
  }
229
246
 
230
247
  const onStarted = function() {
231
- toggleInputs(false);
232
- enableItem("applyBtn");
233
- showItem("backward");
234
- toggleBackButtons(true);
235
- setText("applyBtn", "Stop");
236
- setHandler("applyBtn", "click", stopBtnClick, playBtnClick);
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
+ }
237
257
  }
238
258
 
239
259
 
240
260
  const onStopped = function() {
241
- toggleInputs(true);
242
- enableItem("applyBtn");
243
- hideItem("backward");
244
- setText("applyBtn", "Play");
245
- setHandler("applyBtn", "click", playBtnClick, stopBtnClick);
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
+ }
246
269
  if(!document.getElementById('remoteVideo')) {
247
270
  createRemoteVideo(document.getElementById('videoContainer'));
248
271
  }
@@ -250,10 +273,8 @@ const onStopped = function() {
250
273
 
251
274
 
252
275
  const createRemoteVideo = function(parent) {
253
- remoteVideo = document.createElement("video");
276
+ let remoteVideo = document.createElement("video");
254
277
  remoteVideo.id = "remoteVideo";
255
- remoteVideo.width=852;
256
- remoteVideo.height=480;
257
278
  remoteVideo.controls="controls";
258
279
  remoteVideo.autoplay="autoplay";
259
280
  remoteVideo.type="application/vnd.apple.mpegurl";
@@ -261,7 +282,7 @@ const createRemoteVideo = function(parent) {
261
282
  remoteVideo.setAttribute("playsinline","");
262
283
  remoteVideo.setAttribute("webkit-playsinline","");
263
284
  parent.appendChild(remoteVideo);
264
- player = initVideoJsPlayer(remoteVideo);
285
+ player = initVideoJsPlayer(remoteVideo, autoplay);
265
286
  }
266
287
 
267
288
 
@@ -306,22 +327,28 @@ const removeHighlight = function(input) {
306
327
  }
307
328
  }
308
329
 
309
- const initVideoJsPlayer = function(video) {
310
- let videoJsPlayer = videojs(video, {
311
- playsinline: true,
312
- playbackRates: [0.1, 0.25, 0.5, 1, 1.5, 2],
313
- liveui: true,
314
- liveTracker: {
315
- trackingThreshold: LIVE_THRESHOLD,
316
- liveTolerance: LIVE_TOLERANCE
317
- }
318
- });
319
- console.log("Using VideoJs " + videojs.VERSION);
320
- if (Browser.isSafariWebRTC() && Browser.isiOS()) {
321
- // iOS hack when using standard controls to leave fullscreen mode
322
- let videoTag = getActualVideoTag();
323
- if(videoTag) {
324
- setWebkitFullscreenHandlers(videoTag, false);
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
+ }
325
352
  }
326
353
  }
327
354
  return videoJsPlayer;
@@ -335,15 +362,25 @@ const getActualVideoTag = function() {
335
362
  return null;
336
363
  }
337
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
+
338
373
  const toggleBackButtons = function(enable) {
339
- if (enable) {
340
- enableItem("backBtn10");
341
- enableItem("backBtn30");
342
- enableItem("backBtnMax");
343
- } else {
344
- disableItem("backBtn10");
345
- disableItem("backBtn30");
346
- disableItem("backBtnMax");
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
+ }
347
384
  }
348
385
  }
349
386
 
@@ -361,4 +398,126 @@ const toggleInputs = function(enable) {
361
398
  disableItem("token");
362
399
  disableItem("player");
363
400
  }
401
+ }
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
+
479
+ const PlaybackStats = function(interval) {
480
+ const playbackStats = {
481
+ interval: interval || STATS_INTERVAL,
482
+ timer: null,
483
+ stats: null,
484
+ start: function() {
485
+ let video = getActualVideoTag();
486
+ playbackStats.stop();
487
+ stats = HTML5Stats(video);
488
+ playbackStats.timer = setInterval(playbackStats.displayStats, playbackStats.interval);
489
+ setText("videoWidth", "N/A");
490
+ setText("videoHeight", "N/A");
491
+ setText("videoRate", "N/A");
492
+ setText("videoFps", "N/A");
493
+ showItem("stats");
494
+ },
495
+ stop: function() {
496
+ if (playbackStats.timer) {
497
+ clearInterval(playbackStats.timer);
498
+ playbackStats.timer = null;
499
+ }
500
+ playbackStats.stats = null;
501
+ hideItem("stats");
502
+ },
503
+ displayStats: function() {
504
+ if (stats.collect()) {
505
+ let width = stats.getWidth();
506
+ let height = stats.getHeight();
507
+ let bitrate = stats.getBitrate();
508
+ let fps = stats.getFps();
509
+
510
+ setText("videoWidth", width);
511
+ setText("videoHeight", height);
512
+
513
+ if (bitrate !== undefined) {
514
+ setText("videoRate", Math.round(bitrate));
515
+ }
516
+ if (fps !== undefined) {
517
+ setText("videoFps", fps.toFixed(1));
518
+ }
519
+ }
520
+ }
521
+ };
522
+ return playbackStats;
364
523
  }
@@ -1,5 +1,5 @@
1
1
  <div class="row">
2
- <div class="col-sm-12 text-center" style="max-width: 525px">
2
+ <div class="col-sm-12 text-center" style="max-width: 500px">
3
3
 
4
4
  <h2 id="header"></h2>
5
5
 
@@ -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="playStream">Auth</label>
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,12 +87,42 @@
69
87
  </div>
70
88
  </div>
71
89
  <div class="row">
72
- <div id="videoContainer" class="col-sm-12 text-center" style="margin-top: 20px; max-width: 852px">
73
- <video id="remoteVideo" width="852" height="480"
90
+ <div id="videoContainer" style="margin-top: 20px; width: available; height: 56.25vw">
91
+ <video id="remoteVideo"
92
+ width="100%"
93
+ height="100%"
74
94
  controls="controls"
75
95
  autoplay="autoplay"
76
96
  playsinline="playsinline"
77
97
  webkit-playsinline="webkit-playsinline"
78
98
  type="application/vnd.apple.mpegurl"></video>
79
99
  </div>
100
+ </div>
101
+ <div id="stats" class="row" style="display: none;">
102
+ <div class="col-sm-12">
103
+ <div class="row" style="margin-top: 20px">
104
+ <div class="col-sm-2">
105
+ <label class="form-check-label" for="videoWidth">Video width</label>
106
+ </div>
107
+ <div class="col-sm-2" id="videoWidth"></div>
108
+ </div>
109
+ <div class="row" style="margin-top: 10px">
110
+ <div class="col-sm-2">
111
+ <label class="form-check-label" for="videoHeight">Video height</label>
112
+ </div>
113
+ <div class="col-sm-2" id="videoHeight"></div>
114
+ </div>
115
+ <div class="row" style="margin-top: 10px">
116
+ <div class="col-sm-2">
117
+ <label class="form-check-label" for="videoRate">Bitrate, bps</label>
118
+ </div>
119
+ <div class="col-sm-2" id="videoRate"></div>
120
+ </div>
121
+ <div class="row" style="margin-top: 10px">
122
+ <div class="col-sm-2">
123
+ <label class="form-check-label" for="videoFps">Framerate</label>
124
+ </div>
125
+ <div class="col-sm-2" id="videoFps"></div>
126
+ </div>
127
+ </div>
80
128
  </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flashphoner/websdk",
3
- "version": "2.0.242",
3
+ "version": "2.0.244",
4
4
  "description": "Official Flashphoner WebCallServer WebSDK package",
5
5
  "main": "./src/flashphoner-core.js",
6
6
  "types": "./src/flashphoner-core.d.ts",