@gcorevideo/player 2.3.1 → 2.4.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.
package/src/Player.ts CHANGED
@@ -13,19 +13,20 @@ import type {
13
13
  CorePlayerEvents,
14
14
  CoreOptions,
15
15
  CorePluginOptions,
16
+ PlayerMediaSource,
16
17
  } from './internal.types.js'
17
18
  import type {
18
19
  PlaybackType,
19
20
  PlayerPlugin,
20
21
  QualityLevelInfo,
21
22
  StreamMediaSource,
23
+ TransportPreference,
22
24
  } from './types.js'
23
25
  import { reportError, trace } from './trace/index.js'
24
26
  import { PlayerConfig, PlayerEvent } from './types.js'
25
27
  import DashPlayback from './plugins/dash-playback/DashPlayback.js'
26
28
  import HlsPlayback from './plugins/hls-playback/HlsPlayback.js'
27
-
28
- // import '../assets/style/main.scss' // TODO check if needed
29
+ import { buildSourcesPriorityList, buildSourcesSet, unwrapSource } from './utils/mediaSources.js'
29
30
 
30
31
  // TODO implement transport retry/failover and fallback logic
31
32
 
@@ -35,15 +36,16 @@ const T = 'GPlayer'
35
36
 
36
37
  const DEFAULT_OPTIONS: PlayerConfig = {
37
38
  autoPlay: false,
38
- mute: false,
39
+ debug: 'none',
39
40
  loop: false,
41
+ mute: false,
40
42
  multisources: [],
41
43
  playbackType: 'vod',
42
- priorityTransport: 'dash',
43
- debug: 'none',
44
44
  pluginSettings: {},
45
- strings: {},
46
45
  poster: '',
46
+ priorityTransport: 'dash',
47
+ sources: [],
48
+ strings: {},
47
49
  }
48
50
 
49
51
  export type PlaybackModule = 'dash' | 'hls' | 'native'
@@ -236,7 +238,6 @@ export class Player {
236
238
  player.core.on(
237
239
  ClapprEvents.CORE_ACTIVE_CONTAINER_CHANGED,
238
240
  () => {
239
- // this.trigger(Events.ContainerChanged)
240
241
  this.bindBitrateChangeHandler()
241
242
  },
242
243
  null,
@@ -345,16 +346,20 @@ export class Player {
345
346
  }
346
347
 
347
348
  private buildCoreOptions(rootNode: HTMLElement): CoreOptions {
348
- const multisources = this.config.multisources
349
- const mainSource =
350
- this.config.playbackType === 'live'
351
- ? multisources.find((ms) => ms.live !== false)
352
- : multisources[0]
353
- const mediaSources = mainSource
354
- ? this.buildMediaSourcesList(mainSource)
355
- : []
349
+ // TODO extract
350
+ // const multisources = this.config.multisources
351
+ // const mainSource =
352
+ // this.config.playbackType === 'live'
353
+ // ? multisources.find((ms) => ms.live !== false)
354
+ // : multisources[0]
355
+ // const mediaSources = mainSource
356
+ // ? this.buildMediaSourcesList(mainSource)
357
+ // : []
356
358
  // const mainSourceUrl = mediaSources[0];
357
- const poster = mainSource?.poster ?? this.config.poster
359
+ // const poster = mainSource?.poster ?? this.config.poster
360
+ const poster = this.config.poster
361
+
362
+ const source = this.selectMediaSource(); // TODO
358
363
 
359
364
  this.rootNode = rootNode
360
365
 
@@ -366,7 +371,6 @@ export class Player {
366
371
  events: this.events,
367
372
  height: rootNode.clientHeight,
368
373
  loop: this.config.loop,
369
- multisources,
370
374
  mute: this.config.mute,
371
375
  playback: {
372
376
  controls: false,
@@ -382,8 +386,8 @@ export class Player {
382
386
  playbackType: this.config.playbackType,
383
387
  poster,
384
388
  width: rootNode.clientWidth,
385
- // source: mainSourceUrl,
386
- sources: mediaSources,
389
+ source: source ? unwrapSource(source) : undefined,
390
+ // sources: mediaSources,
387
391
  strings: this.config.strings,
388
392
  }
389
393
  return coreOptions
@@ -404,63 +408,8 @@ export class Player {
404
408
  )
405
409
  }
406
410
 
407
- private buildMediaSourcesList(ms: StreamMediaSource): string[] {
408
- const msl: string[] = []
409
- const sources: Record<'dash' | 'master' | 'hls' | 'mpegts', string | null> =
410
- {
411
- dash: ms.sourceDash,
412
- master: ms.source,
413
- hls: ms.hlsCmafUrl,
414
- mpegts: ms.hlsMpegtsUrl,
415
- }
416
- switch (this.config.priorityTransport) {
417
- case 'dash':
418
- addDash()
419
- break
420
- case 'hls':
421
- addHls()
422
- break
423
- case 'mpegts':
424
- addMpegts()
425
- break
426
- case 'auto':
427
- addDash()
428
- addHls()
429
- break
430
- }
431
- Object.values(sources).forEach((s) => {
432
- if (s) {
433
- msl.push(s)
434
- }
435
- })
436
- return msl
437
-
438
- function addMpegts() {
439
- if (sources.mpegts) {
440
- msl.push(sources.mpegts)
441
- sources.mpegts = null
442
- }
443
- }
444
-
445
- function addHls() {
446
- if (sources.hls && HlsPlayback.canPlay(sources.hls)) {
447
- msl.push(sources.hls)
448
- sources.hls = null
449
- }
450
- if (
451
- sources.master?.endsWith('.m3u8') &&
452
- HlsPlayback.canPlay(sources.master)
453
- ) {
454
- msl.push(sources.master)
455
- sources.master = null
456
- }
457
- }
458
-
459
- function addDash() {
460
- if (sources.dash && DashPlayback.canPlay(sources.dash)) {
461
- msl.push(sources.dash)
462
- sources.dash = null
463
- }
464
- }
411
+ // TODO select a single source to play according to the priority transport and the modules support
412
+ private selectMediaSource(): PlayerMediaSource | undefined {
413
+ return buildSourcesPriorityList(buildSourcesSet(this.config.sources), this.config.priorityTransport)[0]
465
414
  }
466
415
  }
@@ -18,7 +18,7 @@ type MediacontrolStyles = {
18
18
  buttons?: string;
19
19
  }
20
20
 
21
- type PlayerMediaSourceDesc = {
21
+ export type PlayerMediaSourceDesc = {
22
22
  mimeType?: string;
23
23
  source: string;
24
24
  }
@@ -116,7 +116,7 @@ export type CoreOptions = {
116
116
  maxBufferLength?: number;
117
117
  mediacontrol?: MediacontrolStyles;
118
118
  mimeType?: string;
119
- multisources: StreamMediaSource[];
119
+ // multisources: StreamMediaSource[];
120
120
  mute?: boolean;
121
121
  persistConfig?: boolean;
122
122
  preload?: "auto" | "metadata" | "none";
@@ -788,6 +788,7 @@ DashPlayback.canPlay = function (resource, mimeType) {
788
788
  const resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || [];
789
789
  const isDash = ((resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'mpd') ||
790
790
  mimeType === 'application/dash+xml' || mimeType === 'video/mp4');
791
+ // TODO check
791
792
  const ctor = window.MediaSource || ('WebKitMediaSource' in window ? window.WebKitMediaSource : undefined);
792
793
  const hasSupport = typeof ctor === 'function';
793
794
  trace(`${T} canPlay`, {hasSupport, isDash, resource});
package/src/types.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { PlayerMediaSource } from "./internal.types"
2
+
1
3
  export type PlayerDebugTag = 'all' | 'clappr' | 'dash' | 'hls' | 'none'
2
4
  export type PlayerDebugSettings = PlayerDebugTag | boolean
3
5
 
@@ -21,6 +23,7 @@ export type PlayerConfig = {
21
23
  pluginSettings?: Record<string, unknown>
22
24
  poster?: string
23
25
  priorityTransport?: TransportPreference
26
+ sources: PlayerMediaSource[];
24
27
  strings: TranslationSettings
25
28
  }
26
29
 
@@ -104,8 +107,6 @@ export type QualityLevelInfo = {
104
107
  bitrate: number
105
108
  }
106
109
 
107
- export type BitrateInfo = QualityLevelInfo
108
-
109
110
  export enum PlayerEvent {
110
111
  Ready = 'ready',
111
112
  Play = 'play',
@@ -1,73 +1,73 @@
1
1
  import "@clappr/core";
2
2
 
3
3
  declare module "@clappr/core" {
4
- type MediacontrolStyles = {
5
- // TODO
6
- }
4
+ // type MediacontrolStyles = {
5
+ // // TODO
6
+ // }
7
7
 
8
- type PlayerMediaSourceDesc = {
9
- mimeType?: string;
10
- source: string;
11
- }
8
+ // type PlayerMediaSourceDesc = {
9
+ // mimeType?: string;
10
+ // source: string;
11
+ // }
12
12
 
13
- type PlayerMediaSource = string | PlayerMediaSourceDesc;
13
+ // type PlayerMediaSource = string | PlayerMediaSourceDesc;
14
14
 
15
- type HlsjsConfig = {
16
- debug?: boolean;
17
- startLevel?: number;
18
- } & Record<string, unknown>;
15
+ // type HlsjsConfig = {
16
+ // debug?: boolean;
17
+ // startLevel?: number;
18
+ // } & Record<string, unknown>;
19
19
 
20
- type ShakaConfig = Record<string, unknown>;
20
+ // type ShakaConfig = Record<string, unknown>;
21
21
 
22
- declare type CorePlaybackConfig = {
23
- // audioOnly: boolean;
24
- disableContextMenu?: boolean;
25
- controls?: boolean;
26
- crossOrigin?: 'anonymous' | 'use-credentials';
27
- // enableAutomaticABR?: boolean;
28
- externalTracks?: unknown[]; // TODO
29
- hlsjsConfig?: HlsjsConfig;
30
- // initialBandwidthEstimate?: number;
31
- // maxBufferLength?: number;
32
- // maxBackBufferLength?: number;
33
- // minBufferLength?: number;
34
- minimumDvrSize?: number; // TODO ?
35
- // maxAdaptiveBitrate?: number;
36
- // maxAdaptiveVideoDimensions?: unknown; // TODO
37
- playInline: boolean;
38
- preload?: 'metadata' | 'auto' | 'none';
39
- // preferredTextLanguage?: string;
40
- // preferredAudioLanguage?: string;
41
- shakaConfiguration?: ShakaConfig;
42
- }
22
+ // declare type CorePlaybackConfig = {
23
+ // // audioOnly: boolean;
24
+ // disableContextMenu?: boolean;
25
+ // controls?: boolean;
26
+ // crossOrigin?: 'anonymous' | 'use-credentials';
27
+ // // enableAutomaticABR?: boolean;
28
+ // externalTracks?: unknown[]; // TODO
29
+ // hlsjsConfig?: HlsjsConfig;
30
+ // // initialBandwidthEstimate?: number;
31
+ // // maxBufferLength?: number;
32
+ // // maxBackBufferLength?: number;
33
+ // // minBufferLength?: number;
34
+ // minimumDvrSize?: number; // TODO ?
35
+ // // maxAdaptiveBitrate?: number;
36
+ // // maxAdaptiveVideoDimensions?: unknown; // TODO
37
+ // playInline: boolean;
38
+ // preload?: 'metadata' | 'auto' | 'none';
39
+ // // preferredTextLanguage?: string;
40
+ // // preferredAudioLanguage?: string;
41
+ // shakaConfiguration?: ShakaConfig;
42
+ // }
43
43
 
44
- type ErrorLevel = "FATAL" | "WARN" | "INFO";
44
+ // type ErrorLevel = "FATAL" | "WARN" | "INFO";
45
45
 
46
- declare type EventSpec = string;
47
- declare type EventHandlerSpec = string;
48
- declare type PluginEventsConfig = Record<EventSpec, EventHandlerSpec>;
46
+ // declare type EventSpec = string;
47
+ // declare type EventHandlerSpec = string;
48
+ // declare type PluginEventsConfig = Record<EventSpec, EventHandlerSpec>;
49
49
 
50
- declare type PlaybackError = {
51
- code?: number | string;
52
- description: string;
53
- raw?: MediaError;
54
- level?: ErrorLevel;
55
- }
50
+ // declare type PlaybackError = {
51
+ // code?: number | string;
52
+ // description: string;
53
+ // raw?: MediaError;
54
+ // level?: ErrorLevel;
55
+ // }
56
56
 
57
- declare type CorePlayerEvents = {
58
- // TODO event arguments types
59
- onReady?: () => void;
60
- onResize?: (data: { width: number; height: number }) => void;
61
- onPlay?: (metadata: unknown) => void;
62
- onPause?: (metadata: unknown) => void;
63
- onStop?: (metadata: unknown) => void;
64
- onEnded?: () => void;
65
- onSeek?: (currentTime: number) => void;
66
- onError?: (err: PlaybackError) => void;
67
- onTimeUpdate?: (timeProgress: { current: number; total: number }) => void;
68
- onVolumeUpdate?: (value: number) => void;
69
- onSubtitleAvailable?: () => void;
70
- }
57
+ // declare type CorePlayerEvents = {
58
+ // // TODO event arguments types
59
+ // onReady?: () => void;
60
+ // onResize?: (data: { width: number; height: number }) => void;
61
+ // onPlay?: (metadata: unknown) => void;
62
+ // onPause?: (metadata: unknown) => void;
63
+ // onStop?: (metadata: unknown) => void;
64
+ // onEnded?: () => void;
65
+ // onSeek?: (currentTime: number) => void;
66
+ // onError?: (err: PlaybackError) => void;
67
+ // onTimeUpdate?: (timeProgress: { current: number; total: number }) => void;
68
+ // onVolumeUpdate?: (value: number) => void;
69
+ // onSubtitleAvailable?: () => void;
70
+ // }
71
71
 
72
72
  declare type ClapprVersionSpec = {
73
73
  min: string;
@@ -0,0 +1,104 @@
1
+ import { PlayerMediaSource } from '../internal.types'
2
+ import DashPlayback from '../plugins/dash-playback/DashPlayback'
3
+ import HlsPlayback from '../plugins/hls-playback/HlsPlayback'
4
+ import { StreamMediaSource, TransportPreference } from '../types'
5
+
6
+ export type SourceVariants = {
7
+ dash: string | null
8
+ master: string | null
9
+ hls: string | null
10
+ mpegts: string | null
11
+ }
12
+
13
+ export function buildSourcesSet(sources: PlayerMediaSource[]): SourceVariants {
14
+ const sv: SourceVariants = {
15
+ dash: null,
16
+ master: null,
17
+ hls: null,
18
+ mpegts: null,
19
+ }
20
+ sources.forEach((ps) => {
21
+ const [s, t] = typeof ps === 'string' ? [ps, ''] : [ps.source, ps.mimeType]
22
+ if (DashPlayback.canPlay(s, t)) {
23
+ sv.dash = s
24
+ } else if (HlsPlayback.canPlay(s, t)) {
25
+ sv.hls = s
26
+ } else {
27
+ sv.master = s
28
+ }
29
+ })
30
+ return sv
31
+ }
32
+
33
+ export function buildSourcesPriorityList(
34
+ sources: SourceVariants,
35
+ priorityTransport: TransportPreference = 'auto',
36
+ ): PlayerMediaSource[] {
37
+ const msl: string[] = []
38
+ switch (priorityTransport) {
39
+ case 'dash':
40
+ addDash()
41
+ break
42
+ case 'hls':
43
+ addHls()
44
+ break
45
+ case 'mpegts':
46
+ addMpegts()
47
+ break
48
+ case 'auto':
49
+ addDash()
50
+ addHls()
51
+ break
52
+ }
53
+ Object.values(sources).forEach((s) => {
54
+ if (s) {
55
+ msl.push(s)
56
+ }
57
+ })
58
+ return msl
59
+
60
+ function addMpegts() {
61
+ if (sources.mpegts) {
62
+ msl.push(sources.mpegts)
63
+ sources.mpegts = null
64
+ }
65
+ }
66
+
67
+ function addHls() {
68
+ if (sources.hls && HlsPlayback.canPlay(sources.hls)) {
69
+ msl.push(sources.hls)
70
+ sources.hls = null
71
+ }
72
+ if (
73
+ sources.master?.endsWith('.m3u8') &&
74
+ HlsPlayback.canPlay(sources.master)
75
+ ) {
76
+ msl.push(sources.master)
77
+ sources.master = null
78
+ }
79
+ }
80
+
81
+ function addDash() {
82
+ if (sources.dash && DashPlayback.canPlay(sources.dash)) {
83
+ msl.push(sources.dash)
84
+ sources.dash = null
85
+ }
86
+ }
87
+ }
88
+
89
+ export function unwrapSource(s: PlayerMediaSource): string {
90
+ return typeof s === 'string' ? s : s.source
91
+ }
92
+
93
+ export function buildGcoreStreamSourcesList(
94
+ ms: StreamMediaSource,
95
+ priorityTransport: TransportPreference,
96
+ ): PlayerMediaSource[] {
97
+ const sources: Record<'dash' | 'master' | 'hls' | 'mpegts', string | null> = {
98
+ dash: ms.sourceDash,
99
+ master: ms.source,
100
+ hls: ms.hlsCmafUrl,
101
+ mpegts: ms.hlsMpegtsUrl,
102
+ }
103
+ return buildSourcesPriorityList(sources, priorityTransport)
104
+ }