@gcorevideo/player 2.12.1 → 2.12.2
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/dist/index.js +42 -66
- package/lib/Player.d.ts.map +1 -1
- package/lib/Player.js +10 -15
- package/lib/index.d.ts +0 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/internal.types.d.ts +1 -12
- package/lib/internal.types.d.ts.map +1 -1
- package/lib/playback.types.d.ts +10 -0
- package/lib/playback.types.d.ts.map +1 -1
- package/lib/plugins/dash-playback/DashPlayback.d.ts +1 -0
- package/lib/plugins/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/plugins/dash-playback/DashPlayback.js +16 -13
- package/lib/plugins/hls-playback/HlsPlayback.d.ts +3 -4
- package/lib/plugins/hls-playback/HlsPlayback.d.ts.map +1 -1
- package/lib/plugins/hls-playback/HlsPlayback.js +15 -37
- package/lib/utils/mediaSources.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/Player.ts +12 -23
- package/src/index.ts +0 -1
- package/src/internal.types.ts +1 -14
- package/src/playback.types.ts +18 -7
- package/src/plugins/dash-playback/DashPlayback.ts +16 -16
- package/src/plugins/hls-playback/HlsPlayback.ts +19 -40
- package/src/utils/mediaSources.ts +30 -20
- package/tsconfig.tsbuildinfo +1 -1
package/src/Player.ts
CHANGED
|
@@ -15,9 +15,7 @@ import type {
|
|
|
15
15
|
CoreOptions,
|
|
16
16
|
CorePluginOptions,
|
|
17
17
|
} from './internal.types.js'
|
|
18
|
-
import type {
|
|
19
|
-
PlayerPlugin,
|
|
20
|
-
} from './types.js'
|
|
18
|
+
import type { PlayerMediaSourceDesc, PlayerPlugin } from './types.js'
|
|
21
19
|
import { PlayerConfig, PlayerEvent } from './types.js'
|
|
22
20
|
import {
|
|
23
21
|
buildMediaSourcesList,
|
|
@@ -74,12 +72,6 @@ export class Player {
|
|
|
74
72
|
|
|
75
73
|
private tunedIn = false
|
|
76
74
|
|
|
77
|
-
// private sourcesList: PlayerMediaSourceDesc[] = []
|
|
78
|
-
|
|
79
|
-
// private currentSourceIndex = 0
|
|
80
|
-
|
|
81
|
-
// private sourcesDelay: Record<string, number> = {}
|
|
82
|
-
|
|
83
75
|
constructor(config: PlayerConfig) {
|
|
84
76
|
this.setConfig(config)
|
|
85
77
|
}
|
|
@@ -125,10 +117,6 @@ export class Player {
|
|
|
125
117
|
Log.setLevel(0)
|
|
126
118
|
}
|
|
127
119
|
|
|
128
|
-
trace(`${T} init`, {
|
|
129
|
-
// TODO selected options
|
|
130
|
-
})
|
|
131
|
-
|
|
132
120
|
this.configurePlaybacks()
|
|
133
121
|
const coreOpts = this.buildCoreOptions(playerElement)
|
|
134
122
|
const { core, container } = Loader.registeredPlugins
|
|
@@ -400,11 +388,11 @@ export class Player {
|
|
|
400
388
|
}
|
|
401
389
|
|
|
402
390
|
private buildCoreOptions(rootNode: HTMLElement): CoreOptions {
|
|
403
|
-
this.buildMediaSourcesList()
|
|
404
|
-
const source =
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
391
|
+
const sources = this.buildMediaSourcesList()
|
|
392
|
+
const source = sources[0]
|
|
393
|
+
trace(`${T} buildCoreOptions`, {
|
|
394
|
+
source
|
|
395
|
+
})
|
|
408
396
|
|
|
409
397
|
this.rootNode = rootNode
|
|
410
398
|
|
|
@@ -412,7 +400,7 @@ export class Player {
|
|
|
412
400
|
...this.config, // plugin settings
|
|
413
401
|
allowUserInteraction: true,
|
|
414
402
|
autoPlay: false,
|
|
415
|
-
dash: this.config.dash,
|
|
403
|
+
dash: this.config.dash, // TODO move this to the playback section
|
|
416
404
|
debug: this.config.debug || 'none',
|
|
417
405
|
events: this.events,
|
|
418
406
|
height: rootNode.clientHeight,
|
|
@@ -432,7 +420,7 @@ export class Player {
|
|
|
432
420
|
playbackType: this.config.playbackType,
|
|
433
421
|
width: rootNode.clientWidth,
|
|
434
422
|
source: source ? unwrapSource(source) : undefined,
|
|
435
|
-
sources
|
|
423
|
+
sources, // prevent Clappr from loading all sources simultaneously
|
|
436
424
|
strings: this.config.strings,
|
|
437
425
|
}
|
|
438
426
|
return coreOptions
|
|
@@ -442,9 +430,10 @@ export class Player {
|
|
|
442
430
|
registerPlaybacks()
|
|
443
431
|
}
|
|
444
432
|
|
|
445
|
-
private buildMediaSourcesList() {
|
|
446
|
-
return buildMediaSourcesList(
|
|
447
|
-
|
|
433
|
+
private buildMediaSourcesList(): PlayerMediaSourceDesc[] {
|
|
434
|
+
return buildMediaSourcesList(
|
|
435
|
+
// TODO ensure unsupported sources are filtered out
|
|
436
|
+
this.config.sources.map((s) => wrapSource(s)),
|
|
448
437
|
this.config.priorityTransport,
|
|
449
438
|
)
|
|
450
439
|
}
|
package/src/index.ts
CHANGED
package/src/internal.types.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
} from "@clappr/core";
|
|
6
6
|
|
|
7
7
|
import { PlaybackType, PlayerDebugTag, PlayerMediaSource } from "./types";
|
|
8
|
+
import { PlaybackError } from "./playback.types";
|
|
8
9
|
|
|
9
10
|
type ExternalTrack = {
|
|
10
11
|
kind?: "subtitles" | "captions";
|
|
@@ -56,20 +57,6 @@ export interface CorePlaybackConfig {
|
|
|
56
57
|
shakaConfiguration?: ShakaConfig;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
type ErrorLevel = "FATAL" | "WARN" | "INFO";
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* @beta
|
|
63
|
-
*/
|
|
64
|
-
export type PlaybackError = {
|
|
65
|
-
code?: number | string;
|
|
66
|
-
description: string;
|
|
67
|
-
raw?: MediaError;
|
|
68
|
-
level?: ErrorLevel;
|
|
69
|
-
message: string;
|
|
70
|
-
scope?: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
60
|
/**
|
|
74
61
|
* @internal
|
|
75
62
|
*/
|
package/src/playback.types.ts
CHANGED
|
@@ -1,33 +1,32 @@
|
|
|
1
|
-
|
|
2
1
|
/**
|
|
3
2
|
* Playback time in seconds since the beginning of the stream (or a segment for the live streams)
|
|
4
3
|
* For the plugin development
|
|
5
4
|
* @internal
|
|
6
5
|
*/
|
|
7
|
-
export type TimeValue = number
|
|
6
|
+
export type TimeValue = number
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* For the plugin development
|
|
11
10
|
* @internal
|
|
12
11
|
*/
|
|
13
12
|
export type TimePosition = {
|
|
14
|
-
current: TimeValue
|
|
15
|
-
total: TimeValue
|
|
13
|
+
current: TimeValue
|
|
14
|
+
total: TimeValue
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* For the plugin development
|
|
20
19
|
* @internal
|
|
21
20
|
*/
|
|
22
|
-
export type TimeProgress = TimePosition & { start: number
|
|
21
|
+
export type TimeProgress = TimePosition & { start: number }
|
|
23
22
|
|
|
24
23
|
/**
|
|
25
24
|
* For the plugin development
|
|
26
25
|
* @internal
|
|
27
26
|
*/
|
|
28
27
|
export type TimeUpdate = TimePosition & {
|
|
29
|
-
firstFragDateTime: number
|
|
30
|
-
}
|
|
28
|
+
firstFragDateTime: number
|
|
29
|
+
}
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
32
|
* @beta
|
|
@@ -47,3 +46,15 @@ export enum PlaybackErrorCode {
|
|
|
47
46
|
MediaSourceUnavailable = 1,
|
|
48
47
|
QualityLevelUnavailable = 2,
|
|
49
48
|
}
|
|
49
|
+
|
|
50
|
+
export type ErrorLevel = 'FATAL' | 'WARN' | 'INFO'
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @beta
|
|
54
|
+
*/
|
|
55
|
+
export interface PlaybackError {
|
|
56
|
+
code: PlaybackErrorCode
|
|
57
|
+
description: string
|
|
58
|
+
level: ErrorLevel
|
|
59
|
+
message: string
|
|
60
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style
|
|
3
3
|
// license that can be found in the LICENSE file.
|
|
4
4
|
|
|
5
|
-
import { Events, HTML5Video, Log, Playback, Utils } from '@clappr/core'
|
|
5
|
+
import { Events, HTML5Video, Log, Playback, PlayerError, Utils } from '@clappr/core'
|
|
6
6
|
import { trace } from '@gcorevideo/utils'
|
|
7
7
|
import assert from 'assert'
|
|
8
8
|
import DASHJS, {
|
|
@@ -14,7 +14,7 @@ import DASHJS, {
|
|
|
14
14
|
IManifestInfo,
|
|
15
15
|
} from 'dashjs'
|
|
16
16
|
|
|
17
|
-
import { PlaybackErrorCode, QualityLevel, TimePosition, TimeUpdate, TimeValue } from '../../playback.types.js'
|
|
17
|
+
import { PlaybackError, PlaybackErrorCode, QualityLevel, TimePosition, TimeUpdate, TimeValue } from '../../playback.types.js'
|
|
18
18
|
|
|
19
19
|
const AUTO = -1
|
|
20
20
|
|
|
@@ -406,7 +406,6 @@ export default class DashPlayback extends HTML5Video {
|
|
|
406
406
|
|
|
407
407
|
private _onDASHJSSError = (event: DashErrorEvent) => {
|
|
408
408
|
trace(`${T} _onDASHJSSError`, { event })
|
|
409
|
-
// TODO figure out what's for
|
|
410
409
|
this._stopTimeUpdateTimer()
|
|
411
410
|
|
|
412
411
|
const e = (event as MediaPlayerErrorEvent).error
|
|
@@ -414,31 +413,32 @@ export default class DashPlayback extends HTML5Video {
|
|
|
414
413
|
case DASHJS.MediaPlayer.errors.MANIFEST_LOADER_PARSING_FAILURE_ERROR_CODE:
|
|
415
414
|
case DASHJS.MediaPlayer.errors.MANIFEST_LOADER_LOADING_FAILURE_ERROR_CODE:
|
|
416
415
|
case DASHJS.MediaPlayer.errors.DOWNLOAD_ERROR_ID_MANIFEST_CODE:
|
|
417
|
-
|
|
416
|
+
case DASHJS.MediaPlayer.errors.DOWNLOAD_ERROR_ID_CONTENT_CODE:
|
|
417
|
+
this.triggerError({
|
|
418
418
|
code: PlaybackErrorCode.MediaSourceUnavailable,
|
|
419
419
|
message: e.message,
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
})
|
|
420
|
+
description: e.message,
|
|
421
|
+
level: PlayerError.Levels.FATAL,
|
|
422
|
+
})
|
|
423
423
|
break;
|
|
424
424
|
// TODO more cases
|
|
425
425
|
default:
|
|
426
|
-
this.
|
|
426
|
+
this.triggerError({
|
|
427
427
|
code: PlaybackErrorCode.Generic,
|
|
428
428
|
message: e.message,
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
})
|
|
429
|
+
description: e.message,
|
|
430
|
+
level: PlayerError.Levels.FATAL,
|
|
431
|
+
})
|
|
432
432
|
}
|
|
433
|
+
}
|
|
433
434
|
|
|
435
|
+
private triggerError(error: PlaybackError) {
|
|
436
|
+
trace(`${T} triggerError`, { error })
|
|
437
|
+
this.trigger(Events.PLAYBACK_ERROR, error)
|
|
434
438
|
// only reset the dash player in 10ms async, so that the rest of the
|
|
435
439
|
// calling function finishes
|
|
436
440
|
setTimeout(() => {
|
|
437
|
-
|
|
438
|
-
this._dash,
|
|
439
|
-
'An instance of dashjs MediaPlayer is required to reset',
|
|
440
|
-
)
|
|
441
|
-
this._dash.reset()
|
|
441
|
+
this.stop()
|
|
442
442
|
}, 10)
|
|
443
443
|
}
|
|
444
444
|
|
|
@@ -25,7 +25,7 @@ import HLSJS, {
|
|
|
25
25
|
type LevelSwitchingData,
|
|
26
26
|
} from 'hls.js'
|
|
27
27
|
|
|
28
|
-
import { PlaybackErrorCode, QualityLevel, TimePosition, TimeUpdate } from '../../playback.types.js'
|
|
28
|
+
import { PlaybackError, PlaybackErrorCode, QualityLevel, TimePosition, TimeUpdate } from '../../playback.types.js'
|
|
29
29
|
import { PlaybackType } from '../../types'
|
|
30
30
|
import { TimerId } from '../../utils/types'
|
|
31
31
|
|
|
@@ -493,7 +493,7 @@ export default class HlsPlayback extends HTML5Video {
|
|
|
493
493
|
this.trigger(Events.PLAYBACK_READY, this.name)
|
|
494
494
|
}
|
|
495
495
|
|
|
496
|
-
_recover(evt: HlsEvents.ERROR, data: HlsErrorData, error:
|
|
496
|
+
_recover(evt: HlsEvents.ERROR, data: HlsErrorData, error: PlaybackError) {
|
|
497
497
|
assert(this._hls, 'Hls.js instance is not available')
|
|
498
498
|
if (!this._recoveredDecodingError) {
|
|
499
499
|
this._recoveredDecodingError = true
|
|
@@ -505,10 +505,8 @@ export default class HlsPlayback extends HTML5Video {
|
|
|
505
505
|
} else {
|
|
506
506
|
Log.error('hlsjs: failed to recover', { evt, data })
|
|
507
507
|
error.level = PlayerError.Levels.FATAL
|
|
508
|
-
const formattedError = this.createError(error)
|
|
509
508
|
|
|
510
|
-
this.
|
|
511
|
-
this.stop()
|
|
509
|
+
this.triggerError(error)
|
|
512
510
|
}
|
|
513
511
|
}
|
|
514
512
|
|
|
@@ -608,13 +606,12 @@ export default class HlsPlayback extends HTML5Video {
|
|
|
608
606
|
}
|
|
609
607
|
|
|
610
608
|
_onHLSJSError(evt: HlsEvents.ERROR, data: HlsErrorData) {
|
|
611
|
-
const error:
|
|
612
|
-
// code: `${data.type}_${data.details}`,
|
|
609
|
+
const error: PlaybackError = {
|
|
613
610
|
code: PlaybackErrorCode.Generic,
|
|
614
|
-
description: `${this.name} error: type: ${data.type}, details: ${data.details}`,
|
|
615
|
-
|
|
611
|
+
description: `${this.name} error: type: ${data.type}, details: ${data.details} fatal: ${data.fatal}`,
|
|
612
|
+
level: data.fatal ? PlayerError.Levels.FATAL : PlayerError.Levels.WARN,
|
|
613
|
+
message: `${this.name} error: type: ${data.type}, details: ${data.details}`,
|
|
616
614
|
}
|
|
617
|
-
let formattedError
|
|
618
615
|
|
|
619
616
|
if (data.response) {
|
|
620
617
|
error.description += `, response: ${JSON.stringify(data.response)}`
|
|
@@ -639,18 +636,8 @@ export default class HlsPlayback extends HTML5Video {
|
|
|
639
636
|
evt,
|
|
640
637
|
data,
|
|
641
638
|
})
|
|
642
|
-
error.code =
|
|
643
|
-
|
|
644
|
-
HLSJS.ErrorDetails.MANIFEST_LOAD_TIMEOUT,
|
|
645
|
-
HLSJS.ErrorDetails.MANIFEST_PARSING_ERROR
|
|
646
|
-
].includes(data.details)
|
|
647
|
-
? PlaybackErrorCode.MediaSourceUnavailable
|
|
648
|
-
: PlaybackErrorCode.QualityLevelUnavailable
|
|
649
|
-
formattedError = this.createError(error, {
|
|
650
|
-
useCodePrefix: false,
|
|
651
|
-
})
|
|
652
|
-
this.trigger(Events.PLAYBACK_ERROR, formattedError)
|
|
653
|
-
this.stop()
|
|
639
|
+
error.code = PlaybackErrorCode.MediaSourceUnavailable;
|
|
640
|
+
this.triggerError(error)
|
|
654
641
|
break
|
|
655
642
|
default:
|
|
656
643
|
Log.warn('hlsjs: trying to recover from network error.', {
|
|
@@ -658,8 +645,7 @@ export default class HlsPlayback extends HTML5Video {
|
|
|
658
645
|
data,
|
|
659
646
|
})
|
|
660
647
|
error.level = PlayerError.Levels.WARN
|
|
661
|
-
|
|
662
|
-
this._hls.startLoad()
|
|
648
|
+
this._hls?.startLoad()
|
|
663
649
|
break
|
|
664
650
|
}
|
|
665
651
|
break
|
|
@@ -673,11 +659,7 @@ export default class HlsPlayback extends HTML5Video {
|
|
|
673
659
|
break
|
|
674
660
|
default:
|
|
675
661
|
Log.error('hlsjs: could not recover from error.', { evt, data })
|
|
676
|
-
|
|
677
|
-
useCodePrefix: false,
|
|
678
|
-
})
|
|
679
|
-
this.trigger(Events.PLAYBACK_ERROR, formattedError)
|
|
680
|
-
this.stop()
|
|
662
|
+
this.triggerError(error)
|
|
681
663
|
break
|
|
682
664
|
}
|
|
683
665
|
} else {
|
|
@@ -686,11 +668,7 @@ export default class HlsPlayback extends HTML5Video {
|
|
|
686
668
|
{ evt, data },
|
|
687
669
|
)
|
|
688
670
|
// TODO
|
|
689
|
-
|
|
690
|
-
useCodePrefix: false,
|
|
691
|
-
})
|
|
692
|
-
this.trigger(Events.PLAYBACK_ERROR, formattedError)
|
|
693
|
-
this.stop()
|
|
671
|
+
this.triggerError(error)
|
|
694
672
|
}
|
|
695
673
|
} else {
|
|
696
674
|
// Transforms HLSJS.ErrorDetails.KEY_LOAD_ERROR non-fatal error to
|
|
@@ -702,16 +680,11 @@ export default class HlsPlayback extends HTML5Video {
|
|
|
702
680
|
this._keyIsDenied(data)
|
|
703
681
|
) {
|
|
704
682
|
Log.error('hlsjs: could not load decrypt key.', { evt, data })
|
|
705
|
-
|
|
706
|
-
useCodePrefix: false,
|
|
707
|
-
})
|
|
708
|
-
this.trigger(Events.PLAYBACK_ERROR, formattedError)
|
|
709
|
-
this.stop()
|
|
683
|
+
this.triggerError(error)
|
|
710
684
|
|
|
711
685
|
return
|
|
712
686
|
}
|
|
713
687
|
|
|
714
|
-
error.level = PlayerError.Levels.WARN
|
|
715
688
|
Log.warn('hlsjs: non-fatal error occurred', { evt, data })
|
|
716
689
|
}
|
|
717
690
|
}
|
|
@@ -1081,6 +1054,12 @@ export default class HlsPlayback extends HTML5Video {
|
|
|
1081
1054
|
isSeekEnabled() {
|
|
1082
1055
|
return this._playbackType === Playback.VOD || this.dvrEnabled
|
|
1083
1056
|
}
|
|
1057
|
+
|
|
1058
|
+
private triggerError(error: PlaybackError) {
|
|
1059
|
+
trace(`${T} triggerError`, { error })
|
|
1060
|
+
this.trigger(Events.PLAYBACK_ERROR, error)
|
|
1061
|
+
this.stop()
|
|
1062
|
+
}
|
|
1084
1063
|
}
|
|
1085
1064
|
|
|
1086
1065
|
HlsPlayback.canPlay = function (resource: string, mimeType?: string): boolean {
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
PlayerMediaSource,
|
|
3
|
+
PlayerMediaSourceDesc,
|
|
4
|
+
TransportPreference,
|
|
5
|
+
} from '../types'
|
|
2
6
|
import { canPlayDash, canPlayHls } from '../playback/index.js'
|
|
3
7
|
|
|
4
8
|
export type SourceVariants = {
|
|
@@ -8,10 +12,10 @@ export type SourceVariants = {
|
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
|
-
*
|
|
15
|
+
*
|
|
12
16
|
* @param sources
|
|
13
17
|
* @deprecated
|
|
14
|
-
* @returns
|
|
18
|
+
* @returns
|
|
15
19
|
*/
|
|
16
20
|
export function buildSourcesSet(sources: PlayerMediaSource[]): SourceVariants {
|
|
17
21
|
const sv: SourceVariants = {
|
|
@@ -38,23 +42,29 @@ export function buildMediaSourcesList(
|
|
|
38
42
|
): PlayerMediaSourceDesc[] {
|
|
39
43
|
const [preferred, rest] = sources.reduce(
|
|
40
44
|
priorityTransport === 'dash' || priorityTransport === 'auto'
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
45
|
+
? (
|
|
46
|
+
acc: [PlayerMediaSourceDesc[], PlayerMediaSourceDesc[]],
|
|
47
|
+
item: PlayerMediaSourceDesc,
|
|
48
|
+
) => {
|
|
49
|
+
if (canPlayDash(item.source, item.mimeType)) {
|
|
50
|
+
acc[0].push(item)
|
|
51
|
+
} else if (canPlayHls(item.source, item.mimeType)) {
|
|
52
|
+
acc[1].push(item)
|
|
53
|
+
}
|
|
54
|
+
return acc
|
|
55
|
+
}
|
|
56
|
+
: (
|
|
57
|
+
acc: [PlayerMediaSourceDesc[], PlayerMediaSourceDesc[]],
|
|
58
|
+
item: PlayerMediaSourceDesc,
|
|
59
|
+
) => {
|
|
60
|
+
if (canPlayHls(item.source, item.mimeType)) {
|
|
61
|
+
acc[0].push(item)
|
|
62
|
+
} else if (canPlayDash(item.source, item.mimeType)) {
|
|
63
|
+
acc[1].push(item)
|
|
64
|
+
}
|
|
65
|
+
return acc
|
|
66
|
+
},
|
|
67
|
+
[[], []],
|
|
58
68
|
)
|
|
59
69
|
return preferred.concat(rest)
|
|
60
70
|
}
|