bigscreen-player 10.2.0 → 10.3.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
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-4fdad7d2.js';
2
+ import { f as findSegmentTemplate, L as LoadUrl, a as DebugTool, P as Plugins, U as Utils, D as DOMHelpers } from './main-4e864739.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-4fdad7d2.js';
1
+ import { D as DOMHelpers, a as DebugTool, P as Plugins, L as LoadUrl, T as TransportControlPosition } from './main-4e864739.js';
2
2
  import 'tslib';
3
3
 
4
4
  /**
@@ -287,6 +287,9 @@ function render({ dynamic: dynamicLogs, static: staticLogs }) {
287
287
  renderStaticLogs(staticLogs);
288
288
  }
289
289
  function renderStaticLog(entry) {
290
+ if (entry == null) {
291
+ return;
292
+ }
290
293
  const { id, key, value } = entry;
291
294
  const existingElement = document.querySelector(`#${id}`);
292
295
  const text = `${key}: ${value}`;
@@ -351,23 +354,85 @@ class DebugViewController {
351
354
  this.dynamicEntries = [];
352
355
  this.latestMetricByKey = {};
353
356
  }
354
- isMerged(metric) {
357
+ isMediaState(metric) {
355
358
  const { kind } = metric;
356
- const mediaStateMetrics = ["ended", "paused", "ready-state", "seeking"];
359
+ const mediaStateMetrics = ["ended", "paused", "playback-rate", "ready-state", "seeking"];
357
360
  return mediaStateMetrics.includes(kind);
358
361
  }
359
362
  mergeMediaState(entry) {
360
- const prevData = this.latestMetricByKey["media-element-state"] == null
361
- ? {}
362
- : this.latestMetricByKey["media-element-state"].data;
363
- const { kind, data } = entry;
364
- return Object.assign(Object.assign({}, entry), { category: "union", kind: "media-element-state", data: Object.assign(Object.assign({}, prevData), { [kind]: data }) });
363
+ const prevEntry = this.latestMetricByKey["media-element-state"] == null
364
+ ? { category: "union", kind: "media-element-state", data: {} }
365
+ : this.latestMetricByKey["media-element-state"];
366
+ const { sessionTime, currentElementTime, kind: metricKind, data: metricData } = entry;
367
+ return Object.assign(Object.assign({}, prevEntry), { sessionTime,
368
+ currentElementTime, data: Object.assign(Object.assign({}, prevEntry.data), { [metricKind]: metricData }) });
369
+ }
370
+ isAudioQuality(metric) {
371
+ const { kind } = metric;
372
+ return ["audio-max-quality", "audio-download-quality", "audio-playback-quality"].includes(kind);
373
+ }
374
+ isVideoQuality(metric) {
375
+ const { kind } = metric;
376
+ return ["video-max-quality", "video-download-quality", "video-playback-quality"].includes(kind);
377
+ }
378
+ mergeVideoQuality(entry) {
379
+ const { sessionTime, currentElementTime, kind: metricKind, data: metricData } = entry;
380
+ const prevEntry = this.latestMetricByKey["video-quality"] == null
381
+ ? { category: "union", kind: "video-quality", data: {} }
382
+ : this.latestMetricByKey["video-quality"];
383
+ const keyForKind = {
384
+ "video-max-quality": "max",
385
+ "video-download-quality": "download",
386
+ "video-playback-quality": "playback",
387
+ };
388
+ return Object.assign(Object.assign({}, prevEntry), { sessionTime,
389
+ currentElementTime, data: Object.assign(Object.assign({}, prevEntry.data), { [keyForKind[metricKind]]: metricData }) });
390
+ }
391
+ mergeAudioQuality(entry) {
392
+ const { sessionTime, currentElementTime, kind: metricKind, data: metricData } = entry;
393
+ const prevEntry = this.latestMetricByKey["audio-quality"] == null
394
+ ? { category: "union", kind: "audio-quality", data: {} }
395
+ : this.latestMetricByKey["audio-quality"];
396
+ const keyForKind = {
397
+ "audio-max-quality": "max",
398
+ "audio-download-quality": "download",
399
+ "audio-playback-quality": "playback",
400
+ };
401
+ return Object.assign(Object.assign({}, prevEntry), { sessionTime,
402
+ currentElementTime, data: Object.assign(Object.assign({}, prevEntry.data), { [keyForKind[metricKind]]: metricData }) });
403
+ }
404
+ mergeMaxBitrate(entry) {
405
+ const { sessionTime, currentElementTime, kind: metricKind, data: [, bitrate], } = entry;
406
+ const prevEntry = this.latestMetricByKey["max-bitrate"] == null
407
+ ? { category: "union", kind: "max-bitrate", data: { audio: 0, video: 0 } }
408
+ : this.latestMetricByKey["max-bitrate"];
409
+ const keyForKind = {
410
+ "audio-max-quality": "audio",
411
+ "video-max-quality": "video",
412
+ };
413
+ return Object.assign(Object.assign({}, prevEntry), { sessionTime,
414
+ currentElementTime, data: Object.assign(Object.assign({}, prevEntry.data), { [keyForKind[metricKind]]: bitrate }) });
365
415
  }
366
416
  cacheEntry(entry) {
367
- const { category } = entry;
417
+ const { category, kind } = entry;
368
418
  switch (category) {
369
419
  case EntryCategory.METRIC:
370
- return this.cacheStaticEntry(this.isMerged(entry) ? this.mergeMediaState(entry) : entry);
420
+ if (this.isMediaState(entry)) {
421
+ this.cacheStaticEntry(this.mergeMediaState(entry));
422
+ return;
423
+ }
424
+ if (kind === "audio-max-quality" || kind === "video-max-quality") {
425
+ this.cacheStaticEntry(this.mergeMaxBitrate(entry));
426
+ }
427
+ if (this.isVideoQuality(entry)) {
428
+ this.cacheStaticEntry(this.mergeVideoQuality(entry));
429
+ return;
430
+ }
431
+ if (this.isAudioQuality(entry)) {
432
+ this.cacheStaticEntry(this.mergeAudioQuality(entry));
433
+ return;
434
+ }
435
+ return this.cacheStaticEntry(entry);
371
436
  case EntryCategory.MESSAGE:
372
437
  case EntryCategory.TRACE:
373
438
  this.cacheDynamicEntry(entry);
@@ -486,9 +551,10 @@ class DebugViewController {
486
551
  const { kind } = entry;
487
552
  const parsedKey = kind.replace(/-/g, " ");
488
553
  const parsedValue = this.serialiseMetric(entry);
489
- return { id: kind, key: parsedKey, value: parsedValue };
554
+ return parsedValue == null ? null : { id: kind, key: parsedKey, value: parsedValue };
490
555
  }
491
556
  serialiseMetric({ kind, data }) {
557
+ var _a, _b, _c, _d, _e, _f;
492
558
  if (typeof data !== "object") {
493
559
  return data;
494
560
  }
@@ -496,7 +562,7 @@ class DebugViewController {
496
562
  const parts = [];
497
563
  const isWaiting = typeof data["ready-state"] === "number" && data["ready-state"] <= 2;
498
564
  if (!isWaiting && !data.paused && !data.seeking) {
499
- parts.push("playing");
565
+ parts.push(data["playback-rate"] === 0 ? "halted at rate 0" : `playing at rate ${(_a = data["playback-rate"]) === null || _a === void 0 ? void 0 : _a.toFixed(2)}`);
500
566
  }
501
567
  if (isWaiting) {
502
568
  parts.push("waiting");
@@ -516,14 +582,27 @@ class DebugViewController {
516
582
  const [start, end] = data;
517
583
  return `${formatDate(new Date(start * 1000))} - ${formatDate(new Date(end * 1000))}`;
518
584
  }
519
- if (kind === "representation-audio" || kind === "representation-video") {
520
- const [qualityIndex, bitrate] = data;
521
- return `${qualityIndex} (${bitrate} kbps)`;
522
- }
523
585
  if (kind === "initial-playback-time") {
524
586
  const [seconds, timeline] = data;
525
587
  return `${seconds}s ${timeline}`;
526
588
  }
589
+ if (kind === "audio-quality" || kind === "video-quality") {
590
+ const [maxQuality] = (_b = data.max) !== null && _b !== void 0 ? _b : [];
591
+ const [downloadQuality, downloadBitrate] = (_c = data.download) !== null && _c !== void 0 ? _c : [];
592
+ const [playbackQuality, playbackBitrate] = (_d = data.playback) !== null && _d !== void 0 ? _d : [];
593
+ const playbackPart = `${((playbackBitrate !== null && playbackBitrate !== void 0 ? playbackBitrate : 0) / 1000).toFixed(0)} kbps (${playbackQuality !== null && playbackQuality !== void 0 ? playbackQuality : 0}/${maxQuality !== null && maxQuality !== void 0 ? maxQuality : 0})`;
594
+ if (playbackQuality === downloadQuality) {
595
+ return playbackPart;
596
+ }
597
+ return `${playbackPart} - downloading ${((downloadBitrate !== null && downloadBitrate !== void 0 ? downloadBitrate : 0) / 1000).toFixed(0)} kbps`;
598
+ }
599
+ if (kind === "max-bitrate") {
600
+ if (data.audio === 0) {
601
+ return null;
602
+ }
603
+ const bitratePart = ((((_e = data.audio) !== null && _e !== void 0 ? _e : 0) + ((_f = data.video) !== null && _f !== void 0 ? _f : 0)) / 1000).toFixed(0);
604
+ return `${bitratePart} kbps`;
605
+ }
527
606
  return data.join(", ");
528
607
  }
529
608
  render() {
@@ -579,7 +658,7 @@ const LogLevels = {
579
658
  INFO: 2,
580
659
  DEBUG: 3,
581
660
  };
582
- function shouldDisplayEntry(entry) {
661
+ function shouldDisplayMediaElemenEvent(entry) {
583
662
  return (!isTrace(entry) ||
584
663
  entry.kind !== "event" ||
585
664
  entry.data.eventTarget !== "MediaElement" ||
@@ -608,12 +687,7 @@ function createDebugTool() {
608
687
  if (typeof newLogLevel !== "number") {
609
688
  return;
610
689
  }
611
- if (newLogLevel === LogLevels.DEBUG) {
612
- viewController.setFilters([]);
613
- }
614
- else {
615
- viewController.setFilters([shouldDisplayEntry]);
616
- }
690
+ viewController.setFilters(newLogLevel === LogLevels.DEBUG ? [] : [shouldDisplayMediaElemenEvent]);
617
691
  currentLogLevel = newLogLevel;
618
692
  }
619
693
  function setRootElement(element) {
@@ -5331,10 +5405,9 @@ const NativeStrategy = (mediaSources, _mediaKind, playbackElement, isUHD) =>
5331
5405
 
5332
5406
  NativeStrategy.getLiveSupport = () => window.bigscreenPlayer.liveSupport;
5333
5407
 
5334
- const MediaKinds = {
5335
- AUDIO: "audio",
5336
- VIDEO: "video",
5337
- };
5408
+ const AUDIO = "audio";
5409
+ const VIDEO = "video";
5410
+ const MediaKinds = { AUDIO, VIDEO };
5338
5411
 
5339
5412
  function BasicStrategy(mediaSources, mediaKind, playbackElement) {
5340
5413
  const CLAMP_OFFSET_SECONDS = 1.1;
@@ -5637,7 +5710,7 @@ BasicStrategy.getLiveSupport = () => LiveSupport.SEEKABLE;
5637
5710
  function StrategyPicker() {
5638
5711
  return new Promise((resolve, reject) => {
5639
5712
  if (window.bigscreenPlayer.playbackStrategy === PlaybackStrategy.MSE) {
5640
- return import('./msestrategy-9d3cfdfe.js')
5713
+ return import('./msestrategy-3666dabc.js')
5641
5714
  .then(({ default: MSEStrategy }) => resolve(MSEStrategy))
5642
5715
  .catch((reason) => {
5643
5716
  const error = new Error(isError(reason) ? reason.message : undefined);
@@ -6392,7 +6465,7 @@ const PauseTriggers = {
6392
6465
  DEVICE: 3,
6393
6466
  };
6394
6467
 
6395
- var Version = "10.2.0";
6468
+ var Version = "10.3.0";
6396
6469
 
6397
6470
  /* eslint-disable no-use-before-define */
6398
6471
 
@@ -7570,7 +7643,7 @@ function Subtitles(mediaPlayer, autoStart, playbackElement, defaultStyleOpts, me
7570
7643
 
7571
7644
  if (available()) {
7572
7645
  if (useLegacySubs) {
7573
- import('./legacysubtitles-54814af0.js')
7646
+ import('./legacysubtitles-0db45bc6.js')
7574
7647
  .then(({ default: LegacySubtitles }) => {
7575
7648
  subtitlesContainer = LegacySubtitles(mediaPlayer, autoStart, playbackElement, mediaSources, defaultStyleOpts);
7576
7649
  callback(subtitlesEnabled);
@@ -7579,7 +7652,7 @@ function Subtitles(mediaPlayer, autoStart, playbackElement, defaultStyleOpts, me
7579
7652
  Plugins.interface.onSubtitlesDynamicLoadError();
7580
7653
  });
7581
7654
  } else {
7582
- import('./imscsubtitles-515e599a.js')
7655
+ import('./imscsubtitles-298f7b8e.js')
7583
7656
  .then(({ default: IMSCSubtitles }) => {
7584
7657
  subtitlesContainer = IMSCSubtitles(mediaPlayer, autoStart, playbackElement, mediaSources, defaultStyleOpts);
7585
7658
  callback(subtitlesEnabled);
@@ -449,8 +449,10 @@ type CreateMetric<Kind extends string, Data extends Primitives> = {
449
449
  kind: Kind;
450
450
  data: Data;
451
451
  };
452
+ type AudioDownloadQuality = CreateMetric<"audio-download-quality", [qualityIndex: number, bitrate: number]>;
453
+ type AudioPlaybackQuality = CreateMetric<"audio-playback-quality", [qualityIndex: number, bitrate: number]>;
454
+ type AudioMaxQuality = CreateMetric<"audio-max-quality", [qualityIndex: number, bitrate: number]>;
452
455
  type AutoResume = CreateMetric<"auto-resume", number>;
453
- type BitRate = CreateMetric<"bitrate", number>;
454
456
  type BufferLength = CreateMetric<"buffer-length", number>;
455
457
  type CDNsAvailable = CreateMetric<"cdns-available", string[]>;
456
458
  type CurrentLatency = CreateMetric<"current-latency", number>;
@@ -464,14 +466,15 @@ type MediaElementPlaybackRate = CreateMetric<"playback-rate", HTMLMediaElement["
464
466
  type MediaElementReadyState = CreateMetric<"ready-state", HTMLMediaElement["readyState"]>;
465
467
  type MediaElementSeeking = CreateMetric<"seeking", HTMLMediaElement["seeking"]>;
466
468
  type PlaybackStrategy = CreateMetric<"strategy", string>;
467
- type RepresentationAudio = CreateMetric<"representation-audio", [qualityIndex: number, bitrate: number]>;
468
- type RepresentationVideo = CreateMetric<"representation-video", [qualityIndex: number, bitrate: number]>;
469
469
  type SeekableRange = CreateMetric<"seekable-range", [start: number, end: number]>;
470
470
  type SubtitleCDNsAvailable = CreateMetric<"subtitle-cdns-available", string[]>;
471
471
  type SubtitleCurrentUrl = CreateMetric<"subtitle-current-url", string>;
472
472
  type TargetLatency = CreateMetric<"target-latency", number>;
473
473
  type Version = CreateMetric<"version", string>;
474
- type Metric = AutoResume | BitRate | BufferLength | CDNsAvailable | CurrentLatency | CurrentUrl | Duration | FramesDropped | InitialPlaybackTime | MediaElementEnded | MediaElementPaused | MediaElementPlaybackRate | MediaElementReadyState | MediaElementSeeking | PlaybackStrategy | RepresentationAudio | RepresentationVideo | SeekableRange | SubtitleCDNsAvailable | SubtitleCurrentUrl | TargetLatency | Version;
474
+ type VideoDownloadQuality = CreateMetric<"video-download-quality", [qualityIndex: number, bitrate: number]>;
475
+ type VideoPlaybackQuality = CreateMetric<"video-playback-quality", [qualityIndex: number, bitrate: number]>;
476
+ type VideoMaxQuality = CreateMetric<"video-max-quality", [qualityIndex: number, bitrate: number]>;
477
+ type Metric = AudioDownloadQuality | AudioMaxQuality | AudioPlaybackQuality | AutoResume | BufferLength | CDNsAvailable | CurrentLatency | CurrentUrl | Duration | FramesDropped | InitialPlaybackTime | MediaElementEnded | MediaElementPaused | MediaElementPlaybackRate | MediaElementReadyState | MediaElementSeeking | PlaybackStrategy | SeekableRange | SubtitleCDNsAvailable | SubtitleCurrentUrl | TargetLatency | Version | VideoDownloadQuality | VideoMaxQuality | VideoPlaybackQuality;
475
478
  type MetricKind = Metric["kind"];
476
479
  type MetricForKind<Kind extends MetricKind> = Extract<Metric, {
477
480
  kind: Kind;
@@ -590,8 +593,8 @@ declare const DebugTool: {
590
593
  }) => void;
591
594
  statechange: (value: MediaState) => void;
592
595
  warn: (...parts: any[]) => void;
593
- dynamicMetric: <Kind extends "auto-resume" | "bitrate" | "buffer-length" | "cdns-available" | "current-latency" | "current-url" | "duration" | "frames-dropped" | "initial-playback-time" | "ended" | "paused" | "playback-rate" | "ready-state" | "seeking" | "strategy" | "representation-audio" | "representation-video" | "seekable-range" | "subtitle-cdns-available" | "subtitle-current-url" | "target-latency" | "version">(kind: Kind, data: MetricForKind<Kind>["data"]) => void;
594
- staticMetric: <Kind_1 extends "auto-resume" | "bitrate" | "buffer-length" | "cdns-available" | "current-latency" | "current-url" | "duration" | "frames-dropped" | "initial-playback-time" | "ended" | "paused" | "playback-rate" | "ready-state" | "seeking" | "strategy" | "representation-audio" | "representation-video" | "seekable-range" | "subtitle-cdns-available" | "subtitle-current-url" | "target-latency" | "version">(kind: Kind_1, data: MetricForKind<Kind_1>["data"]) => void;
596
+ dynamicMetric: <Kind extends "audio-download-quality" | "audio-max-quality" | "audio-playback-quality" | "auto-resume" | "buffer-length" | "cdns-available" | "current-latency" | "current-url" | "duration" | "frames-dropped" | "initial-playback-time" | "ended" | "paused" | "playback-rate" | "ready-state" | "seeking" | "strategy" | "seekable-range" | "subtitle-cdns-available" | "subtitle-current-url" | "target-latency" | "version" | "video-download-quality" | "video-max-quality" | "video-playback-quality">(kind: Kind, data: MetricForKind<Kind>["data"]) => void;
597
+ staticMetric: <Kind_1 extends "audio-download-quality" | "audio-max-quality" | "audio-playback-quality" | "auto-resume" | "buffer-length" | "cdns-available" | "current-latency" | "current-url" | "duration" | "frames-dropped" | "initial-playback-time" | "ended" | "paused" | "playback-rate" | "ready-state" | "seeking" | "strategy" | "seekable-range" | "subtitle-cdns-available" | "subtitle-current-url" | "target-latency" | "version" | "video-download-quality" | "video-max-quality" | "video-playback-quality">(kind: Kind_1, data: MetricForKind<Kind_1>["data"]) => void;
595
598
  hide: () => void;
596
599
  show: () => void;
597
600
  setRootElement: (element: HTMLElement) => void;
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-4fdad7d2.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-4e864739.js';
2
2
  import 'tslib';
@@ -1,5 +1,5 @@
1
1
  import { MediaPlayer } from 'dashjs/index_mediaplayerOnly';
2
- import { U as Utils, b as LiveSupport, M as MediaKinds, a as DebugTool, c as ManifestType, d as MediaState, P as Plugins, e as autoResumeAtStartOfRange, D as DOMHelpers } from './main-4fdad7d2.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-4e864739.js';
3
3
  import 'tslib';
4
4
 
5
5
  function filter(manifest, representationOptions) {
@@ -182,6 +182,10 @@ function MSEStrategy(
182
182
  let manifestLoadCount = 0;
183
183
 
184
184
  let playerMetadata = {
185
+ downloadQuality: {
186
+ [MediaKinds.AUDIO]: undefined,
187
+ [MediaKinds.VIDEO]: undefined,
188
+ },
185
189
  playbackBitrate: undefined,
186
190
  bufferLength: undefined,
187
191
  fragmentInfo: {
@@ -422,16 +426,22 @@ function MSEStrategy(
422
426
  mediaPlayer.setMediaDuration(Number.MAX_SAFE_INTEGER);
423
427
  }
424
428
 
429
+ if (mediaKind === MediaKinds.VIDEO) {
430
+ dispatchDownloadQualityChangeForKind(MediaKinds.VIDEO);
431
+ dispatchMaxQualityChangeForKind(MediaKinds.VIDEO);
432
+ }
433
+
434
+ dispatchMaxQualityChangeForKind(MediaKinds.AUDIO);
435
+ dispatchDownloadQualityChangeForKind(MediaKinds.AUDIO);
436
+
425
437
  emitPlayerInfo();
426
438
  }
427
439
 
428
440
  function emitPlayerInfo() {
429
441
  playerMetadata.playbackBitrate =
430
442
  mediaKind === MediaKinds.VIDEO
431
- ? currentPlaybackBitrate(MediaKinds.VIDEO) + currentPlaybackBitrate(MediaKinds.AUDIO)
432
- : currentPlaybackBitrate(MediaKinds.AUDIO);
433
-
434
- DebugTool.dynamicMetric("bitrate", playerMetadata.playbackBitrate);
443
+ ? currentPlaybackBitrateInKbps(MediaKinds.VIDEO) + currentPlaybackBitrateInKbps(MediaKinds.AUDIO)
444
+ : currentPlaybackBitrateInKbps(MediaKinds.AUDIO);
435
445
 
436
446
  Plugins.interface.onPlayerInfoUpdated({
437
447
  bufferLength: playerMetadata.bufferLength,
@@ -439,6 +449,36 @@ function MSEStrategy(
439
449
  });
440
450
  }
441
451
 
452
+ function dispatchDownloadQualityChangeForKind(kind) {
453
+ const { qualityIndex: prevQualityIndex, bitrateInBps: prevBitrateInBps } =
454
+ playerMetadata.downloadQuality[kind] ?? {};
455
+
456
+ const qualityIndex = mediaPlayer.getQualityFor(kind);
457
+
458
+ if (prevQualityIndex === qualityIndex) {
459
+ return
460
+ }
461
+
462
+ const bitrateInBps = playbackBitrateForRepresentationIndex(qualityIndex, kind);
463
+
464
+ playerMetadata.downloadQuality[kind] = { bitrateInBps, qualityIndex };
465
+
466
+ DebugTool.dynamicMetric(`${kind}-download-quality`, [qualityIndex, bitrateInBps]);
467
+
468
+ const abrChangePart = `ABR ${kind} download quality switched`;
469
+ const switchFromPart =
470
+ prevQualityIndex == null ? "" : ` from ${prevQualityIndex} (${(prevBitrateInBps / 1000).toFixed(0)} kbps)`;
471
+ const switchToPart = ` to ${qualityIndex} (${(bitrateInBps / 1000).toFixed(0)} kbps)`;
472
+
473
+ DebugTool.info(`${abrChangePart}${switchFromPart}${switchToPart}`);
474
+ }
475
+
476
+ function dispatchMaxQualityChangeForKind(kind) {
477
+ const { qualityIndex, bitrate: bitrateInBps } = mediaPlayer.getTopBitrateInfoFor(kind);
478
+
479
+ DebugTool.dynamicMetric(`${kind}-max-quality`, [qualityIndex, bitrateInBps]);
480
+ }
481
+
442
482
  function getBufferedRanges() {
443
483
  if (mediaPlayer == null) {
444
484
  return []
@@ -454,52 +494,49 @@ function MSEStrategy(
454
494
  }))
455
495
  }
456
496
 
457
- function currentPlaybackBitrate(mediaKind) {
497
+ function currentPlaybackBitrateInKbps(mediaKind) {
458
498
  const representationSwitch = mediaPlayer.getDashMetrics().getCurrentRepresentationSwitch(mediaKind);
499
+
459
500
  const representation = representationSwitch ? representationSwitch.to : "";
460
- return playbackBitrateForRepresentation(representation, mediaKind)
501
+
502
+ return playbackBitrateForRepresentation(representation, mediaKind) / 1000
461
503
  }
462
504
 
463
505
  function playbackBitrateForRepresentation(representation, mediaKind) {
464
506
  const repIdx = mediaPlayer.getDashAdapter().getIndexForRepresentation(representation, 0);
507
+
465
508
  return playbackBitrateForRepresentationIndex(repIdx, mediaKind)
466
509
  }
467
510
 
468
511
  function playbackBitrateForRepresentationIndex(index, mediaKind) {
469
- if (index === -1) return ""
512
+ if (index === -1) return 0
470
513
 
471
514
  const bitrateInfoList = mediaPlayer.getBitrateInfoListFor(mediaKind);
472
- return parseInt(bitrateInfoList[index].bitrate / 1000)
473
- }
474
-
475
- function logBitrate(abrType, { mediaType, oldQuality, newQuality }) {
476
- const oldBitrate = isNaN(oldQuality) ? "--" : playbackBitrateForRepresentationIndex(oldQuality, mediaType);
477
- const newBitrate = isNaN(newQuality) ? "--" : playbackBitrateForRepresentationIndex(newQuality, mediaType);
478
-
479
- const oldRepresentation = isNaN(oldQuality) ? "Start" : `${oldQuality} (${oldBitrate} kbps)`;
480
- const newRepresentation = `${newQuality} (${newBitrate} kbps)`;
481
515
 
482
- DebugTool.info(
483
- `${mediaType} ABR Change ${abrType} From Representation ${oldRepresentation} to ${newRepresentation}`
484
- );
516
+ return bitrateInfoList[index].bitrate ?? 0
485
517
  }
486
518
 
487
519
  function onQualityChangeRequested(event) {
488
- if (event.newQuality !== undefined) {
489
- logBitrate("Requested", event);
490
- }
491
-
492
- event.throughput = mediaPlayer.getAverageThroughput(mediaKind);
493
-
494
520
  Plugins.interface.onQualityChangeRequested(event);
495
521
  }
496
522
 
497
523
  function onQualityChangeRendered(event) {
498
- if (event.newQuality !== undefined) {
499
- logBitrate("Rendered", event);
524
+ if (
525
+ event.newQuality !== undefined &&
526
+ (event.mediaType === MediaKinds.AUDIO || event.mediaType === MediaKinds.VIDEO)
527
+ ) {
528
+ const { mediaType, newQuality } = event;
529
+
530
+ DebugTool.dynamicMetric(`${mediaType}-playback-quality`, [
531
+ newQuality,
532
+ playbackBitrateForRepresentationIndex(newQuality, mediaType),
533
+ ]);
534
+
535
+ dispatchMaxQualityChangeForKind(mediaType);
500
536
  }
501
537
 
502
538
  emitPlayerInfo();
539
+
503
540
  Plugins.interface.onQualityChangedRendered(event);
504
541
  }
505
542
 
@@ -540,6 +577,7 @@ function MSEStrategy(
540
577
  if (event.mediaType === "video" && event.metric === "DroppedFrames") {
541
578
  DebugTool.staticMetric("frames-dropped", event.value.droppedFrames);
542
579
  }
580
+
543
581
  if (event.mediaType === mediaKind && event.metric === "BufferLevel") {
544
582
  dashMetrics = mediaPlayer.getDashMetrics();
545
583
 
@@ -552,6 +590,16 @@ function MSEStrategy(
552
590
  });
553
591
  }
554
592
  }
593
+
594
+ if (
595
+ event.metric === "RepSwitchList" &&
596
+ (event.mediaType === MediaKinds.AUDIO || event.mediaType === MediaKinds.VIDEO)
597
+ ) {
598
+ const { mediaType } = event;
599
+
600
+ dispatchDownloadQualityChangeForKind(mediaType);
601
+ dispatchMaxQualityChangeForKind(mediaType);
602
+ }
555
603
  }
556
604
 
557
605
  function onDebugLog(event) {
@@ -850,12 +898,16 @@ function MSEStrategy(
850
898
  const audioTracks = mediaPlayer.getTracksFor("audio");
851
899
  const mainTrack = audioTracks.find((track) => track.roles.includes("main"));
852
900
  mediaPlayer.setCurrentTrack(mainTrack);
901
+
902
+ if (isPaused()) mediaPlayer.play();
853
903
  }
854
904
 
855
905
  function setAudioDescribedOn() {
856
906
  const ADTrack = getAudioDescribedTrack();
857
907
  if (ADTrack) {
858
908
  mediaPlayer.setCurrentTrack(ADTrack);
909
+
910
+ if (isPaused()) mediaPlayer.play();
859
911
  }
860
912
  }
861
913
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bigscreen-player",
3
- "version": "10.2.0",
3
+ "version": "10.3.0",
4
4
  "type": "module",
5
5
  "description": "Simplified media playback for bigscreen devices.",
6
6
  "main": "dist/esm/main.js",