bigscreen-player 5.6.7 → 5.7.0

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,11 +1,12 @@
1
1
  import { fromXML, generateISD, renderHTML } from 'smp-imsc';
2
- import { b as TimeUtils, L as LoadUrl, a as DebugTool, P as Plugins, U as Utils, D as DOMHelpers } from './main-dd98eecc.js';
2
+ import { f as findSegmentTemplate, L as LoadUrl, a as DebugTool, P as Plugins, U as Utils, D as DOMHelpers } from './main-ed4ed68c.js';
3
+
4
+ const SEGMENTS_BUFFER_SIZE = 3;
5
+ const LOAD_ERROR_COUNT_MAX = 3;
3
6
 
4
7
  function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defaultStyleOpts) {
5
- const SEGMENTS_TO_KEEP = 3;
6
- const liveSubtitles = !!mediaSources.currentSubtitlesSegmentLength();
7
- const LOAD_ERROR_COUNT_MAX = 3;
8
- const windowStartEpochSeconds = getWindowStartTime() / 1000;
8
+ const windowStartEpochSeconds = mediaSources?.time().windowStartTime / 1000;
9
+ const presentationTimeOffsetSeconds = mediaSources?.time().presentationTimeOffsetSeconds;
9
10
 
10
11
  let imscRenderOpts = transformStyleOptions(defaultStyleOpts);
11
12
  let currentSegmentRendered = {};
@@ -20,14 +21,30 @@ function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defa
20
21
  start();
21
22
  }
22
23
 
24
+ function getTimeOffset() {
25
+ return presentationTimeOffsetSeconds || windowStartEpochSeconds
26
+ }
27
+
28
+ function calculateSegmentNumber() {
29
+ const segmentNumber = Math.floor(getCurrentTime() / mediaSources.currentSubtitlesSegmentLength());
30
+
31
+ // Add 1 as the PTO gives segment '0' relative to the presentation time.
32
+ // DASH segments use one-based indexing, so add 1 to the result of PTO.
33
+ // (Imagine PTO was 0)
34
+ if (typeof presentationTimeOffsetSeconds === "number" && isFinite(presentationTimeOffsetSeconds)) {
35
+ return segmentNumber + 1
36
+ }
37
+
38
+ return segmentNumber
39
+ }
40
+
23
41
  function loadAllRequiredSegments() {
24
42
  const segmentsToLoad = [];
25
- const currentSegment = TimeUtils.calculateSegmentNumber(
26
- windowStartEpochSeconds + mediaPlayer.getCurrentTime(),
27
- mediaSources.currentSubtitlesSegmentLength()
28
- );
29
- for (let index = 0; index < SEGMENTS_TO_KEEP; index++) {
30
- const segmentNumber = currentSegment + index;
43
+
44
+ const currentSegmentNumber = calculateSegmentNumber();
45
+
46
+ for (let offset = 0; offset < SEGMENTS_BUFFER_SIZE; offset++) {
47
+ const segmentNumber = currentSegmentNumber + offset;
31
48
  const alreadyLoaded = segments.some((segment) => segment.number === segmentNumber);
32
49
 
33
50
  if (!alreadyLoaded) {
@@ -35,24 +52,25 @@ function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defa
35
52
  }
36
53
  }
37
54
 
38
- if (SEGMENTS_TO_KEEP === segmentsToLoad.length) {
55
+ if (SEGMENTS_BUFFER_SIZE === segmentsToLoad.length) {
39
56
  // This is to ensure when seeking to a point with no subtitles, don't leave previous subtitle displayed.
40
57
  removeCurrentSubtitlesElement();
41
58
  }
42
59
 
60
+ const segmentsUrlTemplate = mediaSources.currentSubtitlesSource();
61
+ const segmentsTemplate = findSegmentTemplate(segmentsUrlTemplate);
62
+
43
63
  segmentsToLoad.forEach((segmentNumber) => {
44
- const url = mediaSources.currentSubtitlesSource();
45
- loadSegment(url, segmentNumber);
64
+ loadSegment(segmentsUrlTemplate.replace(segmentsTemplate, segmentNumber), segmentNumber);
46
65
  });
47
66
  }
48
67
 
49
68
  function loadSegment(url, segmentNumber) {
50
- const segmentUrl = url.replace("$segment$", segmentNumber);
51
- LoadUrl(segmentUrl, {
69
+ LoadUrl(url, {
52
70
  timeout: mediaSources.subtitlesRequestTimeout(),
53
71
  onLoad: (responseXML, responseText) => {
54
72
  resetLoadErrorCount();
55
- if (!responseXML && !liveSubtitles) {
73
+ if (!responseXML && isSubtitlesWhole()) {
56
74
  DebugTool.info("Error: responseXML is invalid.");
57
75
  Plugins.interface.onSubtitlesXMLError({ cdn: mediaSources.currentSubtitlesCdn() });
58
76
  stop();
@@ -70,7 +88,7 @@ function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defa
70
88
  number: segmentNumber,
71
89
  });
72
90
 
73
- if (segments.length > SEGMENTS_TO_KEEP) {
91
+ if (segments.length > SEGMENTS_BUFFER_SIZE) {
74
92
  pruneSegments();
75
93
  }
76
94
  } catch (error) {
@@ -108,7 +126,9 @@ function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defa
108
126
  DebugTool.info("No more CDNs available for subtitle failover");
109
127
  };
110
128
 
111
- if ((liveSubtitles && loadErrorLimit()) || !liveSubtitles) {
129
+ const isWhole = isSubtitlesWhole();
130
+
131
+ if (isWhole || (!isWhole && loadErrorLimit())) {
112
132
  stop();
113
133
  segments = [];
114
134
  mediaSources.failoverSubtitles(start, errorCase, opts);
@@ -117,7 +137,7 @@ function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defa
117
137
 
118
138
  function pruneSegments() {
119
139
  // Before sorting, check if we've gone back in time, so we know whether to prune from front or back of array
120
- const seekedBack = segments[SEGMENTS_TO_KEEP].number < segments[SEGMENTS_TO_KEEP - 1].number;
140
+ const seekedBack = segments[SEGMENTS_BUFFER_SIZE].number < segments[SEGMENTS_BUFFER_SIZE - 1].number;
121
141
 
122
142
  segments.sort((someSegment, otherSegment) => someSegment.number - otherSegment.number);
123
143
 
@@ -153,10 +173,6 @@ function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defa
153
173
  return customStyles
154
174
  }
155
175
 
156
- function isCurrentTimeBehindCurrentSubtitles(currentTime, segments, segmentIndex) {
157
- return currentTime < segments[segmentIndex].times[currentSegmentRendered.previousSubtitleIndex]
158
- }
159
-
160
176
  function removeCurrentSubtitlesElement() {
161
177
  if (currentSubtitlesElement) {
162
178
  DOMHelpers.safeRemoveElement(currentSubtitlesElement);
@@ -171,22 +187,10 @@ function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defa
171
187
  }
172
188
  }
173
189
 
174
- function update(currentTime) {
175
- const segment = getSegmentToRender(currentTime);
176
-
177
- if (segment) {
178
- render(currentTime, segment.xml);
179
- }
180
- }
181
-
182
190
  function getSegmentToRender(currentTime) {
183
191
  let segment;
184
192
 
185
193
  for (let segmentIndex = 0; segmentIndex < segments.length; segmentIndex++) {
186
- if (isCurrentTimeBehindCurrentSubtitles(currentTime, segments, segmentIndex)) {
187
- removeCurrentSubtitlesElement();
188
- }
189
-
190
194
  for (let timesIndex = 0; timesIndex < segments[segmentIndex].times.length; timesIndex++) {
191
195
  const lastOne = segments[segmentIndex].times.length === timesIndex + 1;
192
196
 
@@ -266,37 +270,49 @@ function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defa
266
270
  }
267
271
 
268
272
  function modifyStyling(xml) {
269
- if (liveSubtitles && xml && xml.head && xml.head.styling) {
273
+ if (!isSubtitlesWhole() && xml?.head?.styling) {
270
274
  xml.head.styling.initials = defaultStyleOpts.initials;
271
275
  }
276
+
272
277
  return xml
273
278
  }
274
279
 
275
- function timeIsValid(time) {
276
- return time > windowStartEpochSeconds
280
+ function isSubtitlesWhole() {
281
+ const subtitlesUrl = mediaSources.currentSubtitlesSource();
282
+
283
+ if (typeof subtitlesUrl !== "string") {
284
+ return false
285
+ }
286
+
287
+ return findSegmentTemplate(subtitlesUrl) == null
277
288
  }
278
289
 
279
- function getCurrentTime() {
280
- return liveSubtitles ? windowStartEpochSeconds + mediaPlayer.getCurrentTime() : mediaPlayer.getCurrentTime()
290
+ function isValidTime(time) {
291
+ return time >= getTimeOffset()
281
292
  }
282
293
 
283
- function getWindowStartTime() {
284
- return mediaSources && mediaSources.time().windowStartTime
294
+ function getCurrentTime() {
295
+ return isSubtitlesWhole() ? mediaPlayer.getCurrentTime() : getTimeOffset() + mediaPlayer.getCurrentTime()
285
296
  }
286
297
 
287
298
  function start() {
288
299
  stop();
300
+
289
301
  const url = mediaSources.currentSubtitlesSource();
302
+ const isWhole = isSubtitlesWhole();
303
+
290
304
  if (url && url !== "") {
291
- if (!liveSubtitles && segments.length === 0) {
305
+ if (isWhole && segments.length === 0) {
292
306
  loadSegment(url);
293
307
  }
294
308
 
295
309
  updateInterval = setInterval(() => {
296
310
  const time = getCurrentTime();
297
- if (liveSubtitles && timeIsValid(time)) {
311
+
312
+ if (!isWhole && isValidTime(time)) {
298
313
  loadAllRequiredSegments();
299
314
  }
315
+
300
316
  update(time);
301
317
  }, 750);
302
318
  }
@@ -307,6 +323,14 @@ function IMSCSubtitles(mediaPlayer, autoStart, parentElement, mediaSources, defa
307
323
  removeCurrentSubtitlesElement();
308
324
  }
309
325
 
326
+ function update(currentTime) {
327
+ const segment = getSegmentToRender(currentTime);
328
+
329
+ if (segment) {
330
+ render(currentTime, segment.xml);
331
+ }
332
+ }
333
+
310
334
  function customise(styleOpts, enabled) {
311
335
  const customStyleOptions = transformStyleOptions(styleOpts);
312
336
  imscRenderOpts = Utils.merge(imscRenderOpts, customStyleOptions);
@@ -1,4 +1,4 @@
1
- import { D as DOMHelpers, a as DebugTool, P as Plugins, L as LoadUrl, T as TransportControlPosition } from './main-dd98eecc.js';
1
+ import { D as DOMHelpers, a as DebugTool, P as Plugins, L as LoadUrl, T as TransportControlPosition } from './main-ed4ed68c.js';
2
2
 
3
3
  /**
4
4
  * Safely checks if an attribute exists on an element.