ovenplayer 0.10.39 → 0.10.41
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/README.md +2 -2
- package/dist/ovenplayer.js +1 -1
- package/dist/ovenplayer.js.map +1 -1
- package/package.json +1 -1
- package/src/js/api/Configurator.js +4 -2
- package/src/js/api/constants.js +9 -0
- package/src/js/api/provider/html5/Listener.js +32 -33
- package/src/js/api/provider/html5/providers/WebRTC.js +9 -2
- package/src/js/utils/deepMerge.js +42 -0
- package/src/js/view/components/controls/progressBar.js +0 -22
- package/src/js/view/components/controls/settingPanel/main.js +4 -3
- package/src/js/view/components/controls/settingPanel/qualityPanel.js +1 -1
- package/src/js/view/components/controls/timeDisplay.js +14 -23
- package/src/js/view/view.js +101 -98
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ovenplayer",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.41",
|
|
4
4
|
"description": "OvenPlayer is Open-Source HTML5 Player. OvenPlayer supports WebRTC Signaling from OvenMediaEngine for Sub-Second Latency Streaming.",
|
|
5
5
|
"main": "dist/ovenplayer.js",
|
|
6
6
|
"scripts": {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _ from "utils/underscore";
|
|
2
|
+
import deepMerge from "utils/deepMerge";
|
|
2
3
|
|
|
3
4
|
import {
|
|
4
5
|
CONTENT_TIME_MODE_CHANGED, SYSTEM_TEXT
|
|
@@ -82,12 +83,13 @@ const Configurator = function (options, provider) {
|
|
|
82
83
|
let currentSystemText = _.findWhere(SYSTEM_TEXT, { "lang": userCustumSystemText[i].lang });
|
|
83
84
|
if (currentSystemText) {
|
|
84
85
|
//validate & update
|
|
85
|
-
|
|
86
|
+
deepMerge(currentSystemText, userCustumSystemText[i]);
|
|
86
87
|
} else {
|
|
87
88
|
//create
|
|
88
89
|
currentSystemText = _.findWhere(SYSTEM_TEXT, { "lang": "en" });
|
|
89
90
|
currentSystemText.lang = userCustumSystemText[i].lang;
|
|
90
|
-
|
|
91
|
+
const newMerged = deepMerge({}, currentSystemText, userCustumSystemText[i]);
|
|
92
|
+
SYSTEM_TEXT.push(newMerged);
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
}
|
package/src/js/api/constants.js
CHANGED
|
@@ -135,6 +135,9 @@ export const SYSTEM_TEXT = [
|
|
|
135
135
|
"low_latency_p2p": "Sub-Second Latency P2P",
|
|
136
136
|
},
|
|
137
137
|
"playlist": "Playlist",
|
|
138
|
+
"quality": {
|
|
139
|
+
"auto": "Auto"
|
|
140
|
+
},
|
|
138
141
|
"setting": {
|
|
139
142
|
"title": "Settings",
|
|
140
143
|
"speed": "Speed",
|
|
@@ -295,6 +298,9 @@ export const SYSTEM_TEXT = [
|
|
|
295
298
|
"low_latency_p2p": "초저지연 P2P",
|
|
296
299
|
},
|
|
297
300
|
"playlist": "플레이리스트",
|
|
301
|
+
"quality": {
|
|
302
|
+
"auto": "자동"
|
|
303
|
+
},
|
|
298
304
|
"setting": {
|
|
299
305
|
"title": "설정",
|
|
300
306
|
"speed": "재생 속도",
|
|
@@ -455,6 +461,9 @@ export const SYSTEM_TEXT = [
|
|
|
455
461
|
"low_latency_p2p": "Transmisja z niskim opóźnieniem P2P",
|
|
456
462
|
},
|
|
457
463
|
"playlist": "Playlista",
|
|
464
|
+
"quality": {
|
|
465
|
+
"auto": "Auto"
|
|
466
|
+
},
|
|
458
467
|
"setting": {
|
|
459
468
|
"title": "Ustawienia",
|
|
460
469
|
"speed": "Prędkość",
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
PROVIDER_DASH,
|
|
29
29
|
PROVIDER_HLS
|
|
30
30
|
} from "api/constants";
|
|
31
|
-
import {extractVideoElement, errorTrigger} from "api/provider/utils";
|
|
31
|
+
import { extractVideoElement, errorTrigger } from "api/provider/utils";
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* @brief Trigger on various video events.
|
|
@@ -37,18 +37,18 @@ import {extractVideoElement, errorTrigger} from "api/provider/utils";
|
|
|
37
37
|
* */
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
40
|
+
const Listener = function (element, provider, videoEndedCallback, playerConfig) {
|
|
41
41
|
const lowLevelEvents = {};
|
|
42
42
|
|
|
43
|
-
OvenPlayerConsole.log("EventListener loaded.",element
|
|
43
|
+
OvenPlayerConsole.log("EventListener loaded.", element, provider);
|
|
44
44
|
const that = {};
|
|
45
45
|
|
|
46
46
|
let stalled = -1;
|
|
47
|
-
let elVideo =
|
|
47
|
+
let elVideo = element;
|
|
48
48
|
const between = function (num, min, max) {
|
|
49
49
|
return Math.max(Math.min(num, max), min);
|
|
50
50
|
};
|
|
51
|
-
const compareStalledTime = function(stalled, position){
|
|
51
|
+
const compareStalledTime = function (stalled, position) {
|
|
52
52
|
//Original Code is stalled !== position
|
|
53
53
|
//Because Dashjs is very meticulous. Then always diffrence stalled and position.
|
|
54
54
|
//That is why when I use toFixed(2).
|
|
@@ -77,12 +77,12 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
77
77
|
// IE doesn't set paused property to true. So force set it.
|
|
78
78
|
elVideo.pause();
|
|
79
79
|
|
|
80
|
-
if(provider.getState() !== STATE_IDLE && provider.getState() !== STATE_COMPLETE && provider.getState() !== STATE_ERROR) {
|
|
81
|
-
if(videoEndedCallback){
|
|
82
|
-
videoEndedCallback(function(){
|
|
80
|
+
if (provider.getState() !== STATE_IDLE && provider.getState() !== STATE_COMPLETE && provider.getState() !== STATE_ERROR) {
|
|
81
|
+
if (videoEndedCallback) {
|
|
82
|
+
videoEndedCallback(function () {
|
|
83
83
|
provider.setState(STATE_COMPLETE);
|
|
84
84
|
});
|
|
85
|
-
}else{
|
|
85
|
+
} else {
|
|
86
86
|
provider.setState(STATE_COMPLETE);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
@@ -107,8 +107,8 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
107
107
|
let sourceIndex = provider.getCurrentSource();
|
|
108
108
|
let type = sourceIndex > -1 ? sources[sourceIndex].type : "";
|
|
109
109
|
var metadata = {
|
|
110
|
-
duration: provider.isLive() ?
|
|
111
|
-
type
|
|
110
|
+
duration: provider.isLive() ? Infinity : elVideo.duration,
|
|
111
|
+
type: type
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
provider.setMetaLoaded();
|
|
@@ -119,16 +119,16 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
119
119
|
|
|
120
120
|
lowLevelEvents.pause = () => {
|
|
121
121
|
//Fires when the audio/video has been paused
|
|
122
|
-
if(provider.getState() === STATE_COMPLETE || provider.getState() === STATE_ERROR){
|
|
122
|
+
if (provider.getState() === STATE_COMPLETE || provider.getState() === STATE_ERROR) {
|
|
123
123
|
return false;
|
|
124
124
|
}
|
|
125
|
-
if(elVideo.ended){
|
|
125
|
+
if (elVideo.ended) {
|
|
126
126
|
return false;
|
|
127
127
|
}
|
|
128
|
-
if(elVideo.error){
|
|
128
|
+
if (elVideo.error) {
|
|
129
129
|
return false;
|
|
130
130
|
}
|
|
131
|
-
if(elVideo.currentTime === elVideo.duration){
|
|
131
|
+
if (elVideo.currentTime === elVideo.duration) {
|
|
132
132
|
return false;
|
|
133
133
|
}
|
|
134
134
|
OvenPlayerConsole.log("EventListener : on pause");
|
|
@@ -157,7 +157,7 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
157
157
|
lowLevelEvents.playing = () => {
|
|
158
158
|
//Fires when the audio/video is playing after having been paused or stopped for buffering
|
|
159
159
|
OvenPlayerConsole.log("EventListener : on playing");
|
|
160
|
-
if(stalled < 0){
|
|
160
|
+
if (stalled < 0) {
|
|
161
161
|
provider.setState(STATE_PLAYING);
|
|
162
162
|
}
|
|
163
163
|
};
|
|
@@ -165,20 +165,20 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
165
165
|
lowLevelEvents.progress = () => {
|
|
166
166
|
//Fires when the browser is downloading the audio/video
|
|
167
167
|
let timeRanges = elVideo.buffered;
|
|
168
|
-
if(!timeRanges
|
|
168
|
+
if (!timeRanges) {
|
|
169
169
|
return false;
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
let duration = elVideo.duration, position = elVideo.currentTime;
|
|
173
|
-
let buffered = between(
|
|
173
|
+
let buffered = between((timeRanges.length > 0 ? timeRanges.end(timeRanges.length - 1) : 0) / duration, 0, 1);
|
|
174
174
|
|
|
175
|
-
provider.setBuffer(buffered*100);
|
|
175
|
+
provider.setBuffer(buffered * 100);
|
|
176
176
|
provider.trigger(CONTENT_BUFFER, {
|
|
177
|
-
bufferPercent: buffered*100,
|
|
178
|
-
position:
|
|
177
|
+
bufferPercent: buffered * 100,
|
|
178
|
+
position: position,
|
|
179
179
|
duration: duration
|
|
180
180
|
});
|
|
181
|
-
OvenPlayerConsole.log("EventListener : on progress", buffered*100);
|
|
181
|
+
OvenPlayerConsole.log("EventListener : on progress", buffered * 100);
|
|
182
182
|
};
|
|
183
183
|
|
|
184
184
|
|
|
@@ -213,12 +213,12 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
//Sometimes dash live gave to me crazy duration. (9007199254740991...) why???
|
|
216
|
-
if(duration > 9000000000000000){ //9007199254740991
|
|
216
|
+
if (duration > 9000000000000000) { //9007199254740991
|
|
217
217
|
duration = Infinity;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
if(!provider.isSeeking() && !elVideo.paused && (provider.getState() === STATE_STALLED || provider.getState() === STATE_LOADING || provider.getState() === STATE_AD_PLAYING) &&
|
|
221
|
-
!compareStalledTime(stalled, position)
|
|
220
|
+
if (!provider.isSeeking() && !elVideo.paused && (provider.getState() === STATE_STALLED || provider.getState() === STATE_LOADING || provider.getState() === STATE_AD_PLAYING) &&
|
|
221
|
+
!compareStalledTime(stalled, position)) {
|
|
222
222
|
stalled = -1;
|
|
223
223
|
provider.setState(STATE_PLAYING);
|
|
224
224
|
}
|
|
@@ -252,12 +252,12 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
252
252
|
lowLevelEvents.seeking = () => {
|
|
253
253
|
provider.setSeeking(true);
|
|
254
254
|
OvenPlayerConsole.log("EventListener : on seeking", elVideo.currentTime);
|
|
255
|
-
provider.trigger(CONTENT_SEEK,{
|
|
256
|
-
position
|
|
255
|
+
provider.trigger(CONTENT_SEEK, {
|
|
256
|
+
position: elVideo.currentTime
|
|
257
257
|
});
|
|
258
258
|
};
|
|
259
259
|
lowLevelEvents.seeked = () => {
|
|
260
|
-
if(!provider.isSeeking()){
|
|
260
|
+
if (!provider.isSeeking()) {
|
|
261
261
|
return;
|
|
262
262
|
}
|
|
263
263
|
OvenPlayerConsole.log("EventListener : on seeked");
|
|
@@ -273,11 +273,10 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
273
273
|
lowLevelEvents.waiting = () => {
|
|
274
274
|
//Fires when the video stops because it needs to buffer the next frame
|
|
275
275
|
OvenPlayerConsole.log("EventListener : on waiting", provider.getState());
|
|
276
|
-
if(provider.isSeeking()){
|
|
276
|
+
if (provider.isSeeking()) {
|
|
277
277
|
provider.setState(STATE_LOADING);
|
|
278
|
-
}else if(provider.getState() === STATE_PLAYING){
|
|
278
|
+
} else if (provider.getState() === STATE_PLAYING) {
|
|
279
279
|
stalled = elVideo.currentTime;
|
|
280
|
-
provider.setState(STATE_STALLED);
|
|
281
280
|
}
|
|
282
281
|
};
|
|
283
282
|
|
|
@@ -297,7 +296,7 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
297
296
|
2: PLAYER_UNKNWON_NETWORK_ERROR,
|
|
298
297
|
3: PLAYER_UNKNWON_DECODE_ERROR,
|
|
299
298
|
4: PLAYER_FILE_ERROR
|
|
300
|
-
}[code]||0);
|
|
299
|
+
}[code] || 0);
|
|
301
300
|
|
|
302
301
|
OvenPlayerConsole.log("EventListener : on error", convertedErroCode);
|
|
303
302
|
errorTrigger(ERRORS.codes[convertedErroCode], provider);
|
|
@@ -308,7 +307,7 @@ const Listener = function(element, provider, videoEndedCallback, playerConfig){
|
|
|
308
307
|
elVideo.addEventListener(eventName, lowLevelEvents[eventName]);
|
|
309
308
|
});
|
|
310
309
|
|
|
311
|
-
that.destroy = () =>{
|
|
310
|
+
that.destroy = () => {
|
|
312
311
|
OvenPlayerConsole.log("EventListener : destroy()");
|
|
313
312
|
|
|
314
313
|
Object.keys(lowLevelEvents).forEach(eventName => {
|
|
@@ -20,6 +20,7 @@ const WebRTC = function (element, playerConfig, adTagUrl) {
|
|
|
20
20
|
let webrtcLoader = null;
|
|
21
21
|
let superDestroy_func = null;
|
|
22
22
|
let superPlay_func = null;
|
|
23
|
+
let superStop_func = null;
|
|
23
24
|
|
|
24
25
|
let sourceFile = null;
|
|
25
26
|
|
|
@@ -255,6 +256,7 @@ const WebRTC = function (element, playerConfig, adTagUrl) {
|
|
|
255
256
|
|
|
256
257
|
superDestroy_func = that.super('destroy');
|
|
257
258
|
superPlay_func = that.super('play');
|
|
259
|
+
superStop_func = that.super('stop');
|
|
258
260
|
|
|
259
261
|
OvenPlayerConsole.log("WEBRTC PROVIDER LOADED.");
|
|
260
262
|
|
|
@@ -277,14 +279,19 @@ const WebRTC = function (element, playerConfig, adTagUrl) {
|
|
|
277
279
|
|
|
278
280
|
that.play = () => {
|
|
279
281
|
|
|
280
|
-
if (timeoutMaxRetry > 0 && !connected) {
|
|
281
|
-
|
|
282
|
+
if (!webrtcLoader || (timeoutMaxRetry > 0 && !connected)) {
|
|
282
283
|
loadWebRTCLoader();
|
|
283
284
|
}
|
|
284
285
|
|
|
285
286
|
superPlay_func();
|
|
286
287
|
};
|
|
287
288
|
|
|
289
|
+
that.stop = () => {
|
|
290
|
+
clearTimeout(connectionCheckTimer);
|
|
291
|
+
destroyWebRtcLoader();
|
|
292
|
+
superStop_func();
|
|
293
|
+
};
|
|
294
|
+
|
|
288
295
|
return that;
|
|
289
296
|
};
|
|
290
297
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Performs a deep merge of the `source` object's properties into the `target` object.
|
|
3
|
+
* For nested objects, the function recurses; otherwise it directly overwrites values.
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} target - The object to which properties are merged.
|
|
6
|
+
* @param {Object} source - The object containing properties to be copied.
|
|
7
|
+
* @returns {Object} The modified `target` object reference.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const objA = {
|
|
11
|
+
* a: 1,
|
|
12
|
+
* b: { x: 10, y: 20 }
|
|
13
|
+
* };
|
|
14
|
+
* const objB = {
|
|
15
|
+
* b: { y: 999, z: 50 },
|
|
16
|
+
* c: 3
|
|
17
|
+
* };
|
|
18
|
+
*
|
|
19
|
+
* deepMerge(objA, objB);
|
|
20
|
+
* Result: objA = {
|
|
21
|
+
* a: 1,
|
|
22
|
+
* b: { x: 10, y: 999, z: 50 },
|
|
23
|
+
* c: 3
|
|
24
|
+
* }
|
|
25
|
+
*/
|
|
26
|
+
export default function deepMerge(target, source) {
|
|
27
|
+
for (let key in source) {
|
|
28
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
29
|
+
if (
|
|
30
|
+
typeof source[key] === "object" &&
|
|
31
|
+
source[key] !== null &&
|
|
32
|
+
typeof target[key] === "object" &&
|
|
33
|
+
target[key] !== null
|
|
34
|
+
) {
|
|
35
|
+
deepMerge(target[key], source[key]);
|
|
36
|
+
} else {
|
|
37
|
+
target[key] = source[key];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return target;
|
|
42
|
+
}
|
|
@@ -231,28 +231,6 @@ const ProgressBar = function ($container, api, isAd, metadata) {
|
|
|
231
231
|
|
|
232
232
|
let time = (durationForCalc || 0) * percentage;
|
|
233
233
|
|
|
234
|
-
if (hlsLive && !nativeHlsLive) {
|
|
235
|
-
|
|
236
|
-
// if latency control is on. temporarily disable latency control
|
|
237
|
-
const config = api.getConfig();
|
|
238
|
-
if (config.hlsConfig) {
|
|
239
|
-
|
|
240
|
-
if (typeof config.hlsConfig.liveSyncDuration === 'number') {
|
|
241
|
-
api.getMseInstance().config.liveSyncDuration = undefined;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (typeof config.hlsConfig.liveMaxLatencyDuration === 'number') {
|
|
245
|
-
api.getMseInstance().config.liveMaxLatencyDuration = undefined;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (typeof config.hlsConfig.maxLiveSyncPlaybackRate === 'number') {
|
|
249
|
-
api.getMseInstance().config.maxLiveSyncPlaybackRate = 1;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
time = (durationForCalc - api.getDvrWindow()) + api.getDvrWindow() * percentage;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
234
|
if (hlsLive && nativeHlsLive) {
|
|
257
235
|
const dvrWindow = getNativeHlsDvrWindow();
|
|
258
236
|
time = (durationForCalc - dvrWindow) + dvrWindow * percentage;
|
|
@@ -106,16 +106,17 @@ const Panels = function ($container, api, data) {
|
|
|
106
106
|
|
|
107
107
|
} else if (panelType === "quality") {
|
|
108
108
|
let qualityLevels = api.getQualityLevels();
|
|
109
|
+
let isQualityCheck = api.isAutoQuality();
|
|
109
110
|
panel.body.push({
|
|
110
|
-
title:
|
|
111
|
-
isCheck:
|
|
111
|
+
title: playerConfig.systemText.ui.quality.auto,
|
|
112
|
+
isCheck: isQualityCheck,
|
|
112
113
|
value: "AUTO",
|
|
113
114
|
panelType: panelType
|
|
114
115
|
});
|
|
115
116
|
for (let i = 0; i < qualityLevels.length; i++) {
|
|
116
117
|
let body = {
|
|
117
118
|
title: qualityLevels[i].label,
|
|
118
|
-
isCheck: api.getCurrentQuality() === i,
|
|
119
|
+
isCheck: !isQualityCheck && api.getCurrentQuality() === i,
|
|
119
120
|
value: i,
|
|
120
121
|
panelType: panelType
|
|
121
122
|
};
|
|
@@ -31,7 +31,7 @@ const QualityPanel = function($container, api, data){
|
|
|
31
31
|
if( $panel.find(".op-setting-item-checked").hasClass("op-show")){
|
|
32
32
|
$panel.find(".op-setting-item-checked").removeClass("op-show");
|
|
33
33
|
}
|
|
34
|
-
if(newQuality === parseInt($panel.attr("op-data-value"))){
|
|
34
|
+
if(!data.isAuto && newQuality === parseInt($panel.attr("op-data-value"))){
|
|
35
35
|
$panel.find(".op-setting-item-checked").addClass("op-show");
|
|
36
36
|
}
|
|
37
37
|
if(data.isAuto && $panel.attr("op-data-value") === "AUTO"){
|
|
@@ -19,6 +19,8 @@ const TimeDisplay = function ($container, api, data) {
|
|
|
19
19
|
let hlsLive = false;
|
|
20
20
|
let nativeHlsLive = false;
|
|
21
21
|
|
|
22
|
+
let currVodPosition = 0;
|
|
23
|
+
|
|
22
24
|
function convertHumanizeTime(time) {
|
|
23
25
|
return naturalHms(time);
|
|
24
26
|
}
|
|
@@ -29,6 +31,7 @@ const TimeDisplay = function ($container, api, data) {
|
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
const onRendered = function ($current, template) {
|
|
34
|
+
currVodPosition = 0;
|
|
32
35
|
let isTimecode = api.isTimecodeMode();
|
|
33
36
|
$position = $current.find(".op-time-current");
|
|
34
37
|
$duration = $current.find(".op-time-duration");
|
|
@@ -48,19 +51,25 @@ const TimeDisplay = function ($container, api, data) {
|
|
|
48
51
|
if (isTimecode) {
|
|
49
52
|
$duration.text(convertHumanizeTime(data.duration));
|
|
50
53
|
} else {
|
|
54
|
+
$position.text(0);
|
|
51
55
|
$duration.text(Math.round(data.duration * api.getFramerate()) + " (" + api.getFramerate() + "fps)");
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
api.on(CONTENT_TIME_MODE_CHANGED, function (isTimecodeMode) {
|
|
55
59
|
isTimecode = isTimecodeMode;
|
|
56
60
|
if (isTimecode) {
|
|
61
|
+
$position.text(convertHumanizeTime(currVodPosition));
|
|
57
62
|
$duration.text(convertHumanizeTime(data.duration));
|
|
58
63
|
} else {
|
|
64
|
+
$position.text(Math.round(currVodPosition * api.getFramerate()));
|
|
59
65
|
$duration.text(Math.round(data.duration * api.getFramerate()) + " (" + api.getFramerate() + "fps)");
|
|
60
66
|
}
|
|
61
67
|
}, template);
|
|
62
68
|
|
|
63
69
|
api.on(CONTENT_TIME, function (data) {
|
|
70
|
+
|
|
71
|
+
currVodPosition = data.position;
|
|
72
|
+
|
|
64
73
|
if (isTimecode) {
|
|
65
74
|
$position.text(convertHumanizeTime(data.position));
|
|
66
75
|
} else {
|
|
@@ -71,7 +80,7 @@ const TimeDisplay = function ($container, api, data) {
|
|
|
71
80
|
if (hlsLive && !nativeHlsLive) {
|
|
72
81
|
api.on(CONTENT_TIME, function (data) {
|
|
73
82
|
if (!api.getConfig().legacyUI) {
|
|
74
|
-
if (
|
|
83
|
+
if (api.getMseInstance().liveSyncPosition - data.position > api.getMseInstance().targetLatency) {
|
|
75
84
|
$liveBadge.addClass('op-live-badge-delayed');
|
|
76
85
|
} else {
|
|
77
86
|
$liveBadge.removeClass('op-live-badge-delayed');
|
|
@@ -105,29 +114,11 @@ const TimeDisplay = function ($container, api, data) {
|
|
|
105
114
|
|
|
106
115
|
event.preventDefault();
|
|
107
116
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const config = api.getConfig();
|
|
112
|
-
if (config.hlsConfig) {
|
|
113
|
-
|
|
114
|
-
const hlsConfig = config.hlsConfig;
|
|
115
|
-
if (typeof hlsConfig.liveSyncDuration === 'number') {
|
|
116
|
-
api.getMseInstance().config.liveSyncDuration
|
|
117
|
-
= hlsConfig.liveSyncDuration;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (typeof hlsConfig.liveMaxLatencyDuration === 'number') {
|
|
121
|
-
api.getMseInstance().config.liveMaxLatencyDuration
|
|
122
|
-
= hlsConfig.liveMaxLatencyDuration;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (typeof hlsConfig.maxLiveSyncPlaybackRate === 'number') {
|
|
126
|
-
api.getMseInstance().config.maxLiveSyncPlaybackRate =
|
|
127
|
-
hlsConfig.maxLiveSyncPlaybackRate;
|
|
128
|
-
}
|
|
117
|
+
if (hlsLive && !nativeHlsLive) {
|
|
118
|
+
const syncPosition = api.getMseInstance().liveSyncPosition;
|
|
119
|
+
api.seek(syncPosition);
|
|
129
120
|
}
|
|
130
|
-
}
|
|
121
|
+
}
|
|
131
122
|
};
|
|
132
123
|
|
|
133
124
|
return OvenTemplate($container, "TimeDisplay", api.getConfig(), data, events, onRendered, onDestroyed);
|