bigscreen-player 5.0.2 → 5.2.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.
- package/README.md +18 -221
- package/dist/esm/{imscsubtitles-000a037d.js → imscsubtitles-65c7604e.js} +1 -1
- package/dist/esm/{legacysubtitles-f8a640e9.js → legacysubtitles-e0e55e63.js} +1 -1
- package/dist/esm/{main-6ba6ec1b.js → main-ab590038.js} +231 -28
- package/dist/esm/main.js +1 -1
- package/dist/esm/{msestrategy-a4167ac9.js → msestrategy-223ded9f.js} +8 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -8,248 +8,45 @@
|
|
|
8
8
|
|
|
9
9
|
*Bigscreen Player* is an open source project developed by the BBC to simplify video and audio playback on a wide range of 'bigscreen' devices (TVs, set-top boxes, games consoles, and streaming devices).
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
For documentation on using this library, please see our [Getting Started guide](https://bbc.github.io/bigscreen-player/api/tutorial-Getting%20Started.html).
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Running Locally
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
The player will render itself into a supplied parent element, and playback will begin as soon as enough data has buffered.
|
|
21
|
-
|
|
22
|
-
```javascript
|
|
23
|
-
import { BigscreenPlayer, MediaKinds, WindowTypes } from 'bigscreen-player'
|
|
24
|
-
|
|
25
|
-
// configure the media player that will be used before loading
|
|
26
|
-
// see below for further details of ths config
|
|
27
|
-
|
|
28
|
-
// options are: msestrategy, nativestrategy, hybridstrategy
|
|
29
|
-
window.bigscreenPlayer.playbackStrategy = 'msestrategy'
|
|
30
|
-
|
|
31
|
-
const bigscreenPlayer = BigscreenPlayer()
|
|
32
|
-
const playbackElement = document.createElement('div')
|
|
33
|
-
const body = document.getElementByTagName('body')[0]
|
|
34
|
-
|
|
35
|
-
playbackElement.id = 'BigscreenPlayback'
|
|
36
|
-
body.appendChild(playbackElement)
|
|
37
|
-
|
|
38
|
-
const minimalData = {
|
|
39
|
-
media: {
|
|
40
|
-
type: 'application/dash+xml',
|
|
41
|
-
urls: [
|
|
42
|
-
{
|
|
43
|
-
url: 'https://example.com/video.mpd'
|
|
44
|
-
}
|
|
45
|
-
]
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const optionalData = {
|
|
50
|
-
initialPlaybackTime: 0, // Time (in seconds) to begin playback from
|
|
51
|
-
media: {
|
|
52
|
-
type: 'application/dash+xml',
|
|
53
|
-
kind: MediaKinds.VIDEO, // Can be VIDEO, or AUDIO
|
|
54
|
-
urls: [
|
|
55
|
-
// Multiple urls offer the ability to fail-over to another CDN if required
|
|
56
|
-
{
|
|
57
|
-
url: 'https://example.com/video.mpd',
|
|
58
|
-
cdn: 'origin' // For Debug Tool reference
|
|
59
|
-
}, {
|
|
60
|
-
url: 'https://failover.example.com/video.mpd',
|
|
61
|
-
cdn: 'failover'
|
|
62
|
-
}
|
|
63
|
-
],
|
|
64
|
-
captions: [{
|
|
65
|
-
url: 'https://example.com/captions/$segment$', // $segment$ required for replacement for live subtitle segments
|
|
66
|
-
segmentLength: 3.84, // Required to calculate live subtitle segment to fetch & live subtitle URL.
|
|
67
|
-
cdn: 'origin' // Displayed by Debug Tool
|
|
68
|
-
}, {
|
|
69
|
-
url: 'https://failover.example.com/captions/$segment$',
|
|
70
|
-
segmentLength: 3.84,
|
|
71
|
-
cdn: 'failover'
|
|
72
|
-
}
|
|
73
|
-
],
|
|
74
|
-
captionsUrl: 'https://example.com/imsc-doc.xml', // NB This parameter is being deprecated in favour of the captions array shown above.
|
|
75
|
-
subtitlesRequestTimeout: 5000, // Optional override for the XHR timeout on sidecar loaded subtitles
|
|
76
|
-
subtitleCustomisation: {
|
|
77
|
-
size: 0.75,
|
|
78
|
-
lineHeight: 1.10,
|
|
79
|
-
fontFamily: 'Arial',
|
|
80
|
-
backgroundColour: 'black' // (css colour, hex)
|
|
81
|
-
},
|
|
82
|
-
playerSettings: { // This currently can be used to customise settings for the msestrategy. It is a pass through of all the dash.js player settings.
|
|
83
|
-
failoverSort: failoverSort, // Post failover custom sorting algorithm
|
|
84
|
-
failoverResetTime: 60000,
|
|
85
|
-
streaming: {
|
|
86
|
-
bufferToKeep: 8
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// STATIC for VOD content, GROWING/SLIDING for LIVE content
|
|
93
|
-
const windowType = WindowTypes.STATIC
|
|
94
|
-
const enableSubtitles = false
|
|
95
|
-
|
|
96
|
-
bigscreenPlayer.init(playbackElement, optionalData, windowType, enableSubtitles)
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### Configuration
|
|
100
|
-
|
|
101
|
-
Bigscreen Player has some global configuration that is needed before initialisation. A *playback strategy* may be configured, or defaulted to the native Html5 strategy:
|
|
102
|
-
|
|
103
|
-
```javascript
|
|
104
|
-
window.bigscreenPlayer.playbackStrategy = 'msestrategy' // OR 'nativestrategy' OR 'hybridstrategy'
|
|
15
|
+
Install dependencies:
|
|
16
|
+
```bash
|
|
17
|
+
$ npm install
|
|
105
18
|
```
|
|
106
19
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
State changes which are emitted from the player can be acted upon to by registering a callback. The callback will receive all of the following state changes as the `state` property of the event:
|
|
112
|
-
- `MediaState.STOPPED`
|
|
113
|
-
- `MediaState.PAUSED`
|
|
114
|
-
- `MediaState.PLAYING`
|
|
115
|
-
- `MediaState.WAITING`
|
|
116
|
-
- `MediaState.ENDED`
|
|
117
|
-
- `MediaState.FATAL_ERROR`
|
|
118
|
-
|
|
119
|
-
State changes may be registered for before initialisation and will automatically be cleared upon `tearDown()` of the player.
|
|
120
|
-
|
|
121
|
-
```javascript
|
|
122
|
-
const bigscreenPlayer = BigscreenPlayer()
|
|
123
|
-
|
|
124
|
-
// The token is only required in the case where the function is anonymous, a reference to the function can be stored and used to unregister otherwise.
|
|
125
|
-
var stateChangeToken = bigscreenPlayer.registerForStateChanges(function (event) {
|
|
126
|
-
if(event.state == MediaState.PLAYING) {
|
|
127
|
-
console.log('Playing')
|
|
128
|
-
// handle playing event
|
|
129
|
-
}
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
bigscreenPlayer.unregisterForStateChanges(stateChangeToken)
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
### Reacting to time updates
|
|
136
|
-
|
|
137
|
-
Time updates are emitted multiple times a second. Your application can register to receive these updates. The emitted object contains the `currentTime` and `endOfStream` properties.
|
|
138
|
-
|
|
139
|
-
Time updates may be registered for before initialisation and will automatically be cleared upon `tearDown()` of the player.
|
|
140
|
-
|
|
141
|
-
```javascript
|
|
142
|
-
var bigscreenPlayer = BigscreenPlayer();
|
|
143
|
-
|
|
144
|
-
// The token is only required in the case where the function is anonymous, a reference to the function can be stored and used to unregister otherwise.
|
|
145
|
-
var timeUpdateToken = bigscreenPlayer.registerForTimeUpdates(function (event) {
|
|
146
|
-
console.log('Current Time: ' + event.currentTime);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
bigscreenPlayer.unRegisterForTimeUpdates(timeUpdateToken);
|
|
20
|
+
You can run Bigscreen Player locally in a dev environment by running:
|
|
21
|
+
```bash
|
|
22
|
+
$ npm run start
|
|
150
23
|
```
|
|
151
24
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
This is emitted on every `setSubtitlesEnabled` call. The emitted object contains an `enabled` property.
|
|
155
|
-
|
|
156
|
-
This may be registered for before initialisation and will automatically be cleared upon `tearDown()` of the player.
|
|
157
|
-
|
|
158
|
-
```javascript
|
|
159
|
-
var bigscreenPlayer = BigscreenPlayer();
|
|
160
|
-
|
|
161
|
-
// The token is only required in the case where the function is anonymous, a reference to the function can be stored and used to unregister otherwise.
|
|
162
|
-
var subtitleChangeToken = bigscreenPlayer.registerForSubtitleChanges(function (event) {
|
|
163
|
-
console.log('Subttiles enabled: ' + event.enabled);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
bigscreenPlayer.unregisterForSubtitleChanges(subtitleChangeToken);
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### Creating a plugin
|
|
170
|
-
|
|
171
|
-
Plugins can be created to extend the functionality of the Bigscreen Player by adhering to an interface which propagates non state change events from the player. For example, when an error is raised or cleared.
|
|
172
|
-
|
|
173
|
-
The full interface is as follows:
|
|
174
|
-
- `onError`
|
|
175
|
-
- `onFatalError`
|
|
176
|
-
- `onErrorCleared`
|
|
177
|
-
- `onErrorHandled`
|
|
178
|
-
- `onBuffering`
|
|
179
|
-
- `onBufferingCleared`
|
|
180
|
-
- `onScreenCapabilityDetermined`
|
|
181
|
-
|
|
182
|
-
An example plugin may look like:
|
|
183
|
-
|
|
184
|
-
```javascript
|
|
185
|
-
function ExamplePlugin (appName) {
|
|
186
|
-
|
|
187
|
-
var name = appName;
|
|
188
|
-
|
|
189
|
-
function onFatalError (evt) {
|
|
190
|
-
console.log('A fatal error has occured in the app: ' + name);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function onErrorHandled (evt) {
|
|
194
|
-
console.log('The ' + name + ' app is handling a playback error');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return {
|
|
198
|
-
onFatalError: onFatalError,
|
|
199
|
-
onErrorHandled: onErrorHandled
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
```javascript
|
|
205
|
-
var bigscreenPlayer = BigscreenPlayer();
|
|
206
|
-
|
|
207
|
-
var examplePlugin = ExamplePlugin('myApp');
|
|
208
|
-
|
|
209
|
-
bigscreenPlayer.registerPlugin(examplePlugin);
|
|
210
|
-
|
|
211
|
-
// initialise bigscreenPlayer - see above
|
|
212
|
-
|
|
213
|
-
// you should unregister your plugins as part of your playback cleanup
|
|
214
|
-
|
|
215
|
-
// calling with no argument will unregister all plugins
|
|
216
|
-
bigscreenPlayer.unregisterPlugin(examplePlugin);
|
|
217
|
-
|
|
218
|
-
```
|
|
25
|
+
This will open a web page at `localhost:8080`.
|
|
219
26
|
|
|
220
27
|
## Testing
|
|
221
28
|
|
|
222
29
|
The project is unit tested using [Jest](https://jestjs.io/). To run the tests:
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
30
|
+
```bash
|
|
31
|
+
$ npm test
|
|
32
|
+
```
|
|
226
33
|
This project currently has unit test coverage but no integration test suite. This is on our Roadmap to address.
|
|
227
34
|
|
|
228
|
-
### Mocking media playback
|
|
229
|
-
|
|
230
|
-
When writing tests for your application it may be useful to use the mocking functions provided. This creates a fake player with mocking hook functions to simulate real world scenarios.
|
|
231
|
-
|
|
232
|
-
See [here](https://github.com/bbc/bigscreen-player/wiki/Mocking-Bigscreen-Player) for example usage.
|
|
233
|
-
|
|
234
35
|
## Releasing
|
|
235
36
|
|
|
236
37
|
1. Create a PR.
|
|
237
|
-
2. Label the PR with one of these labels
|
|
238
|
-
- `semver prerelease`
|
|
239
|
-
- `semver patch`
|
|
240
|
-
- `semver minor`
|
|
241
|
-
- `semver major`
|
|
242
|
-
|
|
38
|
+
2. Label the PR with one of these labels; `semver prerelease`, `semver patch`, `semver minor` or `semver major`
|
|
243
39
|
3. Get a review from the core team.
|
|
244
40
|
4. If the PR checks are green. The core team can merge to master.
|
|
245
41
|
5. Automation takes care of the package versioning.
|
|
246
42
|
6. Publishing to NPM is handled with our [GitHub Actions CI integration](https://github.com/bbc/bigscreen-player/blob/master/.github/workflows/npm-publish.yml).
|
|
247
43
|
|
|
44
|
+
## Documentation
|
|
248
45
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
46
|
+
Bigscreen Player uses JSDocs to autogenerate API documentation. To regenerate the documentation run:
|
|
47
|
+
```bash
|
|
48
|
+
$ npm run docs
|
|
49
|
+
```
|
|
253
50
|
|
|
254
51
|
## Contributing
|
|
255
52
|
|
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
2
|
+
import { b as TimeUtils, L as LoadUrl, a as DebugTool, P as Plugins, U as Utils, D as DOMHelpers } from './main-ab590038.js';
|
|
3
3
|
|
|
4
4
|
function IMSCSubtitles (mediaPlayer, autoStart, parentElement, mediaSources, defaultStyleOpts) {
|
|
5
5
|
const SEGMENTS_TO_KEEP = 3;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as DOMHelpers, a as DebugTool, P as Plugins, L as LoadUrl, T as TransportControlPosition } from './main-
|
|
1
|
+
import { D as DOMHelpers, a as DebugTool, P as Plugins, L as LoadUrl, T as TransportControlPosition } from './main-ab590038.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Safely checks if an attribute exists on an element.
|
|
@@ -13,9 +13,17 @@ const MediaState = {
|
|
|
13
13
|
FATAL_ERROR: 6
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Enums for WindowTypes
|
|
18
|
+
* @readonly
|
|
19
|
+
* @enum {string}
|
|
20
|
+
*/
|
|
16
21
|
const WindowTypes = {
|
|
22
|
+
/** Media with a duration */
|
|
17
23
|
STATIC: 'staticWindow',
|
|
24
|
+
/** Media with a start time but without a duration until an indeterminate time in the future */
|
|
18
25
|
GROWING: 'growingWindow',
|
|
26
|
+
/** Media with a rewind window that progresses through a media timeline */
|
|
19
27
|
SLIDING: 'slidingWindow'
|
|
20
28
|
};
|
|
21
29
|
|
|
@@ -236,6 +244,8 @@ var Plugins = {
|
|
|
236
244
|
onBufferingCleared: (evt) => callOnAllPlugins('onBufferingCleared', evt),
|
|
237
245
|
onScreenCapabilityDetermined: (tvInfo) => callOnAllPlugins('onScreenCapabilityDetermined', tvInfo),
|
|
238
246
|
onPlayerInfoUpdated: (evt) => callOnAllPlugins('onPlayerInfoUpdated', evt),
|
|
247
|
+
onManifestLoaded: (manifest) => callOnAllPlugins('onManifestLoaded', manifest),
|
|
248
|
+
onQualityChangedRendered: (evt) => callOnAllPlugins('onQualityChangedRendered', evt),
|
|
239
249
|
onSubtitlesLoadError: (evt) => callOnAllPlugins('onSubtitlesLoadError', evt),
|
|
240
250
|
onSubtitlesTimeout: (evt) => callOnAllPlugins('onSubtitlesTimeout', evt),
|
|
241
251
|
onSubtitlesXMLError: (evt) => callOnAllPlugins('onSubtitlesXMLError', evt),
|
|
@@ -836,21 +846,7 @@ if (instance === undefined) {
|
|
|
836
846
|
|
|
837
847
|
var DebugTool$1 = instance;
|
|
838
848
|
|
|
839
|
-
function PlaybackSpinner () {
|
|
840
|
-
const spinnerContainer = document.createElement('div');
|
|
841
|
-
spinnerContainer.id = 'loadingSpinner';
|
|
842
|
-
spinnerContainer.className = 'loadingSpinner loadingSpinner--large ';
|
|
843
|
-
|
|
844
|
-
const spinner = document.createElement('div');
|
|
845
|
-
spinner.className = 'loadingSpinner__spinner';
|
|
846
|
-
|
|
847
|
-
spinnerContainer.appendChild(spinner);
|
|
848
|
-
|
|
849
|
-
return spinnerContainer
|
|
850
|
-
}
|
|
851
|
-
|
|
852
849
|
function LiveGlitchCurtain (parentElement) {
|
|
853
|
-
let spinner = new PlaybackSpinner();
|
|
854
850
|
let curtain = document.createElement('div');
|
|
855
851
|
|
|
856
852
|
curtain.id = 'liveGlitchCurtain';
|
|
@@ -862,8 +858,6 @@ function LiveGlitchCurtain (parentElement) {
|
|
|
862
858
|
curtain.style.bottom = 0;
|
|
863
859
|
curtain.style.backgroundColor = '#3c3c3c';
|
|
864
860
|
|
|
865
|
-
curtain.appendChild(spinner);
|
|
866
|
-
|
|
867
861
|
return {
|
|
868
862
|
showCurtain: () => {
|
|
869
863
|
curtain.style.display = 'block';
|
|
@@ -872,15 +866,10 @@ function LiveGlitchCurtain (parentElement) {
|
|
|
872
866
|
|
|
873
867
|
hideCurtain: () => {
|
|
874
868
|
curtain.style.display = 'none';
|
|
875
|
-
DOMHelpers.safeRemoveElement(spinner);
|
|
876
869
|
},
|
|
877
870
|
|
|
878
871
|
tearDown: () => {
|
|
879
872
|
DOMHelpers.safeRemoveElement(curtain);
|
|
880
|
-
|
|
881
|
-
if (spinner) {
|
|
882
|
-
spinner = undefined;
|
|
883
|
-
}
|
|
884
873
|
}
|
|
885
874
|
}
|
|
886
875
|
}
|
|
@@ -5684,12 +5673,12 @@ function StrategyPicker (windowType, isUHD) {
|
|
|
5684
5673
|
return resolve(NativeStrategy)
|
|
5685
5674
|
}
|
|
5686
5675
|
|
|
5687
|
-
return import('./msestrategy-
|
|
5676
|
+
return import('./msestrategy-223ded9f.js').then(({default: MSEStrategy}) => resolve(MSEStrategy))
|
|
5688
5677
|
.catch(() => {
|
|
5689
5678
|
reject({error: 'strategyDynamicLoadError'});
|
|
5690
5679
|
})
|
|
5691
5680
|
} else if (window.bigscreenPlayer.playbackStrategy === PlaybackStrategy.MSE) {
|
|
5692
|
-
return import('./msestrategy-
|
|
5681
|
+
return import('./msestrategy-223ded9f.js').then(({default: MSEStrategy}) => resolve(MSEStrategy))
|
|
5693
5682
|
.catch(() => {
|
|
5694
5683
|
reject({error: 'strategyDynamicLoadError'});
|
|
5695
5684
|
})
|
|
@@ -6069,7 +6058,7 @@ function CallCallbacks (callbacks, data) {
|
|
|
6069
6058
|
callbacks.forEach((callback) => DeferExceptions(() => callback(data)));
|
|
6070
6059
|
}
|
|
6071
6060
|
|
|
6072
|
-
var version = "5.
|
|
6061
|
+
var version = "5.2.1";
|
|
6073
6062
|
|
|
6074
6063
|
var sourceList;
|
|
6075
6064
|
var source;
|
|
@@ -7255,14 +7244,14 @@ function Subtitles (mediaPlayer, autoStart, playbackElement, defaultStyleOpts, m
|
|
|
7255
7244
|
let subtitlesContainer;
|
|
7256
7245
|
|
|
7257
7246
|
if (useLegacySubs) {
|
|
7258
|
-
import('./legacysubtitles-
|
|
7247
|
+
import('./legacysubtitles-e0e55e63.js').then(({default: LegacySubtitles}) => {
|
|
7259
7248
|
subtitlesContainer = LegacySubtitles(mediaPlayer, autoStart, playbackElement, mediaSources, defaultStyleOpts);
|
|
7260
7249
|
callback(subtitlesEnabled);
|
|
7261
7250
|
}).catch(() => {
|
|
7262
7251
|
Plugins.interface.onSubtitlesDynamicLoadError();
|
|
7263
7252
|
});
|
|
7264
7253
|
} else {
|
|
7265
|
-
import('./imscsubtitles-
|
|
7254
|
+
import('./imscsubtitles-65c7604e.js').then(({default: IMSCSubtitles}) => {
|
|
7266
7255
|
subtitlesContainer = IMSCSubtitles(mediaPlayer, autoStart, playbackElement, mediaSources, defaultStyleOpts);
|
|
7267
7256
|
callback(subtitlesEnabled);
|
|
7268
7257
|
}).catch(() => {
|
|
@@ -7337,6 +7326,10 @@ function Subtitles (mediaPlayer, autoStart, playbackElement, defaultStyleOpts, m
|
|
|
7337
7326
|
}
|
|
7338
7327
|
}
|
|
7339
7328
|
|
|
7329
|
+
/**
|
|
7330
|
+
* @module bigscreenplayer/bigscreenplayer
|
|
7331
|
+
*/
|
|
7332
|
+
|
|
7340
7333
|
function BigscreenPlayer () {
|
|
7341
7334
|
let stateChangeCallbacks = [];
|
|
7342
7335
|
let timeUpdateCallbacks = [];
|
|
@@ -7494,7 +7487,19 @@ function BigscreenPlayer () {
|
|
|
7494
7487
|
return subtitles ? subtitles.available() : false
|
|
7495
7488
|
}
|
|
7496
7489
|
|
|
7497
|
-
return {
|
|
7490
|
+
return /** @alias module:bigscreenplayer/bigscreenplayer */{
|
|
7491
|
+
|
|
7492
|
+
/**
|
|
7493
|
+
* Call first to initialise bigscreen player for playback.
|
|
7494
|
+
* @function
|
|
7495
|
+
* @name init
|
|
7496
|
+
* @param {HTMLDivElement} playbackElement - The Div element where content elements should be rendered
|
|
7497
|
+
* @param {BigscreenPlayerData} bigscreenPlayerData
|
|
7498
|
+
* @param {WindowTypes} newWindowType
|
|
7499
|
+
* @param {boolean} enableSubtitles - Enable subtitles on initialisation
|
|
7500
|
+
* @param {TALDevice} newDevice - An optional TAL device object
|
|
7501
|
+
* @param {InitCallbacks} callbacks
|
|
7502
|
+
*/
|
|
7498
7503
|
init: (newPlaybackElement, bigscreenPlayerData, newWindowType, enableSubtitles, callbacks) => {
|
|
7499
7504
|
playbackElement = newPlaybackElement;
|
|
7500
7505
|
Chronicle.init();
|
|
@@ -7531,6 +7536,11 @@ function BigscreenPlayer () {
|
|
|
7531
7536
|
mediaSources.init(bigscreenPlayerData.media, serverDate, windowType, getLiveSupport(), mediaSourceCallbacks);
|
|
7532
7537
|
},
|
|
7533
7538
|
|
|
7539
|
+
/**
|
|
7540
|
+
* Should be called at the end of all playback sessions. Resets state and clears any UI.
|
|
7541
|
+
* @function
|
|
7542
|
+
* @name tearDown
|
|
7543
|
+
*/
|
|
7534
7544
|
tearDown: function () {
|
|
7535
7545
|
if (subtitles) {
|
|
7536
7546
|
subtitles.tearDown();
|
|
@@ -7560,11 +7570,22 @@ function BigscreenPlayer () {
|
|
|
7560
7570
|
Chronicle.tearDown();
|
|
7561
7571
|
},
|
|
7562
7572
|
|
|
7573
|
+
/**
|
|
7574
|
+
* Pass a function to call whenever the player transitions state.
|
|
7575
|
+
* @see {@link module:models/mediastate}
|
|
7576
|
+
* @function
|
|
7577
|
+
* @param {Function} callback
|
|
7578
|
+
*/
|
|
7563
7579
|
registerForStateChanges: (callback) => {
|
|
7564
7580
|
stateChangeCallbacks.push(callback);
|
|
7565
7581
|
return callback
|
|
7566
7582
|
},
|
|
7567
7583
|
|
|
7584
|
+
/**
|
|
7585
|
+
* Unregisters a previously registered callback.
|
|
7586
|
+
* @function
|
|
7587
|
+
* @param {Function} callback
|
|
7588
|
+
*/
|
|
7568
7589
|
unregisterForStateChanges: (callback) => {
|
|
7569
7590
|
const indexOf = stateChangeCallbacks.indexOf(callback);
|
|
7570
7591
|
if (indexOf !== -1) {
|
|
@@ -7572,11 +7593,21 @@ function BigscreenPlayer () {
|
|
|
7572
7593
|
}
|
|
7573
7594
|
},
|
|
7574
7595
|
|
|
7596
|
+
/**
|
|
7597
|
+
* Pass a function to call whenever the player issues a time update.
|
|
7598
|
+
* @function
|
|
7599
|
+
* @param {Function} callback
|
|
7600
|
+
*/
|
|
7575
7601
|
registerForTimeUpdates: (callback) => {
|
|
7576
7602
|
timeUpdateCallbacks.push(callback);
|
|
7577
7603
|
return callback
|
|
7578
7604
|
},
|
|
7579
7605
|
|
|
7606
|
+
/**
|
|
7607
|
+
* Unregisters a previously registered callback.
|
|
7608
|
+
* @function
|
|
7609
|
+
* @param {Function} callback
|
|
7610
|
+
*/
|
|
7580
7611
|
unregisterForTimeUpdates: (callback) => {
|
|
7581
7612
|
const indexOf = timeUpdateCallbacks.indexOf(callback);
|
|
7582
7613
|
|
|
@@ -7585,11 +7616,21 @@ function BigscreenPlayer () {
|
|
|
7585
7616
|
}
|
|
7586
7617
|
},
|
|
7587
7618
|
|
|
7619
|
+
/**
|
|
7620
|
+
* Pass a function to be called whenever subtitles are enabled or disabled.
|
|
7621
|
+
* @function
|
|
7622
|
+
* @param {Function} callback
|
|
7623
|
+
*/
|
|
7588
7624
|
registerForSubtitleChanges: (callback) => {
|
|
7589
7625
|
subtitleCallbacks.push(callback);
|
|
7590
7626
|
return callback
|
|
7591
7627
|
},
|
|
7592
7628
|
|
|
7629
|
+
/**
|
|
7630
|
+
* Unregisters a previously registered callback for changes to subtitles.
|
|
7631
|
+
* @function
|
|
7632
|
+
* @param {Function} callback
|
|
7633
|
+
*/
|
|
7593
7634
|
unregisterForSubtitleChanges: (callback) => {
|
|
7594
7635
|
const indexOf = subtitleCallbacks.indexOf(callback);
|
|
7595
7636
|
if (indexOf !== -1) {
|
|
@@ -7597,6 +7638,11 @@ function BigscreenPlayer () {
|
|
|
7597
7638
|
}
|
|
7598
7639
|
},
|
|
7599
7640
|
|
|
7641
|
+
/**
|
|
7642
|
+
* Sets the current time of the media asset.
|
|
7643
|
+
* @function
|
|
7644
|
+
* @param {Number} time - In seconds
|
|
7645
|
+
*/
|
|
7600
7646
|
setCurrentTime: function (time) {
|
|
7601
7647
|
DebugTool$1.apicall('setCurrentTime');
|
|
7602
7648
|
if (playerComponent) {
|
|
@@ -7614,15 +7660,46 @@ function BigscreenPlayer () {
|
|
|
7614
7660
|
},
|
|
7615
7661
|
|
|
7616
7662
|
getPlaybackRate: () => playerComponent && playerComponent.getPlaybackRate(),
|
|
7663
|
+
|
|
7664
|
+
/**
|
|
7665
|
+
* Returns the media asset's current time in seconds.
|
|
7666
|
+
* @function
|
|
7667
|
+
*/
|
|
7617
7668
|
getCurrentTime: () => playerComponent && playerComponent.getCurrentTime() || 0,
|
|
7669
|
+
|
|
7670
|
+
/**
|
|
7671
|
+
* Returns the current media kind.
|
|
7672
|
+
* 'audio' or 'video'
|
|
7673
|
+
* @function
|
|
7674
|
+
*/
|
|
7618
7675
|
getMediaKind: () => mediaKind,
|
|
7676
|
+
|
|
7677
|
+
/**
|
|
7678
|
+
* Returns the current window type.
|
|
7679
|
+
* @see {@link module:bigscreenplayer/models/windowtypes}
|
|
7680
|
+
* @function
|
|
7681
|
+
*/
|
|
7619
7682
|
getWindowType: () => windowType,
|
|
7683
|
+
|
|
7684
|
+
/**
|
|
7685
|
+
* Returns an object including the current start and end times.
|
|
7686
|
+
* @function
|
|
7687
|
+
* @returns {Object} {start: Number, end: Number}
|
|
7688
|
+
*/
|
|
7620
7689
|
getSeekableRange: () => playerComponent ? playerComponent.getSeekableRange() : {},
|
|
7621
7690
|
|
|
7691
|
+
/**
|
|
7692
|
+
* @function
|
|
7693
|
+
* @returns {boolean} Returns true if media is initialised and playing a live stream within a tolerance of the end of the seekable range (10 seconds).
|
|
7694
|
+
*/
|
|
7622
7695
|
isPlayingAtLiveEdge: function () {
|
|
7623
7696
|
return !!playerComponent && windowType !== WindowTypes.STATIC && Math.abs(this.getSeekableRange().end - this.getCurrentTime()) < END_OF_STREAM_TOLERANCE
|
|
7624
7697
|
},
|
|
7625
7698
|
|
|
7699
|
+
/**
|
|
7700
|
+
* @function
|
|
7701
|
+
* @return {Object} An object of the shape {windowStartTime: Number, windowEndTime: Number, initialPlaybackTime: Number, serverDate: Date}
|
|
7702
|
+
*/
|
|
7626
7703
|
getLiveWindowData: () => {
|
|
7627
7704
|
if (windowType === WindowTypes.STATIC) {
|
|
7628
7705
|
return {}
|
|
@@ -7636,15 +7713,39 @@ function BigscreenPlayer () {
|
|
|
7636
7713
|
}
|
|
7637
7714
|
},
|
|
7638
7715
|
|
|
7716
|
+
/**
|
|
7717
|
+
* @function
|
|
7718
|
+
* @returns the duration of the media asset.
|
|
7719
|
+
*/
|
|
7639
7720
|
getDuration: () => playerComponent && playerComponent.getDuration(),
|
|
7721
|
+
|
|
7722
|
+
/**
|
|
7723
|
+
* @function
|
|
7724
|
+
* @returns if the player is paused.
|
|
7725
|
+
*/
|
|
7640
7726
|
isPaused: () => playerComponent ? playerComponent.isPaused() : true,
|
|
7727
|
+
|
|
7728
|
+
/**
|
|
7729
|
+
* @function
|
|
7730
|
+
* @returns if the media asset has ended.
|
|
7731
|
+
*/
|
|
7641
7732
|
isEnded: () => playerComponent ? playerComponent.isEnded() : false,
|
|
7642
7733
|
|
|
7734
|
+
/**
|
|
7735
|
+
* Play the media assest from the current point in time.
|
|
7736
|
+
* @function
|
|
7737
|
+
*/
|
|
7643
7738
|
play: () => {
|
|
7644
7739
|
DebugTool$1.apicall('play');
|
|
7645
7740
|
playerComponent.play();
|
|
7646
7741
|
},
|
|
7647
|
-
|
|
7742
|
+
/**
|
|
7743
|
+
* Pause the media asset.
|
|
7744
|
+
* @function
|
|
7745
|
+
* @param {*} opts
|
|
7746
|
+
* @param {boolean} opts.userPause
|
|
7747
|
+
* @param {boolean} opts.disableAutoResume
|
|
7748
|
+
*/
|
|
7648
7749
|
pause: (opts) => {
|
|
7649
7750
|
DebugTool$1.apicall('pause');
|
|
7650
7751
|
pauseTrigger = opts && opts.userPause === false ? PauseTriggers.APP : PauseTriggers.USER;
|
|
@@ -7665,8 +7766,23 @@ function BigscreenPlayer () {
|
|
|
7665
7766
|
resizer.clear(playbackElement);
|
|
7666
7767
|
},
|
|
7667
7768
|
|
|
7769
|
+
/**
|
|
7770
|
+
* Set whether or not subtitles should be enabled.
|
|
7771
|
+
* @function
|
|
7772
|
+
* @param {boolean} value
|
|
7773
|
+
*/
|
|
7668
7774
|
setSubtitlesEnabled: setSubtitlesEnabled,
|
|
7775
|
+
|
|
7776
|
+
/**
|
|
7777
|
+
* @function
|
|
7778
|
+
* @return if subtitles are currently enabled.
|
|
7779
|
+
*/
|
|
7669
7780
|
isSubtitlesEnabled: isSubtitlesEnabled,
|
|
7781
|
+
|
|
7782
|
+
/**
|
|
7783
|
+
* @function
|
|
7784
|
+
* @return Returns whether or not subtitles are currently enabled.
|
|
7785
|
+
*/
|
|
7670
7786
|
isSubtitlesAvailable: isSubtitlesAvailable,
|
|
7671
7787
|
|
|
7672
7788
|
areSubtitlesCustomisable: () => {
|
|
@@ -7691,45 +7807,132 @@ function BigscreenPlayer () {
|
|
|
7691
7807
|
}
|
|
7692
7808
|
},
|
|
7693
7809
|
|
|
7810
|
+
/**
|
|
7811
|
+
*
|
|
7812
|
+
* An enum may be used to set the on-screen position of any transport controls
|
|
7813
|
+
* (work in progress to remove this - UI concern).
|
|
7814
|
+
* @function
|
|
7815
|
+
* @param {*} position
|
|
7816
|
+
*/
|
|
7694
7817
|
setTransportControlsPosition: (position) => {
|
|
7695
7818
|
if (subtitles) {
|
|
7696
7819
|
subtitles.setPosition(position);
|
|
7697
7820
|
}
|
|
7698
7821
|
},
|
|
7699
7822
|
|
|
7823
|
+
/**
|
|
7824
|
+
* @function
|
|
7825
|
+
* @return Returns whether the current media asset is seekable.
|
|
7826
|
+
*/
|
|
7700
7827
|
canSeek: function () {
|
|
7701
7828
|
return windowType === WindowTypes.STATIC || DynamicWindowUtils.canSeek(getWindowStartTime(), getWindowEndTime(), getLiveSupport(), this.getSeekableRange())
|
|
7702
7829
|
},
|
|
7703
7830
|
|
|
7831
|
+
/**
|
|
7832
|
+
* @function
|
|
7833
|
+
* @return Returns whether the current media asset is pausable.
|
|
7834
|
+
*/
|
|
7704
7835
|
canPause: () => {
|
|
7705
7836
|
return windowType === WindowTypes.STATIC || DynamicWindowUtils.canPause(getWindowStartTime(), getWindowEndTime(), getLiveSupport())
|
|
7706
7837
|
},
|
|
7707
7838
|
|
|
7839
|
+
/**
|
|
7840
|
+
* Return a mock for in place testing.
|
|
7841
|
+
* @function
|
|
7842
|
+
* @param {*} opts
|
|
7843
|
+
*/
|
|
7708
7844
|
mock: function (opts) { MockBigscreenPlayer.mock(this, opts); },
|
|
7845
|
+
|
|
7846
|
+
/**
|
|
7847
|
+
* Unmock the player.
|
|
7848
|
+
* @function
|
|
7849
|
+
*/
|
|
7709
7850
|
unmock: function () { MockBigscreenPlayer.unmock(this); },
|
|
7851
|
+
|
|
7852
|
+
/**
|
|
7853
|
+
* Return a mock for unit tests.
|
|
7854
|
+
* @function
|
|
7855
|
+
* @param {*} opts
|
|
7856
|
+
*/
|
|
7710
7857
|
mockJasmine: function (opts) { MockBigscreenPlayer.mockJasmine(this, opts); },
|
|
7711
7858
|
|
|
7859
|
+
/**
|
|
7860
|
+
* Register a plugin for extended events.
|
|
7861
|
+
* @function
|
|
7862
|
+
* @param {*} plugin
|
|
7863
|
+
*/
|
|
7712
7864
|
registerPlugin: (plugin) => Plugins.registerPlugin(plugin),
|
|
7865
|
+
|
|
7866
|
+
/**
|
|
7867
|
+
* Unregister a previously registered plugin.
|
|
7868
|
+
* @function
|
|
7869
|
+
* @param {*} plugin
|
|
7870
|
+
*/
|
|
7713
7871
|
unregisterPlugin: (plugin) => Plugins.unregisterPlugin(plugin),
|
|
7872
|
+
|
|
7873
|
+
/**
|
|
7874
|
+
* Returns an object with a number of functions related to the ability to transition state
|
|
7875
|
+
* given the current state and the playback strategy in use.
|
|
7876
|
+
* @function
|
|
7877
|
+
*/
|
|
7714
7878
|
transitions: () => playerComponent ? playerComponent.transitions() : {},
|
|
7879
|
+
|
|
7880
|
+
/**
|
|
7881
|
+
* @function
|
|
7882
|
+
* @return The media element currently being used.
|
|
7883
|
+
*/
|
|
7715
7884
|
getPlayerElement: () => playerComponent && playerComponent.getPlayerElement(),
|
|
7716
7885
|
|
|
7886
|
+
/**
|
|
7887
|
+
* @function
|
|
7888
|
+
* @param {Number} epochTime - Unix Epoch based time in milliseconds.
|
|
7889
|
+
* @return the time in seconds within the current sliding window.
|
|
7890
|
+
*/
|
|
7717
7891
|
convertEpochMsToVideoTimeSeconds: (epochTime) => {
|
|
7718
7892
|
return getWindowStartTime() ? Math.floor((epochTime - getWindowStartTime()) / 1000) : undefined
|
|
7719
7893
|
},
|
|
7720
7894
|
|
|
7895
|
+
/**
|
|
7896
|
+
* @function
|
|
7897
|
+
* @return The runtime version of the library.
|
|
7898
|
+
*/
|
|
7721
7899
|
getFrameworkVersion: () => {
|
|
7722
7900
|
return version
|
|
7723
7901
|
},
|
|
7724
7902
|
|
|
7903
|
+
/**
|
|
7904
|
+
* @function
|
|
7905
|
+
* @param {Number} time - Seconds
|
|
7906
|
+
* @return the time in milliseconds within the current sliding window.
|
|
7907
|
+
*/
|
|
7725
7908
|
convertVideoTimeSecondsToEpochMs: convertVideoTimeSecondsToEpochMs,
|
|
7909
|
+
|
|
7910
|
+
/**
|
|
7911
|
+
* Toggle the visibility of the debug tool overlay.
|
|
7912
|
+
* @function
|
|
7913
|
+
*/
|
|
7726
7914
|
toggleDebug: toggleDebug,
|
|
7915
|
+
|
|
7916
|
+
/**
|
|
7917
|
+
* @function
|
|
7918
|
+
* @return {Object} - Key value pairs of available log levels
|
|
7919
|
+
*/
|
|
7727
7920
|
getLogLevels: () => DebugTool$1.logLevels,
|
|
7921
|
+
|
|
7922
|
+
/**
|
|
7923
|
+
* @function
|
|
7924
|
+
* @param logLevel - log level to display @see getLogLevels
|
|
7925
|
+
*/
|
|
7728
7926
|
setLogLevel: DebugTool$1.setLogLevel,
|
|
7729
7927
|
getDebugLogs: () => Chronicle.retrieve()
|
|
7730
7928
|
}
|
|
7731
7929
|
}
|
|
7732
7930
|
|
|
7931
|
+
/**
|
|
7932
|
+
* @function
|
|
7933
|
+
* @param {TALDevice} device
|
|
7934
|
+
* @return the live support of the device.
|
|
7935
|
+
*/
|
|
7733
7936
|
function getLiveSupport () {
|
|
7734
7937
|
return PlayerComponent.getLiveSupport()
|
|
7735
7938
|
}
|
package/dist/esm/main.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { B as BigscreenPlayer, c as LiveSupport, d as MediaKinds, M as MediaState, f as MockBigscreenPlayer, g as PauseTriggers, h as PlaybackStrategy, i as TransferFormat, T as TransportControlPosition, W as WindowTypes } from './main-
|
|
1
|
+
export { B as BigscreenPlayer, c as LiveSupport, d as MediaKinds, M as MediaState, f as MockBigscreenPlayer, g as PauseTriggers, h as PlaybackStrategy, i as TransferFormat, T as TransportControlPosition, W as WindowTypes } from './main-ab590038.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as DOMHelpers, W as WindowTypes, c as LiveSupport, M as MediaState, a as DebugTool,
|
|
1
|
+
import { D as DOMHelpers, W as WindowTypes, c as LiveSupport, M as MediaState, a as DebugTool, P as Plugins, d as MediaKinds, U as Utils, b as TimeUtils, e as DynamicWindowUtils } from './main-ab590038.js';
|
|
2
2
|
import { MediaPlayer } from 'dashjs/index_mediaplayerOnly';
|
|
3
3
|
|
|
4
4
|
function filter (manifest, representationOptions) {
|
|
@@ -259,9 +259,15 @@ function MSEStrategy (mediaSources, windowType, mediaKind, playbackElement, isUH
|
|
|
259
259
|
|
|
260
260
|
ManifestModifier.filter(manifest, representationOptions);
|
|
261
261
|
ManifestModifier.generateBaseUrls(manifest, mediaSources.availableSources());
|
|
262
|
+
|
|
263
|
+
emitManifestInfo(manifest);
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
266
|
|
|
267
|
+
function emitManifestInfo (manifest) {
|
|
268
|
+
Plugins.interface.onManifestLoaded(manifest);
|
|
269
|
+
}
|
|
270
|
+
|
|
265
271
|
function onManifestValidityChange (event) {
|
|
266
272
|
DebugTool.info('Manifest validity changed. Duration is: ' + event.newDuration);
|
|
267
273
|
}
|
|
@@ -325,6 +331,7 @@ function MSEStrategy (mediaSources, windowType, mediaKind, playbackElement, isUH
|
|
|
325
331
|
}
|
|
326
332
|
|
|
327
333
|
emitPlayerInfo();
|
|
334
|
+
Plugins.interface.onQualityChangedRendered(event);
|
|
328
335
|
}
|
|
329
336
|
|
|
330
337
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bigscreen-player",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"description": "Simplified media playback for bigscreen devices.",
|
|
5
5
|
"main": "dist/esm/main.js",
|
|
6
6
|
"browser": "dist/esm/main.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
17
|
"prepare": "[ ! -d dist/ ] && npm run build || exit 0",
|
|
18
|
+
"docs": "npx jsdoc -c jsdoc.conf.json",
|
|
18
19
|
"build": "rollup -c rollup.config.js",
|
|
19
20
|
"start": "rollup -c rollup.dev.config.js -w",
|
|
20
21
|
"test": "jest",
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
"@rollup/plugin-json": "^4.1.0",
|
|
38
39
|
"@rollup/plugin-node-resolve": "^13.0.4",
|
|
39
40
|
"babel-jest": "^27.0.6",
|
|
41
|
+
"clean-jsdoc-theme": "^3.2.7",
|
|
40
42
|
"eslint": "^7.2.0",
|
|
41
43
|
"eslint-plugin-es5": "1.3.1",
|
|
42
44
|
"eslint-plugin-jest": "^24.4.0",
|
|
@@ -45,6 +47,7 @@
|
|
|
45
47
|
"eslint-plugin-standard": "4.0.0",
|
|
46
48
|
"husky": "^4.2.5",
|
|
47
49
|
"jest": "^27.0.6",
|
|
50
|
+
"jsdoc": "^3.6.4",
|
|
48
51
|
"rollup": "^2.54.0",
|
|
49
52
|
"rollup-plugin-livereload": "^2.0.5",
|
|
50
53
|
"rollup-plugin-polyfill-node": "^0.7.0",
|