bigscreen-player 10.5.1 → 10.6.1

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.
@@ -0,0 +1,122 @@
1
+ import { fromXML, generateISD, renderHTML } from 'smp-imsc';
2
+ import { U as Utils, a as DebugTool, P as Plugins, D as DOMHelpers } from './main-3a302d13.js';
3
+ import 'tslib';
4
+
5
+ function EmbeddedSubtitles(mediaPlayer, autoStart, parentElement, _mediaSources, defaultStyleOpts) {
6
+ let exampleSubtitlesElement;
7
+ let imscRenderOpts = transformStyleOptions(defaultStyleOpts);
8
+ let subtitlesEnabled = false;
9
+
10
+ if (autoStart) start();
11
+
12
+ function removeExampleSubtitlesElement() {
13
+ if (exampleSubtitlesElement) {
14
+ DOMHelpers.safeRemoveElement(exampleSubtitlesElement);
15
+ exampleSubtitlesElement = undefined;
16
+ }
17
+ }
18
+
19
+ function renderExample(exampleXmlString, styleOpts, safePosition = {}) {
20
+ const exampleXml = fromXML(exampleXmlString);
21
+ removeExampleSubtitlesElement();
22
+
23
+ const customStyleOptions = transformStyleOptions(styleOpts);
24
+ const exampleStyle = Utils.merge(imscRenderOpts, customStyleOptions);
25
+
26
+ exampleSubtitlesElement = document.createElement("div");
27
+ exampleSubtitlesElement.id = "subtitlesPreview";
28
+ exampleSubtitlesElement.style.position = "absolute";
29
+
30
+ const elementWidth = parentElement.clientWidth;
31
+ const elementHeight = parentElement.clientHeight;
32
+ const topPixels = ((safePosition.top || 0) / 100) * elementHeight;
33
+ const rightPixels = ((safePosition.right || 0) / 100) * elementWidth;
34
+ const bottomPixels = ((safePosition.bottom || 0) / 100) * elementHeight;
35
+ const leftPixels = ((safePosition.left || 0) / 100) * elementWidth;
36
+
37
+ const renderWidth = elementWidth - leftPixels - rightPixels;
38
+ const renderHeight = elementHeight - topPixels - bottomPixels;
39
+
40
+ exampleSubtitlesElement.style.top = `${topPixels}px`;
41
+ exampleSubtitlesElement.style.right = `${rightPixels}px`;
42
+ exampleSubtitlesElement.style.bottom = `${bottomPixels}px`;
43
+ exampleSubtitlesElement.style.left = `${leftPixels}px`;
44
+ parentElement.appendChild(exampleSubtitlesElement);
45
+
46
+ renderSubtitle(exampleXml, 1, exampleSubtitlesElement, exampleStyle, renderHeight, renderWidth);
47
+ }
48
+
49
+ function renderSubtitle(xml, currentTime, subsElement, styleOpts, renderHeight, renderWidth) {
50
+ try {
51
+ const isd = generateISD(xml, currentTime);
52
+ renderHTML(isd, subsElement, null, renderHeight, renderWidth, false, null, null, false, styleOpts);
53
+ } catch (error) {
54
+ error.name = "SubtitlesRenderError";
55
+ DebugTool.error(error);
56
+
57
+ Plugins.interface.onSubtitlesRenderError();
58
+ }
59
+ }
60
+
61
+ function start() {
62
+ subtitlesEnabled = true;
63
+ mediaPlayer.setSubtitles(true);
64
+ mediaPlayer.customiseSubtitles(imscRenderOpts);
65
+ }
66
+
67
+ function stop() {
68
+ subtitlesEnabled = false;
69
+ mediaPlayer.setSubtitles(false);
70
+ }
71
+
72
+ function tearDown() {
73
+ stop();
74
+ }
75
+
76
+ function customise(styleOpts) {
77
+ const customStyleOptions = transformStyleOptions(styleOpts);
78
+ imscRenderOpts = Utils.merge(imscRenderOpts, customStyleOptions);
79
+ mediaPlayer.customiseSubtitles(imscRenderOpts);
80
+ if (subtitlesEnabled) {
81
+ stop();
82
+ start();
83
+ }
84
+ }
85
+
86
+ // Opts: { backgroundColour: string (css colour, hex), fontFamily: string , size: number, lineHeight: number }
87
+ function transformStyleOptions(opts) {
88
+ if (opts === undefined) return
89
+
90
+ const customStyles = {};
91
+
92
+ if (opts.backgroundColour) {
93
+ customStyles.spanBackgroundColorAdjust = { transparent: opts.backgroundColour };
94
+ }
95
+
96
+ if (opts.fontFamily) {
97
+ customStyles.fontFamily = opts.fontFamily;
98
+ }
99
+
100
+ if (opts.size > 0) {
101
+ customStyles.sizeAdjust = opts.size;
102
+ }
103
+
104
+ if (opts.lineHeight) {
105
+ customStyles.lineHeightAdjust = opts.lineHeight;
106
+ }
107
+
108
+ return customStyles
109
+ }
110
+
111
+ return {
112
+ start,
113
+ stop,
114
+ updatePosition: () => {},
115
+ customise,
116
+ renderExample,
117
+ clearExample: removeExampleSubtitlesElement,
118
+ tearDown,
119
+ }
120
+ }
121
+
122
+ export { EmbeddedSubtitles as default };
@@ -1,5 +1,5 @@
1
1
  import { fromXML, generateISD, renderHTML } from 'smp-imsc';
2
- import { f as findSegmentTemplate, L as LoadUrl, a as DebugTool, P as Plugins, U as Utils, D as DOMHelpers } from './main-5adbc317.js';
2
+ import { f as findSegmentTemplate, L as LoadUrl, a as DebugTool, P as Plugins, U as Utils, D as DOMHelpers } from './main-3a302d13.js';
3
3
  import 'tslib';
4
4
 
5
5
  const SEGMENTS_BUFFER_SIZE = 3;
@@ -1,4 +1,4 @@
1
- import { D as DOMHelpers, a as DebugTool, P as Plugins, L as LoadUrl, T as TransportControlPosition } from './main-5adbc317.js';
1
+ import { D as DOMHelpers, a as DebugTool, P as Plugins, L as LoadUrl, T as TransportControlPosition } from './main-3a302d13.js';
2
2
  import 'tslib';
3
3
 
4
4
  /**
@@ -5710,7 +5710,7 @@ BasicStrategy.getLiveSupport = () => LiveSupport.SEEKABLE;
5710
5710
  function StrategyPicker() {
5711
5711
  return new Promise((resolve, reject) => {
5712
5712
  if (window.bigscreenPlayer.playbackStrategy === PlaybackStrategy.MSE) {
5713
- return import('./msestrategy-036ce46d.js')
5713
+ return import('./msestrategy-b3ff8486.js')
5714
5714
  .then(({ default: MSEStrategy }) => resolve(MSEStrategy))
5715
5715
  .catch((reason) => {
5716
5716
  const error = new Error(isError(reason) ? reason.message : undefined);
@@ -6051,6 +6051,7 @@ function PlayerComponent(
6051
6051
  errorCallback,
6052
6052
  audioDescribedCallback
6053
6053
  ) {
6054
+ let setSubtitlesState;
6054
6055
  let _stateUpdateCallback = stateUpdateCallback;
6055
6056
 
6056
6057
  let mediaKind = bigscreenPlayerData.media.kind;
@@ -6085,6 +6086,8 @@ function PlayerComponent(
6085
6086
  mediaMetaData = bigscreenPlayerData.media;
6086
6087
 
6087
6088
  loadMedia(bigscreenPlayerData.media.type, bigscreenPlayerData.initialPlaybackTime);
6089
+
6090
+ if (setSubtitlesState) playbackStrategy.setSubtitles(setSubtitlesState);
6088
6091
  })
6089
6092
  .catch((error) => {
6090
6093
  errorCallback && errorCallback(error);
@@ -6104,6 +6107,22 @@ function PlayerComponent(
6104
6107
  }
6105
6108
  }
6106
6109
 
6110
+ function isSubtitlesAvailable() {
6111
+ return playbackStrategy && playbackStrategy.isSubtitlesAvailable()
6112
+ }
6113
+
6114
+ function setSubtitles(state) {
6115
+ if (playbackStrategy) {
6116
+ playbackStrategy.setSubtitles(state);
6117
+ } else {
6118
+ setSubtitlesState = state;
6119
+ }
6120
+ }
6121
+
6122
+ function customiseSubtitles(styleOpts) {
6123
+ return playbackStrategy && playbackStrategy.customiseSubtitles(styleOpts)
6124
+ }
6125
+
6107
6126
  function getDuration() {
6108
6127
  return playbackStrategy?.getDuration()
6109
6128
  }
@@ -6436,8 +6455,10 @@ function PlayerComponent(
6436
6455
  return {
6437
6456
  play,
6438
6457
  pause,
6458
+ customiseSubtitles,
6439
6459
  transitions,
6440
6460
  isEnded,
6461
+ isSubtitlesAvailable,
6441
6462
  setPlaybackRate,
6442
6463
  getPlaybackRate,
6443
6464
  setCurrentTime,
@@ -6450,6 +6471,7 @@ function PlayerComponent(
6450
6471
  isAudioDescribedAvailable,
6451
6472
  isAudioDescribedEnabled,
6452
6473
  setAudioDescribed,
6474
+ setSubtitles,
6453
6475
  }
6454
6476
  }
6455
6477
 
@@ -6465,7 +6487,7 @@ const PauseTriggers = {
6465
6487
  DEVICE: 3,
6466
6488
  };
6467
6489
 
6468
- var Version = "10.5.1";
6490
+ var Version = "10.6.1";
6469
6491
 
6470
6492
  /* eslint-disable no-use-before-define */
6471
6493
 
@@ -7641,6 +7663,8 @@ function findSegmentTemplate(url) {
7641
7663
 
7642
7664
  function Subtitles(mediaPlayer, autoStart, playbackElement, defaultStyleOpts, mediaSources, callback) {
7643
7665
  const useLegacySubs = window.bigscreenPlayer?.overrides?.legacySubtitles ?? false;
7666
+ const embeddedSubs = window.bigscreenPlayer?.overrides?.embeddedSubtitles ?? false;
7667
+
7644
7668
  const isSeekableLiveSupport =
7645
7669
  window.bigscreenPlayer.liveSupport == null || window.bigscreenPlayer.liveSupport === "seekable";
7646
7670
 
@@ -7649,7 +7673,7 @@ function Subtitles(mediaPlayer, autoStart, playbackElement, defaultStyleOpts, me
7649
7673
 
7650
7674
  if (available()) {
7651
7675
  if (useLegacySubs) {
7652
- import('./legacysubtitles-50fa1717.js')
7676
+ import('./legacysubtitles-91115cad.js')
7653
7677
  .then(({ default: LegacySubtitles }) => {
7654
7678
  subtitlesContainer = LegacySubtitles(mediaPlayer, autoStart, playbackElement, mediaSources, defaultStyleOpts);
7655
7679
  callback(subtitlesEnabled);
@@ -7657,8 +7681,23 @@ function Subtitles(mediaPlayer, autoStart, playbackElement, defaultStyleOpts, me
7657
7681
  .catch(() => {
7658
7682
  Plugins.interface.onSubtitlesDynamicLoadError();
7659
7683
  });
7684
+ } else if (embeddedSubs) {
7685
+ import('./embeddedsubtitles-29274c0f.js')
7686
+ .then(({ default: EmbeddedSubtitles }) => {
7687
+ subtitlesContainer = EmbeddedSubtitles(
7688
+ mediaPlayer,
7689
+ autoStart,
7690
+ playbackElement,
7691
+ mediaSources,
7692
+ defaultStyleOpts
7693
+ );
7694
+ callback(subtitlesEnabled);
7695
+ })
7696
+ .catch(() => {
7697
+ Plugins.interface.onSubtitlesDynamicLoadError();
7698
+ });
7660
7699
  } else {
7661
- import('./imscsubtitles-edeb644f.js')
7700
+ import('./imscsubtitles-44eb3000.js')
7662
7701
  .then(({ default: IMSCSubtitles }) => {
7663
7702
  subtitlesContainer = IMSCSubtitles(mediaPlayer, autoStart, playbackElement, mediaSources, defaultStyleOpts);
7664
7703
  callback(subtitlesEnabled);
@@ -7705,6 +7744,10 @@ function Subtitles(mediaPlayer, autoStart, playbackElement, defaultStyleOpts, me
7705
7744
  }
7706
7745
 
7707
7746
  function available() {
7747
+ if (embeddedSubs) {
7748
+ return mediaPlayer && mediaPlayer.isSubtitlesAvailable()
7749
+ }
7750
+
7708
7751
  const url = mediaSources.currentSubtitlesSource();
7709
7752
 
7710
7753
  if (!(typeof url === "string" && url !== "")) {
@@ -7852,13 +7895,6 @@ function BigscreenPlayer() {
7852
7895
  !initialPresentationTime &&
7853
7896
  initialPresentationTime !== 0;
7854
7897
 
7855
- readyHelper = ReadyHelper(
7856
- initialPresentationTime,
7857
- mediaSources.time().manifestType,
7858
- PlayerComponent.getLiveSupport(),
7859
- _callbacks.playerReady
7860
- );
7861
-
7862
7898
  playerComponent = PlayerComponent(
7863
7899
  playbackElement,
7864
7900
  { media, enableAudioDescribed, initialPlaybackTime: initialPresentationTime },
@@ -7868,13 +7904,21 @@ function BigscreenPlayer() {
7868
7904
  callAudioDescribedCallbacks
7869
7905
  );
7870
7906
 
7871
- subtitles = Subtitles(
7872
- playerComponent,
7873
- enableSubtitles,
7874
- playbackElement,
7875
- media.subtitleCustomisation,
7876
- mediaSources,
7877
- callSubtitlesCallbacks
7907
+ readyHelper = ReadyHelper(
7908
+ initialPresentationTime,
7909
+ mediaSources.time().manifestType,
7910
+ PlayerComponent.getLiveSupport(),
7911
+ () => {
7912
+ _callbacks.playerReady && _callbacks.playerReady();
7913
+ subtitles = Subtitles(
7914
+ playerComponent,
7915
+ enableSubtitles,
7916
+ playbackElement,
7917
+ media.subtitleCustomisation,
7918
+ mediaSources,
7919
+ callSubtitlesCallbacks
7920
+ );
7921
+ }
7878
7922
  );
7879
7923
  }
7880
7924
 
package/dist/esm/main.js CHANGED
@@ -1,2 +1,2 @@
1
- export { B as BigscreenPlayer, a as DebugTool, E as EntryCategory, b as LiveSupport, c as ManifestType, M as MediaKinds, d as MediaState, g as MockBigscreenPlayer, h as PauseTriggers, i as PlaybackStrategy, k as Timeline, j as TransferFormat, T as TransportControlPosition, W as WindowTypes, l as isMessage, m as isMetric, n as isTrace } from './main-5adbc317.js';
1
+ export { B as BigscreenPlayer, a as DebugTool, E as EntryCategory, b as LiveSupport, c as ManifestType, M as MediaKinds, d as MediaState, g as MockBigscreenPlayer, h as PauseTriggers, i as PlaybackStrategy, k as Timeline, j as TransferFormat, T as TransportControlPosition, W as WindowTypes, l as isMessage, m as isMetric, n as isTrace } from './main-3a302d13.js';
2
2
  import 'tslib';
@@ -1,5 +1,5 @@
1
1
  import { MediaPlayer } from 'dashjs/index';
2
- import { U as Utils, M as MediaKinds, b as LiveSupport, a as DebugTool, c as ManifestType, d as MediaState, P as Plugins, e as autoResumeAtStartOfRange, D as DOMHelpers } from './main-5adbc317.js';
2
+ import { U as Utils, M as MediaKinds, b as LiveSupport, a as DebugTool, c as ManifestType, d as MediaState, P as Plugins, e as autoResumeAtStartOfRange, D as DOMHelpers } from './main-3a302d13.js';
3
3
  import 'tslib';
4
4
 
5
5
  function filter(manifest, representationOptions) {
@@ -136,6 +136,8 @@ function MSEStrategy(
136
136
 
137
137
  let mediaPlayer;
138
138
  let mediaElement;
139
+ let subtitleElement;
140
+ let subtitlesEnabled = false;
139
141
  const manifestType = mediaSources.time().manifestType;
140
142
 
141
143
  const playerSettings = Utils.merge(
@@ -145,12 +147,15 @@ function MSEStrategy(
145
147
  },
146
148
  streaming: {
147
149
  blacklistExpiryTime: mediaSources.failoverResetTime(),
150
+ lastMediaSettingsCachingInfo: { enabled: false },
148
151
  buffer: {
149
152
  bufferToKeep: 4,
150
153
  bufferTimeAtTopQuality: 12,
151
154
  bufferTimeAtTopQualityLongForm: 15,
152
155
  },
153
- lastMediaSettingsCachingInfo: { enabled: false },
156
+ text: {
157
+ defaultEnabled: false,
158
+ },
154
159
  },
155
160
  },
156
161
  customPlayerSettings
@@ -216,6 +221,7 @@ function MSEStrategy(
216
221
  STREAM_INITIALIZED: "streamInitialized",
217
222
  FRAGMENT_CONTENT_LENGTH_MISMATCH: "fragmentContentLengthMismatch",
218
223
  QUOTA_EXCEEDED: "quotaExceeded",
224
+ TEXT_TRACKS_ADDED: "allTextTracksAdded",
219
225
  CURRENT_TRACK_CHANGED: "currentTrackChanged",
220
226
  };
221
227
 
@@ -663,6 +669,13 @@ function MSEStrategy(
663
669
  }
664
670
  }
665
671
 
672
+ function setUpSubtitleElement(playbackElement) {
673
+ subtitleElement = document.createElement("div");
674
+ subtitleElement.id = "bsp_subtitles";
675
+ subtitleElement.style.position = "absolute";
676
+ playbackElement.appendChild(subtitleElement, playbackElement.firstChild);
677
+ }
678
+
666
679
  function setUpMediaElement(playbackElement) {
667
680
  mediaElement = mediaKind === MediaKinds.AUDIO ? document.createElement("audio") : document.createElement("video");
668
681
 
@@ -686,6 +699,7 @@ function MSEStrategy(
686
699
 
687
700
  function setUpMediaPlayer(presentationTimeInSeconds) {
688
701
  const dashSettings = getDashSettings(playerSettings);
702
+ const embeddedSubs = window.bigscreenPlayer?.overrides?.embeddedSubtitles ?? false;
689
703
  const protectionData = mediaSources.currentProtectionData();
690
704
 
691
705
  mediaPlayer = MediaPlayer().create();
@@ -697,6 +711,11 @@ function MSEStrategy(
697
711
 
698
712
  mediaPlayer.initialize(mediaElement, null);
699
713
 
714
+ if (embeddedSubs) {
715
+ setUpSubtitleElement(playbackElement);
716
+ mediaPlayer.attachTTMLRenderingDiv(subtitleElement);
717
+ }
718
+
700
719
  modifySource(presentationTimeInSeconds);
701
720
  }
702
721
 
@@ -778,10 +797,15 @@ function MSEStrategy(
778
797
  mediaPlayer.on(DashJSEvents.GAP_JUMP, onGapJump);
779
798
  mediaPlayer.on(DashJSEvents.GAP_JUMP_TO_END, onGapJump);
780
799
  mediaPlayer.on(DashJSEvents.QUOTA_EXCEEDED, onQuotaExceeded);
800
+ mediaPlayer.on(DashJSEvents.TEXT_TRACKS_ADDED, handleTextTracks);
781
801
  mediaPlayer.on(DashJSEvents.MANIFEST_LOADING_FINISHED, manifestLoadingFinished);
782
802
  mediaPlayer.on(DashJSEvents.CURRENT_TRACK_CHANGED, onCurrentTrackChanged);
783
803
  }
784
804
 
805
+ function handleTextTracks() {
806
+ mediaPlayer.enableText(subtitlesEnabled);
807
+ }
808
+
785
809
  function manifestLoadingFinished(event) {
786
810
  manifestLoadCount++;
787
811
  manifestRequestTime = event.request.requestEndDate.getTime() - event.request.requestStartDate.getTime();
@@ -808,6 +832,10 @@ function MSEStrategy(
808
832
  : { start: 0, end: getDuration() }
809
833
  }
810
834
 
835
+ function customiseSubtitles(options) {
836
+ return mediaPlayer && mediaPlayer.updateSettings({ streaming: { text: { imsc: { options } } } })
837
+ }
838
+
811
839
  function getDuration() {
812
840
  const duration = mediaPlayer && mediaPlayer.isReady() && mediaPlayer.duration();
813
841
 
@@ -885,6 +913,11 @@ function MSEStrategy(
885
913
  );
886
914
  }
887
915
 
916
+ function isSubtitlesAvailable() {
917
+ const textTracks = mediaPlayer.getTracksFor("text");
918
+ return (textTracks && textTracks.length > 0) ?? false
919
+ }
920
+
888
921
  function isTrackAudioDescribed(track) {
889
922
  return (
890
923
  track.roles.includes("alternate") &&
@@ -963,9 +996,13 @@ function MSEStrategy(
963
996
  mediaElement.removeEventListener("ratechange", onRateChange);
964
997
 
965
998
  DOMHelpers.safeRemoveElement(mediaElement);
966
-
967
999
  mediaElement = undefined;
968
1000
  }
1001
+
1002
+ if (subtitleElement) {
1003
+ DOMHelpers.safeRemoveElement(subtitleElement);
1004
+ subtitleElement = undefined;
1005
+ }
969
1006
  }
970
1007
 
971
1008
  function getSafelySeekableRange() {
@@ -1060,9 +1097,17 @@ function MSEStrategy(
1060
1097
  getCurrentTime,
1061
1098
  isAudioDescribedAvailable,
1062
1099
  isAudioDescribedEnabled,
1100
+ isSubtitlesAvailable,
1063
1101
  setAudioDescribedOn,
1064
1102
  setAudioDescribedOff,
1065
1103
  getDuration,
1104
+ setSubtitles: (state) => {
1105
+ subtitlesEnabled = state ?? false;
1106
+
1107
+ if (mediaPlayer) {
1108
+ mediaPlayer.enableText(subtitlesEnabled);
1109
+ }
1110
+ },
1066
1111
  getPlayerElement: () => mediaElement,
1067
1112
  tearDown,
1068
1113
  reset: () => {
@@ -1072,6 +1117,7 @@ function MSEStrategy(
1072
1117
  },
1073
1118
  isEnded: () => isEnded,
1074
1119
  isPaused,
1120
+ customiseSubtitles,
1075
1121
  pause,
1076
1122
  play: () => mediaPlayer.play(),
1077
1123
  setCurrentTime,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigscreen-player",
3
- "version": "10.5.1",
3
+ "version": "10.6.1",
4
4
  "type": "module",
5
5
  "description": "Simplified media playback for bigscreen devices.",
6
6
  "main": "dist/esm/main.js",
@@ -30,7 +30,7 @@
30
30
  "@babel/plugin-transform-runtime": "^7.23.9",
31
31
  "@babel/preset-env": "^7.23.8",
32
32
  "@babel/preset-typescript": "^7.23.3",
33
- "@rollup/plugin-alias": "^5.1.0",
33
+ "@rollup/plugin-alias": "^5.1.1",
34
34
  "@rollup/plugin-babel": "^6.0.4",
35
35
  "@rollup/plugin-commonjs": "^25.0.7",
36
36
  "@rollup/plugin-inject": "^5.0.5",
@@ -64,7 +64,7 @@
64
64
  "typescript-eslint": "^7.2.0"
65
65
  },
66
66
  "dependencies": {
67
- "dashjs": "github:bbc/dash.js#smp-v4.7.3-6",
67
+ "dashjs": "github:bbc/dash.js#smp-v4.7.3-7",
68
68
  "smp-imsc": "github:bbc/imscJS#v1.0.3"
69
69
  },
70
70
  "repository": {