@gcorevideo/player 2.20.22 → 2.21.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.
Files changed (76) hide show
  1. package/assets/audio-selector/style.scss +48 -82
  2. package/assets/audio-selector/track-selector.ejs +3 -3
  3. package/assets/bottom-gear/bottomgear.ejs +10 -12
  4. package/assets/bottom-gear/gear-sub-menu.scss +0 -15
  5. package/assets/bottom-gear/gear.scss +3 -32
  6. package/assets/media-control/media-control.ejs +5 -20
  7. package/assets/media-control/media-control.scss +124 -34
  8. package/assets/media-control/width370.scss +32 -104
  9. package/assets/picture-in-picture/button.ejs +1 -1
  10. package/assets/picture-in-picture/button.scss +5 -4
  11. package/dist/core.js +148 -23
  12. package/dist/index.css +530 -616
  13. package/dist/index.js +284 -282
  14. package/dist/player.d.ts +19 -16
  15. package/dist/plugins/index.css +1009 -1095
  16. package/dist/plugins/index.js +709 -23402
  17. package/docs/api/player.audioselector.md +4 -59
  18. package/docs/api/player.md +1 -1
  19. package/docs/api/player.mediacontrol.getelement.md +5 -0
  20. package/docs/api/player.mediacontrol.md +14 -0
  21. package/docs/api/{player.audioselector.updatecurrenttrack.md → player.mediacontrol.putelement.md} +7 -7
  22. package/docs/api/player.mediacontrolelement.md +1 -1
  23. package/docs/api/{player.audioselector.starttrackswitch.md → player.pictureinpicture.attributes.md} +5 -7
  24. package/docs/api/player.pictureinpicture.md +45 -0
  25. package/lib/playback/BasePlayback.d.ts +0 -1
  26. package/lib/playback/BasePlayback.d.ts.map +1 -1
  27. package/lib/playback/BasePlayback.js +0 -1
  28. package/lib/playback/HTML5Video.d.ts +4 -0
  29. package/lib/playback/HTML5Video.d.ts.map +1 -1
  30. package/lib/playback/HTML5Video.js +53 -4
  31. package/lib/playback/dash-playback/DashPlayback.d.ts +5 -0
  32. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  33. package/lib/playback/dash-playback/DashPlayback.js +48 -4
  34. package/lib/playback/hls-playback/HlsPlayback.d.ts +31 -25
  35. package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
  36. package/lib/playback/hls-playback/HlsPlayback.js +47 -14
  37. package/lib/plugins/audio-selector/AudioSelector.d.ts +12 -11
  38. package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -1
  39. package/lib/plugins/audio-selector/AudioSelector.js +65 -185
  40. package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -1
  41. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  42. package/lib/plugins/bottom-gear/BottomGear.js +10 -9
  43. package/lib/plugins/level-selector/LevelSelector.js +1 -1
  44. package/lib/plugins/media-control/MediaControl.d.ts +3 -3
  45. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  46. package/lib/plugins/media-control/MediaControl.js +17 -9
  47. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +3 -0
  48. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  49. package/lib/plugins/picture-in-picture/PictureInPicture.js +6 -1
  50. package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
  51. package/lib/plugins/source-controller/SourceController.js +0 -1
  52. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +0 -2
  53. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
  54. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +1 -18
  55. package/lib/testUtils.d.ts.map +1 -1
  56. package/lib/testUtils.js +2 -0
  57. package/package.json +1 -1
  58. package/src/playback/BasePlayback.ts +0 -1
  59. package/src/playback/HTML5Video.ts +57 -4
  60. package/src/playback/dash-playback/DashPlayback.ts +64 -6
  61. package/src/playback/hls-playback/HlsPlayback.ts +82 -40
  62. package/src/plugins/audio-selector/AudioSelector.ts +84 -278
  63. package/src/plugins/bottom-gear/BottomGear.ts +11 -10
  64. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +1 -3
  65. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +14 -37
  66. package/src/plugins/level-selector/LevelSelector.ts +1 -1
  67. package/src/plugins/media-control/MediaControl.ts +18 -13
  68. package/src/plugins/picture-in-picture/PictureInPicture.ts +7 -1
  69. package/src/plugins/source-controller/SourceController.ts +0 -1
  70. package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +1 -20
  71. package/src/testUtils.ts +2 -0
  72. package/src/typings/globals.d.ts +19 -0
  73. package/temp/player.api.json +102 -143
  74. package/tsconfig.tsbuildinfo +1 -1
  75. package/assets/media-control/plugins.scss +0 -94
  76. package/docs/api/player.audioselector.highlightcurrenttrack.md +0 -18
@@ -16,6 +16,9 @@ import HLSJS, {
16
16
  type LevelUpdatedData,
17
17
  type LevelLoadedData,
18
18
  type LevelSwitchingData,
19
+ MediaPlaylist,
20
+ AudioTracksUpdatedData,
21
+ AudioTrackSwitchedData,
19
22
  } from 'hls.js'
20
23
 
21
24
  import {
@@ -32,6 +35,7 @@ import { TimerId } from '../../utils/types.js'
32
35
  import { BasePlayback } from '../BasePlayback.js'
33
36
 
34
37
  import { CLAPPR_VERSION } from '../../build.js'
38
+ import { AudioTrack } from '@clappr/core/types/base/playback/playback.js'
35
39
 
36
40
  const { now } = Utils
37
41
 
@@ -67,10 +71,6 @@ type CustomListener = {
67
71
  once?: boolean
68
72
  }
69
73
 
70
- // TODO level, code, description, etc
71
- type ErrorInfo = Record<string, unknown>
72
-
73
- // @ts-expect-error
74
74
  export default class HlsPlayback extends BasePlayback {
75
75
  private _ccIsSetup = false
76
76
 
@@ -145,7 +145,7 @@ export default class HlsPlayback extends BasePlayback {
145
145
  set currentLevel(id: number) {
146
146
  this._currentLevel = id
147
147
  this.trigger(Events.PLAYBACK_LEVEL_SWITCH_START)
148
- assert.ok(this._hls, 'Hls.js instance is not available')
148
+ assert.ok(this._hls, 'HLS.js is not initialized')
149
149
  if (this.options.playback.hlsUseNextLevel) {
150
150
  this._hls.nextLevel = this._currentLevel
151
151
  } else {
@@ -154,17 +154,17 @@ export default class HlsPlayback extends BasePlayback {
154
154
  }
155
155
 
156
156
  get latency() {
157
- assert.ok(this._hls, 'Hls.js instance is not available')
157
+ assert.ok(this._hls, 'HLS.js is not initialized')
158
158
  return this._hls.latency
159
159
  }
160
160
 
161
161
  get currentProgramDateTime() {
162
- assert.ok(this._hls, 'Hls.js instance is not available')
162
+ assert.ok(this._hls, 'HLS.js is not initialized')
163
163
  assert.ok(this._hls.playingDate, 'Hls.js playingDate is not defined')
164
164
  return this._hls.playingDate
165
165
  }
166
166
 
167
- get _startTime() {
167
+ private get _startTime() {
168
168
  if (
169
169
  this._playbackType === Playback.LIVE &&
170
170
  this._playlistType !== 'EVENT'
@@ -175,13 +175,13 @@ export default class HlsPlayback extends BasePlayback {
175
175
  return this._playableRegionStartTime
176
176
  }
177
177
 
178
- get _now() {
178
+ private get _now() {
179
179
  return now()
180
180
  }
181
181
 
182
182
  // the time in the video element which should represent the start of the sliding window
183
183
  // extrapolated to increase in real time (instead of jumping as the early segments are removed)
184
- get _extrapolatedStartTime() {
184
+ private get _extrapolatedStartTime() {
185
185
  if (!this._localStartTimeCorrelation) {
186
186
  return this._playableRegionStartTime
187
187
  }
@@ -216,7 +216,7 @@ export default class HlsPlayback extends BasePlayback {
216
216
  )
217
217
  }
218
218
 
219
- get _duration() {
219
+ private get _duration() {
220
220
  return this._extrapolatedEndTime - this._startTime
221
221
  }
222
222
 
@@ -237,7 +237,7 @@ export default class HlsPlayback extends BasePlayback {
237
237
  // . . . --> |
238
238
  // . . . .
239
239
  // extrapolatedStartTime
240
- get _extrapolatedWindowDuration() {
240
+ private get _extrapolatedWindowDuration() {
241
241
  if (this._segmentTargetDuration === null) {
242
242
  return 0
243
243
  }
@@ -294,7 +294,7 @@ export default class HlsPlayback extends BasePlayback {
294
294
  this._setInitialState()
295
295
  }
296
296
 
297
- _setInitialState() {
297
+ private _setInitialState() {
298
298
  // @ts-ignore
299
299
  this._minDvrSize =
300
300
  typeof this.options.hlsMinimumDvrSize === 'undefined'
@@ -345,14 +345,14 @@ export default class HlsPlayback extends BasePlayback {
345
345
  this.options.hlsRecoverAttempts || DEFAULT_RECOVER_ATTEMPTS
346
346
  }
347
347
 
348
- _setup() {
348
+ private _setup() {
349
349
  this._destroyHLSInstance()
350
350
  this._createHLSInstance()
351
351
  this._listenHLSEvents()
352
352
  this._attachHLSMedia()
353
353
  }
354
354
 
355
- _destroyHLSInstance() {
355
+ private _destroyHLSInstance() {
356
356
  if (!this._hls) {
357
357
  return
358
358
  }
@@ -364,7 +364,7 @@ export default class HlsPlayback extends BasePlayback {
364
364
  this._hls = null
365
365
  }
366
366
 
367
- _createHLSInstance() {
367
+ private _createHLSInstance() {
368
368
  const config = $.extend(
369
369
  true,
370
370
  {
@@ -378,19 +378,19 @@ export default class HlsPlayback extends BasePlayback {
378
378
  this._hls = new HLSJS(config)
379
379
  }
380
380
 
381
- _attachHLSMedia() {
381
+ private _attachHLSMedia() {
382
382
  if (!this._hls) {
383
383
  return
384
384
  }
385
385
  this._hls.attachMedia(this.el as HTMLMediaElement)
386
386
  }
387
387
 
388
- _listenHLSEvents() {
388
+ private _listenHLSEvents() {
389
389
  if (!this._hls) {
390
390
  return
391
391
  }
392
392
  this._hls.once(HLSJS.Events.MEDIA_ATTACHED, () => {
393
- assert.ok(this._hls, 'Hls.js instance is not available')
393
+ assert.ok(this._hls, 'HLS.js is not initialized')
394
394
  this.options.hlsPlayback.preload && this._hls.loadSource(this.options.src)
395
395
  })
396
396
 
@@ -456,29 +456,33 @@ export default class HlsPlayback extends BasePlayback {
456
456
  HLSJS.Events.SUBTITLE_TRACKS_UPDATED,
457
457
  () => (this._ccTracksUpdated = true),
458
458
  )
459
+ this._hls.on(HlsEvents.AUDIO_TRACKS_UPDATED, (evt, data) =>
460
+ this._onAudioTracksUpdated(evt, data),
461
+ )
462
+ this._hls.on(HlsEvents.AUDIO_TRACK_SWITCHED, (evt, data) => this._onAudioTrackSwitched(evt, data))
459
463
  this.bindCustomListeners()
460
464
  }
461
465
 
462
- bindCustomListeners() {
466
+ private bindCustomListeners() {
463
467
  this.customListeners.forEach((item: CustomListener) => {
464
468
  const requestedEventName = item.eventName
465
469
  const typeOfListener = item.once ? 'once' : 'on'
466
- assert.ok(this._hls, 'Hls.js instance is not available')
470
+ assert.ok(this._hls, 'HLS.js is not initialized')
467
471
  requestedEventName &&
468
472
  this._hls[`${typeOfListener}`](requestedEventName, item.callback)
469
473
  })
470
474
  }
471
475
 
472
- unbindCustomListeners() {
476
+ private unbindCustomListeners() {
473
477
  this.customListeners.forEach((item: CustomListener) => {
474
478
  const requestedEventName = item.eventName
475
479
 
476
- assert.ok(this._hls, 'Hls.js instance is not available')
480
+ assert.ok(this._hls, 'HLS.js is not initialized')
477
481
  requestedEventName && this._hls.off(requestedEventName, item.callback)
478
482
  })
479
483
  }
480
484
 
481
- _onFragmentParsingMetadata(
485
+ private _onFragmentParsingMetadata(
482
486
  evt: HlsEvents.FRAG_PARSING_METADATA,
483
487
  data: FragParsingMetadataData,
484
488
  ) {
@@ -489,13 +493,13 @@ export default class HlsPlayback extends BasePlayback {
489
493
  })
490
494
  }
491
495
 
492
- render() {
496
+ protected override render() {
493
497
  this._ready()
494
498
 
495
499
  return super.render()
496
500
  }
497
501
 
498
- _ready() {
502
+ protected override _ready() {
499
503
  if (this._isReadyState) {
500
504
  return
501
505
  }
@@ -505,7 +509,7 @@ export default class HlsPlayback extends BasePlayback {
505
509
  }
506
510
 
507
511
  private _recover(evt: HlsEvents.ERROR, data: HlsErrorData, error: PlaybackError) {
508
- assert(this._hls, 'Hls.js instance is not available')
512
+ assert(this._hls, 'HLS.js is not initialized')
509
513
  if (!this._recoveredDecodingError) {
510
514
  this._recoveredDecodingError = true
511
515
  this._hls.recoverMediaError()
@@ -528,7 +532,7 @@ export default class HlsPlayback extends BasePlayback {
528
532
  // this playback manages the src on the video element itself
529
533
  protected override _setupSrc(srcUrl: string) {} // eslint-disable-line no-unused-vars
530
534
 
531
- _startTimeUpdateTimer() {
535
+ private _startTimeUpdateTimer() {
532
536
  if (this._timeUpdateTimer) {
533
537
  return
534
538
  }
@@ -538,7 +542,7 @@ export default class HlsPlayback extends BasePlayback {
538
542
  }, 100)
539
543
  }
540
544
 
541
- _stopTimeUpdateTimer() {
545
+ private _stopTimeUpdateTimer() {
542
546
  if (!this._timeUpdateTimer) {
543
547
  return
544
548
  }
@@ -546,7 +550,7 @@ export default class HlsPlayback extends BasePlayback {
546
550
  this._timeUpdateTimer = null
547
551
  }
548
552
 
549
- getProgramDateTime() {
553
+ private getProgramDateTime() {
550
554
  return this._programDateTime ?? 0
551
555
  }
552
556
 
@@ -598,12 +602,12 @@ export default class HlsPlayback extends BasePlayback {
598
602
  this.seek(this.getDuration())
599
603
  }
600
604
 
601
- _updateDvr(status: boolean) {
605
+ private _updateDvr(status: boolean) {
602
606
  this.trigger(Events.PLAYBACK_DVR, status)
603
607
  this.trigger(Events.PLAYBACK_STATS_ADD, { dvr: status })
604
608
  }
605
609
 
606
- _updateSettings() {
610
+ private _updateSettings() {
607
611
  if (this._playbackType === Playback.VOD) {
608
612
  // @ts-expect-error
609
613
  this.settings.left = ['playpause', 'position', 'duration']
@@ -620,7 +624,7 @@ export default class HlsPlayback extends BasePlayback {
620
624
  this.trigger(Events.PLAYBACK_SETTINGSUPDATE)
621
625
  }
622
626
 
623
- _onHLSJSError(evt: HlsEvents.ERROR, data: HlsErrorData) {
627
+ private _onHLSJSError(evt: HlsEvents.ERROR, data: HlsErrorData) {
624
628
  trace(`${T} _onHLSJSError`, {
625
629
  fatal: data.fatal,
626
630
  type: data.type,
@@ -690,10 +694,6 @@ export default class HlsPlayback extends BasePlayback {
690
694
  details: data.details,
691
695
  })
692
696
  error.level = PlayerError.Levels.WARN
693
- // TODO check
694
- // if (data.error instanceof MediaError && data.error.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) {
695
- // error.code = PlaybackErrorCode.MediaSourceUnavailable
696
- // }
697
697
  this._recover(evt, data, error)
698
698
  break
699
699
  default:
@@ -732,7 +732,7 @@ export default class HlsPlayback extends BasePlayback {
732
732
  }
733
733
  }
734
734
 
735
- _keyIsDenied(data: HlsErrorData) {
735
+ private _keyIsDenied(data: HlsErrorData) {
736
736
  return (
737
737
  data.type === HLSJS.ErrorTypes.NETWORK_ERROR &&
738
738
  data.details === HLSJS.ErrorDetails.KEY_LOAD_ERROR &&
@@ -742,7 +742,7 @@ export default class HlsPlayback extends BasePlayback {
742
742
  )
743
743
  }
744
744
 
745
- _onTimeUpdate() {
745
+ private _onTimeUpdate() {
746
746
  const update: TimeUpdate = {
747
747
  current: this.getCurrentTime(),
748
748
  total: this.getDuration(),
@@ -873,7 +873,7 @@ export default class HlsPlayback extends BasePlayback {
873
873
  }
874
874
 
875
875
  private _fillLevels() {
876
- assert.ok(this._hls, 'Hls.js instance is not available')
876
+ assert.ok(this._hls, 'HLS.js is not initialized')
877
877
  this._levels = this._hls.levels.map((level, index) => {
878
878
  return {
879
879
  level: index, // or level.id?
@@ -1109,6 +1109,39 @@ export default class HlsPlayback extends BasePlayback {
1109
1109
  )
1110
1110
  this.stop()
1111
1111
  }
1112
+
1113
+ get audioTracks(): AudioTrack[] {
1114
+ assert.ok(this._hls, 'HLS.js is not initialized')
1115
+ return this._hls.audioTracks.map(toClapprTrack)
1116
+ }
1117
+
1118
+ // @ts-expect-error
1119
+ get currentAudioTrack(): AudioTrack | null {
1120
+ assert.ok(this._hls, 'HLS.js is not initialized')
1121
+ const idx = this._hls.audioTrack
1122
+ const track = this._hls.audioTracks[idx] // TODO or find by .id == idx?
1123
+ if (track) {
1124
+ return toClapprTrack(track)
1125
+ }
1126
+ return null
1127
+ }
1128
+
1129
+ switchAudioTrack(id: string): void {
1130
+ assert.ok(this._hls, 'HLS.js is not initialized')
1131
+ this._hls.audioTrack = Number(id) // TODO or find index by .id == id?
1132
+ }
1133
+
1134
+ private _onAudioTracksUpdated(_: HlsEvents.AUDIO_TRACKS_UPDATED, data: AudioTracksUpdatedData) {
1135
+ trace(`${T} onAudioTracksUpdated`)
1136
+ this.trigger(Events.PLAYBACK_AUDIO_AVAILABLE, data.audioTracks.map(toClapprTrack))
1137
+ }
1138
+
1139
+ private _onAudioTrackSwitched(_: HlsEvents.AUDIO_TRACK_SWITCHED, data: AudioTrackSwitchedData) {
1140
+ trace(`${T} onAudioTrackSwitched`)
1141
+ // @ts-ignore
1142
+ const track = this._hls.audioTracks[data.id]
1143
+ this.trigger(Events.PLAYBACK_AUDIO_CHANGED, toClapprTrack(track))
1144
+ }
1112
1145
  }
1113
1146
 
1114
1147
  HlsPlayback.canPlay = function (resource: string, mimeType?: string): boolean {
@@ -1117,3 +1150,12 @@ HlsPlayback.canPlay = function (resource: string, mimeType?: string): boolean {
1117
1150
  }
1118
1151
  return HLSJS.isSupported()
1119
1152
  }
1153
+
1154
+ function toClapprTrack(t: MediaPlaylist): AudioTrack {
1155
+ return {
1156
+ id: String(t.id),
1157
+ language: t.lang ?? '',
1158
+ kind: t.type === 'main' ? 'main' : 'description', // TODO check
1159
+ label: t.name,
1160
+ }
1161
+ }