bigscreen-player 7.1.5 → 7.2.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,5 +1,5 @@
1
- import { W as WindowTypes, U as Utils, D as DOMHelpers, b as LiveSupport, M as MediaState, a as DebugToolInstance, P as Plugins, c as MediaKinds, d as TimeUtils, e as DynamicWindowUtils } from './main-ef5f7b81.js';
2
1
  import { MediaPlayer } from 'dashjs/index_mediaplayerOnly';
2
+ import { W as WindowTypes, U as Utils, D as DOMHelpers, b as LiveSupport, a as DebugToolInstance, M as MediaState, P as Plugins, c as MediaKinds, d as TimeUtils, e as DynamicWindowUtils } from './main-70e914fd.js';
3
3
 
4
4
  function filter(manifest, representationOptions) {
5
5
  const constantFps = representationOptions.constantFps;
@@ -162,6 +162,14 @@ function buildSourceAnchor(
162
162
  return wholeSeconds === 0 ? "" : `#t=${wholeSeconds}`
163
163
  }
164
164
 
165
+ function convertTimeRangesToArray(ranges) {
166
+ const array = [];
167
+ for (let rangesSoFar = 0; rangesSoFar < ranges.length; rangesSoFar += 1) {
168
+ array.push([ranges.start(rangesSoFar), ranges.end(rangesSoFar)]);
169
+ }
170
+ return array;
171
+ }
172
+
165
173
  function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD, customPlayerSettings) {
166
174
  let mediaPlayer;
167
175
  let mediaElement;
@@ -223,19 +231,44 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
223
231
  METRIC_ADDED: "metricAdded",
224
232
  METRIC_CHANGED: "metricChanged",
225
233
  STREAM_INITIALIZED: "streamInitialized",
234
+ QUOTA_EXCEEDED: "quotaExceeded",
226
235
  };
227
236
 
237
+ function onLoadedMetaData() {
238
+ DebugToolInstance.event("loadedmetadata", "MediaElement");
239
+ DebugToolInstance.dynamicMetric("ready-state", mediaElement.readyState);
240
+ }
241
+
242
+ function onLoadedData() {
243
+ DebugToolInstance.event("loadeddata", "MediaElement");
244
+ DebugToolInstance.dynamicMetric("ready-state", mediaElement.readyState);
245
+ }
246
+
247
+ function onPlay() {
248
+ DebugToolInstance.event("play", "MediaElement");
249
+ DebugToolInstance.dynamicMetric("paused", mediaElement.paused);
250
+ }
251
+
228
252
  function onPlaying() {
253
+ DebugToolInstance.event("playing", "MediaElement");
254
+ DebugToolInstance.dynamicMetric("ready-state", mediaElement.readyState);
255
+
256
+ getBufferedRanges().map(({ kind, buffered }) => DebugToolInstance.buffered(kind, buffered));
257
+
229
258
  isEnded = false;
230
259
  publishMediaState(MediaState.PLAYING);
231
260
  }
232
261
 
233
262
  function onPaused() {
263
+ DebugToolInstance.event("paused", "MediaElement");
264
+ DebugToolInstance.dynamicMetric("paused", mediaElement.paused);
265
+
234
266
  publishMediaState(MediaState.PAUSED);
235
267
  }
236
268
 
237
269
  function onBuffering() {
238
270
  isEnded = false;
271
+
239
272
  if (!isSeeking || !publishedSeekEvent) {
240
273
  publishMediaState(MediaState.WAITING);
241
274
  publishedSeekEvent = true;
@@ -243,8 +276,10 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
243
276
  }
244
277
 
245
278
  function onSeeked() {
279
+ DebugToolInstance.event("seeked", "MediaElement");
280
+ DebugToolInstance.dynamicMetric("seeking", mediaElement.seeking);
281
+
246
282
  isSeeking = false;
247
- DebugToolInstance.info("Seeked Event");
248
283
 
249
284
  if (isPaused()) {
250
285
  if (windowType === WindowTypes.SLIDING) {
@@ -256,12 +291,38 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
256
291
  }
257
292
  }
258
293
 
294
+ function onSeeking() {
295
+ DebugToolInstance.event("seeking", "MediaElement");
296
+ DebugToolInstance.dynamicMetric("seeking", mediaElement.seeking);
297
+
298
+ onBuffering();
299
+ }
300
+
301
+ function onWaiting() {
302
+ DebugToolInstance.event("waiting", "MediaElement");
303
+ DebugToolInstance.dynamicMetric("ready-state", mediaElement.readyState);
304
+
305
+ getBufferedRanges().map(({ kind, buffered }) => DebugToolInstance.buffered(kind, buffered));
306
+
307
+ onBuffering();
308
+ }
309
+
259
310
  function onEnded() {
311
+ DebugToolInstance.event("ended", "MediaElement");
312
+ DebugToolInstance.dynamicMetric("ended", mediaElement.ended);
313
+
260
314
  isEnded = true;
315
+
261
316
  publishMediaState(MediaState.ENDED);
262
317
  }
263
318
 
319
+ function onRateChange() {
320
+ DebugToolInstance.dynamicMetric("playback-rate", mediaElement.playbackRate);
321
+ }
322
+
264
323
  function onTimeUpdate() {
324
+ DebugToolInstance.updateElementTime(mediaElement.currentTime);
325
+
265
326
  const currentMpdTimeSeconds =
266
327
  windowType === WindowTypes.SLIDING
267
328
  ? mediaPlayer.getDashMetrics().getCurrentDVRInfo(mediaKind)?.time
@@ -288,7 +349,8 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
288
349
  }
289
350
 
290
351
  if (event.error && event.error.message) {
291
- DebugToolInstance.info(`MSE Error: ${event.error.message} Code: ${event.error.code}`);
352
+ DebugToolInstance.error(`${event.error.message} (code: ${event.error.code})`);
353
+
292
354
  lastError = event.error;
293
355
 
294
356
  // Don't raise an error on fragment download error
@@ -313,6 +375,14 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
313
375
  publishError(event.error);
314
376
  }
315
377
 
378
+ function onQuotaExceeded(event) {
379
+ // Note: criticalBufferLevel (Total buffered ranges * 0.8) is set BEFORE this event is triggered,
380
+ // therefore it should actually be `criticalBufferLevel * 1.25` to see what the buffer size was on the device when this happened.
381
+ const bufferLevel = event.criticalBufferLevel * 1.25;
382
+ DebugToolInstance.quotaExceeded(bufferLevel, event.quotaExceededTime);
383
+ Plugins.interface.onQuotaExceeded({ criticalBufferLevel: bufferLevel, quotaExceededTime: event.quotaExceededTime });
384
+ }
385
+
316
386
  function manifestDownloadError(mediaError) {
317
387
  const error = () => publishError(mediaError);
318
388
 
@@ -366,7 +436,7 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
366
436
  ? currentPlaybackBitrate(MediaKinds.VIDEO) + currentPlaybackBitrate(MediaKinds.AUDIO)
367
437
  : currentPlaybackBitrate(MediaKinds.AUDIO);
368
438
 
369
- DebugToolInstance.keyValue({ key: "playback bitrate", value: `${playerMetadata.playbackBitrate} kbps` });
439
+ DebugToolInstance.dynamicMetric("bitrate", playerMetadata.playbackBitrate);
370
440
 
371
441
  Plugins.interface.onPlayerInfoUpdated({
372
442
  bufferLength: playerMetadata.bufferLength,
@@ -374,6 +444,21 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
374
444
  });
375
445
  }
376
446
 
447
+ function getBufferedRanges() {
448
+ if (mediaPlayer == null) {
449
+ return []
450
+ }
451
+
452
+ return mediaPlayer
453
+ .getActiveStream()
454
+ .getProcessors()
455
+ .filter((processor) => processor.getType() === "audio" || processor.getType() === "video")
456
+ .map((processor) => ({
457
+ kind: processor.getType(),
458
+ buffered: convertTimeRangesToArray(processor.getBuffer().getAllBufferRanges()),
459
+ }))
460
+ }
461
+
377
462
  function currentPlaybackBitrate(mediaKind) {
378
463
  const representationSwitch = mediaPlayer.getDashMetrics().getCurrentRepresentationSwitch(mediaKind);
379
464
  const representation = representationSwitch ? representationSwitch.to : "";
@@ -393,24 +478,24 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
393
478
  }
394
479
 
395
480
  function onQualityChangeRendered(event) {
396
- function logBitrate(mediaKind, event) {
397
- const oldBitrate = isNaN(event.oldQuality)
398
- ? "--"
399
- : playbackBitrateForRepresentationIndex(event.oldQuality, mediaKind);
400
- const oldRepresentation = isNaN(event.oldQuality) ? "Start" : `${event.oldQuality} (${oldBitrate} kbps)`;
401
- const newRepresentation = `${event.newQuality} (${playbackBitrateForRepresentationIndex(
402
- event.newQuality,
403
- mediaKind
404
- )} kbps)`;
405
-
406
- DebugToolInstance.keyValue({ key: `${event.mediaType} Representation`, value: newRepresentation });
481
+ function logBitrate(event) {
482
+ const { mediaType, oldQuality, newQuality } = event;
483
+
484
+ const oldBitrate = isNaN(oldQuality) ? "--" : playbackBitrateForRepresentationIndex(oldQuality, mediaType);
485
+ const newBitrate = isNaN(newQuality) ? "--" : playbackBitrateForRepresentationIndex(newQuality, mediaType);
486
+
487
+ const oldRepresentation = isNaN(oldQuality) ? "Start" : `${oldQuality} (${oldBitrate} kbps)`;
488
+ const newRepresentation = `${newQuality} (${newBitrate} kbps)`;
489
+
490
+ DebugToolInstance.dynamicMetric(`representation-${mediaType}`, [newQuality, newBitrate]);
491
+
407
492
  DebugToolInstance.info(
408
- `${mediaKind} ABR Change Rendered From Representation ${oldRepresentation} To ${newRepresentation}`
493
+ `${mediaType} ABR Change Rendered From Representation ${oldRepresentation} To ${newRepresentation}`
409
494
  );
410
495
  }
411
496
 
412
497
  if (event.newQuality !== undefined) {
413
- logBitrate(event.mediaType, event);
498
+ logBitrate(event);
414
499
  }
415
500
 
416
501
  emitPlayerInfo();
@@ -448,14 +533,14 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
448
533
 
449
534
  function onMetricAdded(event) {
450
535
  if (event.mediaType === "video" && event.metric === "DroppedFrames") {
451
- DebugToolInstance.keyValue({ key: "Dropped Frames", value: event.value.droppedFrames });
536
+ DebugToolInstance.staticMetric("frames-dropped", event.value.droppedFrames);
452
537
  }
453
538
  if (event.mediaType === mediaKind && event.metric === "BufferLevel") {
454
539
  dashMetrics = mediaPlayer.getDashMetrics();
455
540
 
456
541
  if (dashMetrics) {
457
542
  playerMetadata.bufferLength = dashMetrics.getCurrentBufferLevel(event.mediaType);
458
- DebugToolInstance.keyValue({ key: "Buffer Length", value: playerMetadata.bufferLength });
543
+ DebugToolInstance.staticMetric("buffer-length", playerMetadata.bufferLength);
459
544
  Plugins.interface.onPlayerInfoUpdated({
460
545
  bufferLength: playerMetadata.bufferLength,
461
546
  playbackBitrate: playerMetadata.playbackBitrate,
@@ -465,7 +550,7 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
465
550
  }
466
551
 
467
552
  function onDebugLog(event) {
468
- DebugToolInstance.verbose(event.message);
553
+ DebugToolInstance.debug(event.message);
469
554
  }
470
555
 
471
556
  function publishMediaState(mediaState) {
@@ -495,13 +580,13 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
495
580
  }
496
581
 
497
582
  function load(mimeType, playbackTime) {
498
- if (!mediaPlayer) {
583
+ if (mediaPlayer) {
584
+ modifySource(refreshFailoverTime || failoverTime, failoverZeroPoint);
585
+ } else {
499
586
  failoverTime = playbackTime;
500
587
  setUpMediaElement(playbackElement);
501
588
  setUpMediaPlayer(playbackTime);
502
589
  setUpMediaListeners();
503
- } else {
504
- modifySource(refreshFailoverTime || failoverTime, failoverZeroPoint);
505
590
  }
506
591
  }
507
592
 
@@ -533,13 +618,23 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
533
618
  }
534
619
 
535
620
  function setUpMediaListeners() {
621
+ DebugToolInstance.dynamicMetric("ended", mediaElement.ended);
622
+ DebugToolInstance.dynamicMetric("paused", mediaElement.paused);
623
+ DebugToolInstance.dynamicMetric("playback-rate", mediaElement.playbackRate);
624
+ DebugToolInstance.dynamicMetric("ready-state", mediaElement.readyState);
625
+ DebugToolInstance.dynamicMetric("seeking", mediaElement.seeking);
626
+
536
627
  mediaElement.addEventListener("timeupdate", onTimeUpdate);
628
+ mediaElement.addEventListener("loadedmetadata", onLoadedMetaData);
629
+ mediaElement.addEventListener("loadeddata", onLoadedData);
630
+ mediaElement.addEventListener("play", onPlay);
537
631
  mediaElement.addEventListener("playing", onPlaying);
538
632
  mediaElement.addEventListener("pause", onPaused);
539
- mediaElement.addEventListener("waiting", onBuffering);
540
- mediaElement.addEventListener("seeking", onBuffering);
633
+ mediaElement.addEventListener("waiting", onWaiting);
634
+ mediaElement.addEventListener("seeking", onSeeking);
541
635
  mediaElement.addEventListener("seeked", onSeeked);
542
636
  mediaElement.addEventListener("ended", onEnded);
637
+ mediaElement.addEventListener("ratechange", onRateChange);
543
638
  mediaPlayer.on(DashJSEvents.ERROR, onError);
544
639
  mediaPlayer.on(DashJSEvents.MANIFEST_LOADED, onManifestLoaded);
545
640
  mediaPlayer.on(DashJSEvents.STREAM_INITIALIZED, onStreamInitialised);
@@ -550,6 +645,7 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
550
645
  mediaPlayer.on(DashJSEvents.LOG, onDebugLog);
551
646
  mediaPlayer.on(DashJSEvents.SERVICE_LOCATION_AVAILABLE, onServiceLocationAvailable);
552
647
  mediaPlayer.on(DashJSEvents.URL_RESOLUTION_FAILED, onURLResolutionFailed);
648
+ mediaPlayer.on(DashJSEvents.QUOTA_EXCEEDED, onQuotaExceeded);
553
649
  }
554
650
 
555
651
  function getSeekableRange() {
@@ -582,13 +678,13 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
582
678
 
583
679
  mediaPlayer.refreshManifest((manifest) => {
584
680
  const mediaPresentationDuration = manifest && manifest.mediaPresentationDuration;
585
- if (!isNaN(mediaPresentationDuration)) {
681
+ if (isNaN(mediaPresentationDuration)) {
682
+ mediaPlayer.seek(seekToTime);
683
+ } else {
586
684
  DebugToolInstance.info("Stream ended. Clamping seek point to end of stream");
587
685
  mediaPlayer.seek(
588
686
  getClampedTime(seekToTime, { start: getSeekableRange().start, end: mediaPresentationDuration })
589
687
  );
590
- } else {
591
- mediaPlayer.seek(seekToTime);
592
688
  }
593
689
  });
594
690
  }
@@ -658,12 +754,16 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
658
754
  mediaPlayer.reset();
659
755
 
660
756
  mediaElement.removeEventListener("timeupdate", onTimeUpdate);
757
+ mediaElement.removeEventListener("loadedmetadata", onLoadedMetaData);
758
+ mediaElement.removeEventListener("loadeddata", onLoadedData);
759
+ mediaElement.removeEventListener("play", onPlay);
661
760
  mediaElement.removeEventListener("playing", onPlaying);
662
761
  mediaElement.removeEventListener("pause", onPaused);
663
- mediaElement.removeEventListener("waiting", onBuffering);
664
- mediaElement.removeEventListener("seeking", onBuffering);
762
+ mediaElement.removeEventListener("waiting", onWaiting);
763
+ mediaElement.removeEventListener("seeking", onSeeking);
665
764
  mediaElement.removeEventListener("seeked", onSeeked);
666
765
  mediaElement.removeEventListener("ended", onEnded);
766
+ mediaElement.removeEventListener("ratechange", onRateChange);
667
767
  mediaPlayer.off(DashJSEvents.ERROR, onError);
668
768
  mediaPlayer.off(DashJSEvents.MANIFEST_LOADED, onManifestLoaded);
669
769
  mediaPlayer.off(DashJSEvents.MANIFEST_VALIDITY_CHANGED, onManifestValidityChange);
@@ -674,6 +774,7 @@ function MSEStrategy(mediaSources, windowType, mediaKind, playbackElement, isUHD
674
774
  mediaPlayer.off(DashJSEvents.LOG, onDebugLog);
675
775
  mediaPlayer.off(DashJSEvents.SERVICE_LOCATION_AVAILABLE, onServiceLocationAvailable);
676
776
  mediaPlayer.off(DashJSEvents.URL_RESOLUTION_FAILED, onURLResolutionFailed);
777
+ mediaPlayer.off(DashJSEvents.QUOTA_EXCEEDED, onQuotaExceeded);
677
778
 
678
779
  DOMHelpers.safeRemoveElement(mediaElement);
679
780
 
package/package.json CHANGED
@@ -1,57 +1,66 @@
1
1
  {
2
2
  "name": "bigscreen-player",
3
- "version": "7.1.5",
3
+ "version": "7.2.0",
4
+ "type": "module",
4
5
  "description": "Simplified media playback for bigscreen devices.",
5
6
  "main": "dist/esm/main.js",
6
7
  "browser": "dist/esm/main.js",
7
8
  "module": "dist/esm/main.js",
8
- "type": "module",
9
+ "types": "dist/esm/main.d.ts",
9
10
  "files": [
10
11
  "dist",
11
12
  "CONTRIBUTING.md"
12
13
  ],
13
14
  "scripts": {
14
- "prepare": "[ ! -d dist/ ] && npm run build || exit 0",
15
- "postinstall": "[ -d .git/ ] && husky install || exit 0",
15
+ "prepare": "if [ ! -d dist/ ]; then npm run build; fi",
16
+ "postinstall": "if [ -d .git/ ]; then husky install; fi",
16
17
  "docs": "jsdoc -c jsdoc.conf.json",
17
- "build": "npm run build:clean && npm run build:bundle",
18
- "build:clean": "rm -rf dist",
19
- "build:bundle": "rollup -c rollup.config.js",
20
- "watch": "rollup -c rollup.config.js -w",
21
- "start": "rollup -c rollup.dev.config.js -w",
18
+ "build": "npm run build:clean && npm run build:bundle && npm run build:tmp",
19
+ "build:clean": "rm -rf dist/*",
20
+ "build:bundle": "rollup --config rollup.config.js",
21
+ "build:tmp": "rm -r dist/esm/__tmp",
22
+ "watch": "rollup --watch --config rollup.config.js",
23
+ "start": "rollup --watch --config rollup.dev.config.js",
22
24
  "test": "jest",
23
25
  "coverage": "jest --coverage",
24
26
  "lint": "eslint ."
25
27
  },
26
28
  "devDependencies": {
27
- "@babel/core": "^7.16.12",
28
- "@babel/eslint-parser": "^7.14.7",
29
- "@babel/preset-env": "^7.16.11",
30
- "@rollup/plugin-alias": "^3.1.4",
31
- "@rollup/plugin-babel": "^5.3.0",
32
- "@rollup/plugin-commonjs": "^16.0.0",
33
- "@rollup/plugin-inject": "^4.0.2",
34
- "@rollup/plugin-json": "^4.1.0",
35
- "@rollup/plugin-node-resolve": "^13.0.4",
36
- "babel-jest": "^27.0.6",
29
+ "@babel/core": "^7.23.7",
30
+ "@babel/plugin-transform-runtime": "^7.23.9",
31
+ "@babel/preset-env": "^7.23.8",
32
+ "@babel/preset-typescript": "^7.23.3",
33
+ "@rollup/plugin-alias": "^5.1.0",
34
+ "@rollup/plugin-babel": "^6.0.4",
35
+ "@rollup/plugin-commonjs": "^25.0.7",
36
+ "@rollup/plugin-inject": "^5.0.5",
37
+ "@rollup/plugin-json": "^6.1.0",
38
+ "@rollup/plugin-node-resolve": "^15.2.3",
39
+ "@rollup/plugin-replace": "^5.0.5",
40
+ "@rollup/plugin-typescript": "^11.1.6",
41
+ "@types/jest": "^29.5.11",
42
+ "babel-jest": "^29.7.0",
43
+ "better-docs": "^2.7.3",
37
44
  "clean-jsdoc-theme": "^4.2.7",
38
- "eslint": "^8.27.0",
39
- "eslint-plugin-import": "^2.26.0",
40
- "eslint-plugin-jest": "^27.1.4",
41
- "eslint-plugin-json": "^3.1.0",
42
- "eslint-plugin-sonarjs": "^0.16.0",
43
- "eslint-plugin-unicorn": "^49.0.0",
45
+ "eslint": "^8.57.0",
46
+ "eslint-plugin-jest": "^27.9.0",
47
+ "eslint-plugin-sonarjs": "^0.23.0",
48
+ "eslint-plugin-unicorn": "^50.0.1",
44
49
  "husky": "^8.0.3",
45
50
  "jest": "^29.5.0",
46
51
  "jest-environment-jsdom": "^29.5.0",
47
52
  "jsdoc": "^4.0.2",
48
- "prettier": "^2.7.1",
49
- "rollup": "^2.54.0",
53
+ "prettier": "^3.1.1",
54
+ "rollup": "^3.29.4",
55
+ "rollup-plugin-dts": "^6.1.0",
50
56
  "rollup-plugin-livereload": "^2.0.5",
51
- "rollup-plugin-polyfill-node": "^0.7.0",
57
+ "rollup-plugin-polyfill-node": "^0.13.0",
52
58
  "rollup-plugin-serve": "^1.1.0",
53
- "rollup-plugin-terser": "^7.0.2",
54
- "rollup-plugin-visualizer": "^5.5.2"
59
+ "rollup-plugin-visualizer": "^5.5.2",
60
+ "ts-jest": "^29.1.1",
61
+ "ts-node": "^10.9.2",
62
+ "typescript": "^5.3.3",
63
+ "typescript-eslint": "^7.2.0"
55
64
  },
56
65
  "dependencies": {
57
66
  "dashjs": "github:bbc/dash.js#smp-v3.2.0-8",