@flashphoner/websdk 2.0.241 → 2.0.243

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.
@@ -1,4 +1,4 @@
1
- Web SDK - 2.0.241
1
+ Web SDK - 2.0.243
2
2
 
3
3
  [Download builds](https://docs.flashphoner.com/display/WEBSDK2EN/Web+SDK+release+notes)
4
4
 
@@ -0,0 +1,105 @@
1
+ /**
2
+ * HTML5 video playback statistics
3
+ */
4
+
5
+ /**
6
+ * HTML5 statistics item
7
+ *
8
+ * @returns {object}
9
+ * @constructor
10
+ */
11
+ const HTML5StatsItem = function() {
12
+ const statsItem = {
13
+ value: 0,
14
+ lastData: 0,
15
+ timestamp: 0,
16
+ init: function(value, data) {
17
+ statsItem.setValue(value);
18
+ statsItem.setLastData(data);
19
+ },
20
+ setValue: function(value) {
21
+ statsItem.value = value;
22
+ },
23
+ getValue: function() {
24
+ return statsItem.value;
25
+ },
26
+ setLastData: function(data, timestamp) {
27
+ statsItem.lastData = data;
28
+ statsItem.setTimestamp(timestamp);
29
+ },
30
+ getLastData: function() {
31
+ return statsItem.lastData;
32
+ },
33
+ setTimestamp: function(timestamp) {
34
+ statsItem.timestamp = timestamp || Date.now();
35
+ },
36
+ getTimestamp: function() {
37
+ return statsItem.timestamp;
38
+ },
39
+ elapsedSecs: function(timestamp) {
40
+ let now = timestamp || Date.now();
41
+ return (now - statsItem.timestamp) / 1000;
42
+ }
43
+ };
44
+ return statsItem;
45
+ }
46
+
47
+ const HTML5Stats = function(video) {
48
+ const stats = {
49
+ video: video || null,
50
+ width: 0,
51
+ height: 0,
52
+ bitrate: HTML5StatsItem(),
53
+ fps: HTML5StatsItem(),
54
+ init: function(video) {
55
+ stats.video = video;
56
+ stats.width = 0;
57
+ stats.height = 0;
58
+ stats.bitrate.init(0);
59
+ stats.fps.init(0);
60
+ },
61
+ collect: function() {
62
+ if (stats.video) {
63
+ let now = Date.now();
64
+ let quality = video.getVideoPlaybackQuality();
65
+
66
+ if (quality) {
67
+ let played = quality.totalVideoFrames - quality.droppedVideoFrames;
68
+ if (played !== stats.fps.getLastData()) {
69
+ stats.fps.setValue((played - stats.fps.getLastData()) / stats.fps.elapsedSecs(now));
70
+ stats.fps.setLastData(played, now);
71
+ }
72
+ } else {
73
+ stats.fps.setValue(undefined);
74
+ }
75
+
76
+ if (stats.video.webkitVideoDecodedByteCount !== undefined) {
77
+ let decoded = stats.video.webkitVideoDecodedByteCount;
78
+ stats.bitrate.setValue(Math.round((decoded - stats.bitrate.getLastData()) * 8 / stats.bitrate.elapsedSecs(now)));
79
+ stats.bitrate.setLastData(decoded, now);
80
+ } else {
81
+ stats.bitrate.setValue(undefined);
82
+ }
83
+
84
+ stats.width = stats.video.videoWidth;
85
+ stats.height = stats.video.videoHeight;
86
+
87
+ return true;
88
+ }
89
+ return false;
90
+ },
91
+ getWidth: function() {
92
+ return stats.width;
93
+ },
94
+ getHeight: function() {
95
+ return stats.height;
96
+ },
97
+ getFps: function() {
98
+ return stats.fps.getValue();
99
+ },
100
+ getBitrate: function() {
101
+ return stats.bitrate.getValue();
102
+ }
103
+ };
104
+ return stats;
105
+ }
@@ -457,7 +457,12 @@ function canWebkitFullScreen(video) {
457
457
  return canFullscreen;
458
458
  }
459
459
 
460
- // Helper function to set item text
460
+ /**
461
+ * Helper function to set item text
462
+ *
463
+ * @param id
464
+ * @param text
465
+ */
461
466
  const setText = function (id, text) {
462
467
  let item = document.getElementById(id);
463
468
  if (item) {
@@ -465,7 +470,12 @@ const setText = function (id, text) {
465
470
  }
466
471
  }
467
472
 
468
- // Helper functions to set/get an item value
473
+ /**
474
+ * Helper function to set an item value
475
+ *
476
+ * @param id
477
+ * @param value
478
+ */
469
479
  const setValue = function (id, value) {
470
480
  let item = document.getElementById(id);
471
481
  if (item) {
@@ -473,6 +483,12 @@ const setValue = function (id, value) {
473
483
  }
474
484
  }
475
485
 
486
+ /**
487
+ * Helper function to get an item value
488
+ *
489
+ * @param id
490
+ * @returns value
491
+ */
476
492
  const getValue = function (id) {
477
493
  let item = document.getElementById(id);
478
494
  if (item) {
@@ -481,7 +497,39 @@ const getValue = function (id) {
481
497
  return null;
482
498
  }
483
499
 
484
- // Helper functions to display/hide an item
500
+ /**
501
+ * Helper function to set/unset a checkbox
502
+ *
503
+ * @param id
504
+ * @param value
505
+ */
506
+ const setCheckbox = function (id, value) {
507
+ let item = document.getElementById(id);
508
+ if (item) {
509
+ item.checked = value;
510
+ }
511
+ }
512
+
513
+ /**
514
+ * Helper function to get a checkbox state
515
+ *
516
+ * @param id
517
+ * @returns value
518
+ */
519
+ const getCheckbox = function (id) {
520
+ let item = document.getElementById(id);
521
+ if (item) {
522
+ return item.checked;
523
+ }
524
+ return null;
525
+ }
526
+
527
+
528
+ /**
529
+ * Helper function to display an item
530
+ *
531
+ * @param id
532
+ */
485
533
  const showItem = function(id) {
486
534
  let item = document.getElementById(id);
487
535
  if (item) {
@@ -489,6 +537,11 @@ const showItem = function(id) {
489
537
  }
490
538
  }
491
539
 
540
+ /**
541
+ * Helper function to hide an item
542
+ *
543
+ * @param id
544
+ */
492
545
  const hideItem = function(id) {
493
546
  let item = document.getElementById(id);
494
547
  if (item) {
@@ -496,7 +549,11 @@ const hideItem = function(id) {
496
549
  }
497
550
  }
498
551
 
499
- // Helper functions to disable/enable an item
552
+ /**
553
+ * Helper function to disable an item
554
+ *
555
+ * @param id
556
+ */
500
557
  const disableItem = function(id) {
501
558
  let item = document.getElementById(id);
502
559
  if (item) {
@@ -504,6 +561,11 @@ const disableItem = function(id) {
504
561
  }
505
562
  }
506
563
 
564
+ /**
565
+ * Helper function to enable an item
566
+ *
567
+ * @param id
568
+ */
507
569
  const enableItem = function(id) {
508
570
  let item = document.getElementById(id);
509
571
  if (item) {
@@ -511,7 +573,14 @@ const enableItem = function(id) {
511
573
  }
512
574
  }
513
575
 
514
- // Set an event handler
576
+ /**
577
+ * Set an event handler
578
+ *
579
+ * @param id
580
+ * @param event
581
+ * @param handler
582
+ * @param previous
583
+ */
515
584
  const setHandler = function (id, event, handler, previous = null) {
516
585
  let item = document.getElementById(id);
517
586
  if (item) {
@@ -522,7 +591,13 @@ const setHandler = function (id, event, handler, previous = null) {
522
591
  }
523
592
  }
524
593
 
525
- // Find a closest item
594
+ /**
595
+ * Find a closest item
596
+ *
597
+ * @param id
598
+ * @param selector
599
+ * @returns {null}
600
+ */
526
601
  const closest = function (id, selector) {
527
602
  let currentElement = document.getElementById(id);
528
603
  let returnElement = null;
@@ -534,3 +609,17 @@ const closest = function (id, selector) {
534
609
 
535
610
  return returnElement;
536
611
  }
612
+
613
+ /**
614
+ * Display object properties fro debugging purposes
615
+ *
616
+ * @param object
617
+ */
618
+ const showProps = function (object) {
619
+ console.log("-------------------------------object begin");
620
+ for (const property in object) {
621
+ console.log(`${property}: ${object[property]}`);
622
+ }
623
+ console.log("-------------------------------object end");
624
+
625
+ }
@@ -8,12 +8,9 @@
8
8
  <title>HLS.JS Player Minimal</title>
9
9
  <script type="text/javascript" src="../../../../flashphoner.js"></script>
10
10
  <script type="text/javascript" src="hls.min.js"></script>
11
- <script type="text/javascript" src="../../dependencies/jquery/jquery-1.12.0.js"></script>
12
- <script type="text/javascript" src="../../dependencies/jquery/jquery-ui.js"></script>
13
11
  <script type="text/javascript" src="../../dependencies/js/utils.js"></script>
12
+ <script type="text/javascript" src="../../dependencies/js/stats.js"></script>
14
13
  <script type="text/javascript" src="hls-js-player.js"></script>
15
- <!-- Bootstrap JS -->
16
- <script src="../../dependencies/bootstrap/js/bootstrap.js"></script>
17
14
  </head>
18
15
  <body onload="loadPlayerPage()">
19
16
  <div id="playerPage" class="container">
@@ -1,35 +1,54 @@
1
- var Browser = Flashphoner.Browser;
2
- var remoteVideo = null;
3
- var hlsPlayer = null;
1
+ const Browser = Flashphoner.Browser;
2
+ const STATS_INTERVAL = 1000;
3
+ let remoteVideo = null;
4
+ let hlsPlayer = null;
5
+ let playbackStats = null;
6
+
7
+ const loadPlayerPage = function() {
8
+ loadPage("../hls-player/player-page.html", "playerPage", initPage );
9
+ }
4
10
 
5
- function loadPlayerPage() {
6
- $("#playerPage").load("../hls-player/player-page.html", initPage );
11
+ const loadPage = function(page, containerId, onLoad) {
12
+ fetch(page).then(function (response) {
13
+ if (response.ok) {
14
+ return response.text();
15
+ }
16
+ throw response;
17
+ }).then(function (text) {
18
+ let container = document.getElementById(containerId);
19
+ container.innerHTML = text;
20
+ onLoad();
21
+ });
7
22
  }
8
23
 
9
- function initPage() {
10
- $("#header").text("HLS.JS Player Minimal");
11
- $("#urlServer").val(getHLSUrl());
12
- $("#applyBtn").prop('disabled', true).text("Play").off('click').click(playBtnClick);
24
+ const initPage = function() {
25
+ setText("header", "HLS.JS Player Minimal");
26
+ setValue("urlServer", getHLSUrl());
27
+ setText("applyBtn", "Play");
28
+ setHandler("applyBtn", "click", playBtnClick);
29
+ remoteVideo = document.getElementById('remoteVideo');
30
+ remoteVideo.style ="background-color: lightgrey;";
13
31
  if (Hls.isSupported()) {
14
32
  console.log("Using HLS.JS " + Hls.version);
15
- $("#applyBtn").prop('disabled', false);
33
+ enableItem("applyBtn");
34
+ showItem("llHlsMode");
35
+ playbackStats = PlaybackStats(STATS_INTERVAL);
16
36
  } else {
17
- $("#notifyFlash").text("Your browser doesn't support MSE technology required to play video");
37
+ setText("notifyFlash", "Your browser doesn't support MSE technology required to play video");
38
+ disableItem("applyBtn");
39
+ toggleInputs(false);
18
40
  }
19
- remoteVideo = document.getElementById('remoteVideo');
20
- remoteVideo.style ="background-color: lightgrey;";
21
- $('#llHlsMode').show();
22
41
  }
23
42
 
24
43
 
25
- function playBtnClick() {
44
+ const playBtnClick = function() {
26
45
  if (validateForm()) {
27
- var llHlsEnabled = $('#llHlsEnabled').is(":checked");
28
- var streamName = $('#playStream').val();
46
+ let llHlsEnabled = getCheckbox("llHlsEnabled");
47
+ let streamName = getValue("playStream");
29
48
  streamName = encodeURIComponent(streamName);
30
- var videoSrc = $("#urlServer").val() + '/' + streamName + '/' + streamName + '.m3u8';
31
- var key = $('#key').val();
32
- var token = $("#token").val();
49
+ let videoSrc = getValue("urlServer") + '/' + streamName + '/' + streamName + '.m3u8';
50
+ let key = getValue('key');
51
+ let token = getValue("token");
33
52
  if (key.length > 0 && token.length > 0) {
34
53
  videoSrc += "?" + key + "=" + token;
35
54
  }
@@ -45,8 +64,8 @@ function playBtnClick() {
45
64
  }
46
65
 
47
66
 
48
- function getHlsConfig(llHlsEnabled) {
49
- var config = {
67
+ const getHlsConfig = function(llHlsEnabled) {
68
+ let config = {
50
69
  lowLatencyMode: false,
51
70
  enableWorker: true,
52
71
  backBufferLength: 90,
@@ -71,7 +90,7 @@ function getHlsConfig(llHlsEnabled) {
71
90
  }
72
91
 
73
92
 
74
- function stopBtnClick() {
93
+ const stopBtnClick = function() {
75
94
  if (hlsPlayer != null) {
76
95
  console.log("Stop HLS segments loading");
77
96
  hlsPlayer.stopLoad();
@@ -88,53 +107,126 @@ function stopBtnClick() {
88
107
  }
89
108
 
90
109
 
91
- function onStarted() {
92
- $("#urlServer").prop('disabled', true);
93
- $("#playStream").prop('disabled', true);
94
- $("#key").prop('disabled', true);
95
- $("#token").prop('disabled', true);
96
- $("#player").prop('disabled', true);
97
- $('#llHlsEnabled').prop('disabled', true);
98
- $("#applyBtn").prop('disabled', false).text("Stop").off('click').click(stopBtnClick);
110
+ const onStarted = function() {
111
+ toggleInputs(false);
112
+ enableItem("applyBtn");
113
+ setText("applyBtn", "Stop");
114
+ setHandler("applyBtn", "click", stopBtnClick, playBtnClick);
115
+ playbackStats.start();
99
116
  }
100
117
 
101
118
 
102
119
  function onStopped() {
103
- $("#urlServer").prop('disabled', false);
104
- $("#playStream").prop('disabled', false);
105
- $("#key").prop('disabled', false);
106
- $("#token").prop('disabled', false);
107
- $("#player").prop('disabled', false);
108
- $('#llHlsEnabled').prop('disabled', false);
109
- $("#applyBtn").prop('disabled', false).text("Play").off('click').click(playBtnClick);
120
+ toggleInputs(true);
121
+ enableItem("applyBtn");
122
+ setText("applyBtn", "Play");
123
+ setHandler("applyBtn", "click", playBtnClick, stopBtnClick);
124
+ playbackStats.stop();
110
125
  }
111
126
 
112
127
 
113
- function validateForm() {
114
- var valid = true;
115
- if (!$("#urlServer").val().length) {
116
- highlightInput($("#urlServer"));
117
- valid = false;
118
- } else {
119
- removeHighlight($("#urlServer"));
128
+ const validateForm = function() {
129
+ let valid = validateInput("urlServer");
130
+ if (valid) {
131
+ valid = validateInput("playStream");
120
132
  }
121
- if (!$("#playStream").val().length) {
122
- highlightInput($("#playStream"));
133
+ return valid;
134
+ }
135
+
136
+ const validateInput = function(id) {
137
+ let value = getValue(id);
138
+ let valid = true;
139
+ if (!value || !value.length) {
140
+ highlightInput(id);
123
141
  valid = false;
124
142
  } else {
125
- removeHighlight($("#playStream"));
143
+ removeHighlight(id);
126
144
  }
127
-
128
145
  return valid;
129
-
130
146
  }
131
147
 
132
-
133
- function highlightInput(input) {
134
- input.closest('.form-group').addClass("has-error");
148
+ const highlightInput = function(input) {
149
+ let item = document.getElementById(input);
150
+ if (item) {
151
+ let parent = closest(input,'.form-group');
152
+ if (parent) {
153
+ parent.classList.add("has-error");
154
+ }
155
+ }
135
156
  }
136
157
 
137
158
 
138
- function removeHighlight(input) {
139
- input.closest('.form-group').removeClass("has-error");
159
+ const removeHighlight = function(input) {
160
+ let item = document.getElementById(input);
161
+ if (item) {
162
+ let parent = closest(input,'.form-group');
163
+ if (parent) {
164
+ parent.classList.remove("has-error");
165
+ }
166
+ }
167
+ }
168
+
169
+ const toggleInputs = function(enable) {
170
+ if (enable) {
171
+ enableItem("urlServer");
172
+ enableItem("playStream");
173
+ enableItem("key");
174
+ enableItem("token");
175
+ enableItem("player");
176
+ enableItem("llHlsEnabled");
177
+ } else {
178
+ disableItem("urlServer");
179
+ disableItem("playStream");
180
+ disableItem("key");
181
+ disableItem("token");
182
+ disableItem("player");
183
+ disableItem("llHlsEnabled");
184
+ }
140
185
  }
186
+
187
+ const PlaybackStats = function(interval) {
188
+ const playbackStats = {
189
+ interval: interval || STATS_INTERVAL,
190
+ timer: null,
191
+ stats: null,
192
+ start: function() {
193
+ let video = remoteVideo;
194
+
195
+ playbackStats.stop();
196
+ stats = HTML5Stats(video);
197
+ playbackStats.timer = setInterval(playbackStats.displayStats, playbackStats.interval);
198
+ setText("videoWidth", "N/A");
199
+ setText("videoHeight", "N/A");
200
+ setText("videoRate", "N/A");
201
+ setText("videoFps", "N/A");
202
+ showItem("stats");
203
+ },
204
+ stop: function() {
205
+ if (playbackStats.timer) {
206
+ clearInterval(playbackStats.timer);
207
+ playbackStats.timer = null;
208
+ }
209
+ playbackStats.stats = null;
210
+ hideItem("stats");
211
+ },
212
+ displayStats: function() {
213
+ if (stats.collect()) {
214
+ let width = stats.getWidth();
215
+ let height = stats.getHeight();
216
+ let bitrate = stats.getBitrate();
217
+ let fps = stats.getFps();
218
+
219
+ setText("videoWidth", width);
220
+ setText("videoHeight", height);
221
+
222
+ if (bitrate !== undefined) {
223
+ setText("videoRate", Math.round(bitrate));
224
+ }
225
+ if (fps !== undefined) {
226
+ setText("videoFps", fps.toFixed(1));
227
+ }
228
+ }
229
+ }
230
+ };
231
+ return playbackStats;
232
+ }
@@ -7,12 +7,9 @@
7
7
  <link rel="stylesheet" href="hls-native.css">
8
8
  <title>HLS Native Player Minimal</title>
9
9
  <script type="text/javascript" src="../../../../flashphoner.js"></script>
10
- <script type="text/javascript" src="../../dependencies/jquery/jquery-1.12.0.js"></script>
11
- <script type="text/javascript" src="../../dependencies/jquery/jquery-ui.js"></script>
12
10
  <script type="text/javascript" src="../../dependencies/js/utils.js"></script>
11
+ <script type="text/javascript" src="../../dependencies/js/stats.js"></script>
13
12
  <script type="text/javascript" src="hls-native.js"></script>
14
- <!-- Bootstrap JS -->
15
- <script src="../../dependencies/bootstrap/js/bootstrap.js"></script>
16
13
  </head>
17
14
  <body onload="loadPlayerPage()">
18
15
  <div id="playerPage" class="container">