@gcorevideo/player 0.0.5 → 0.2.3
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 +44501 -1
- package/lib/Player.d.ts +13 -18
- package/lib/Player.d.ts.map +1 -1
- package/lib/Player.js +114 -124
- package/lib/backend.js +2 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/internal.types.d.ts +9 -2
- package/lib/internal.types.d.ts.map +1 -1
- package/lib/plugins/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/plugins/dash-playback/DashPlayback.js +3 -16
- package/lib/plugins/hls-playback/HlsPlayback.d.ts.map +1 -1
- package/lib/plugins/hls-playback/HlsPlayback.js +5 -1
- package/lib/types.d.ts +16 -3
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +8 -1
- package/lib/utils/utils.d.ts +0 -4
- package/lib/utils/utils.d.ts.map +1 -1
- package/lib/utils/utils.js +0 -26
- package/lib/version.d.ts +5 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/version.js +8 -0
- package/package.json +2 -1
- package/rollup.config.js +3 -1
- package/src/Player.ts +129 -137
- package/src/backend.ts +2 -2
- package/src/index.ts +1 -0
- package/src/internal.types.ts +11 -3
- package/src/plugins/dash-playback/DashPlayback.ts +3 -16
- package/src/plugins/hls-playback/HlsPlayback.ts +7 -3
- package/src/types.ts +18 -6
- package/src/typings/@clappr/core/player.d.ts +0 -7
- package/src/typings/@clappr/plugins.d.ts +23 -0
- package/src/utils/utils.ts +0 -26
- package/src/version.ts +9 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/src/utils/scripts-load.ts +0 -26
package/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AACxE,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,OAAO,CAAC;AAE3D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,CAAC;AAC1C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AACvD,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,MAAM,CAAC;AAE1D,MAAM,MAAM,YAAY,GAAG;IACzB,KAAI,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IAC7B,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/lib/types.js
CHANGED
|
@@ -1 +1,8 @@
|
|
|
1
|
-
export
|
|
1
|
+
export var PlayerEvent;
|
|
2
|
+
(function (PlayerEvent) {
|
|
3
|
+
PlayerEvent["Ready"] = "ready";
|
|
4
|
+
PlayerEvent["Play"] = "play";
|
|
5
|
+
PlayerEvent["Pause"] = "pause";
|
|
6
|
+
PlayerEvent["Stop"] = "stop";
|
|
7
|
+
PlayerEvent["Ended"] = "ended";
|
|
8
|
+
})(PlayerEvent || (PlayerEvent = {}));
|
package/lib/utils/utils.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
1
|
export declare function getLocation(href: string): HTMLAnchorElement;
|
|
2
2
|
export declare function strtimeToMiliseconds(str: string): number;
|
|
3
|
-
export declare function isFullscreen(el: HTMLElement): boolean;
|
|
4
|
-
export declare const FullscreenIOS: {
|
|
5
|
-
isFullscreen: (el: HTMLVideoElement) => boolean;
|
|
6
|
-
};
|
|
7
3
|
//# sourceMappingURL=utils.d.ts.map
|
package/lib/utils/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,qBAMvC;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAyBxD
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,qBAMvC;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAyBxD"}
|
package/lib/utils/utils.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// import LogManager from './LogManager';
|
|
2
|
-
import { Browser } from '@clappr/core';
|
|
3
|
-
import assert from 'assert';
|
|
4
1
|
export function getLocation(href) {
|
|
5
2
|
const l = document.createElement('a');
|
|
6
3
|
l.href = href;
|
|
@@ -32,26 +29,3 @@ export function strtimeToMiliseconds(str) {
|
|
|
32
29
|
}
|
|
33
30
|
return (h + m + s);
|
|
34
31
|
}
|
|
35
|
-
// TODO refactor
|
|
36
|
-
export function isFullscreen(el) {
|
|
37
|
-
const video = el.nodeName === "video" ? el : el.querySelector('video');
|
|
38
|
-
assert.ok(video, 'element must be a video or contain a video element');
|
|
39
|
-
if (Browser.isiOS) {
|
|
40
|
-
return FullscreenIOS.isFullscreen(video);
|
|
41
|
-
}
|
|
42
|
-
return !!(document.fullscreenElement);
|
|
43
|
-
}
|
|
44
|
-
export const FullscreenIOS = {
|
|
45
|
-
isFullscreen: function (el) {
|
|
46
|
-
try {
|
|
47
|
-
if (el.webkitDisplayingFullscreen !== undefined) {
|
|
48
|
-
return !!(el.webkitDisplayingFullscreen);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
catch (e) {
|
|
52
|
-
// LogManager.exception(error);
|
|
53
|
-
reportError(e);
|
|
54
|
-
}
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
};
|
package/lib/version.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAGA,wBAAgB,OAAO;;;EAKtB"}
|
package/lib/version.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as pkg from '../package.json' with { "type": "json" };
|
|
2
|
+
import * as lock from '../package-lock.json' with { "type": "json" };
|
|
3
|
+
export function version() {
|
|
4
|
+
return {
|
|
5
|
+
gplayer: pkg.version,
|
|
6
|
+
clappr: lock.packages['node_modules/@clappr/core'].version,
|
|
7
|
+
};
|
|
8
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gcorevideo/player",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Gcore JavaScript video player",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"homepage": "https://github.com/G-Core/gcore-videoplayer-js#readme",
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@rollup/plugin-commonjs": "^28.0.1",
|
|
34
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
34
35
|
"@rollup/plugin-node-resolve": "^15.3.0",
|
|
35
36
|
"@types/node": "^22.10.1",
|
|
36
37
|
"assert": "^2.1.0",
|
package/rollup.config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// https://github.com/rollup/rollup-starter-lib
|
|
2
|
-
import resolve from '@rollup/plugin-node-resolve';
|
|
3
2
|
import commonjs from '@rollup/plugin-commonjs';
|
|
3
|
+
import json from '@rollup/plugin-json';
|
|
4
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
4
5
|
import sass from 'rollup-plugin-sass';
|
|
5
6
|
import { string } from 'rollup-plugin-string';
|
|
6
7
|
import polyfillNode from 'rollup-plugin-polyfill-node';
|
|
@@ -15,6 +16,7 @@ export default [
|
|
|
15
16
|
}),
|
|
16
17
|
resolve(),
|
|
17
18
|
commonjs(),
|
|
19
|
+
json(),
|
|
18
20
|
string({
|
|
19
21
|
include: [
|
|
20
22
|
'**/*.ejs',
|
package/src/Player.ts
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Browser,
|
|
3
|
+
Events as ClapprEvents,
|
|
4
|
+
HTML5Video,
|
|
3
5
|
Log,
|
|
4
6
|
Player as PlayerClappr,
|
|
5
7
|
$,
|
|
6
8
|
Loader,
|
|
7
9
|
} from '@clappr/core';
|
|
8
10
|
import assert from 'assert';
|
|
9
|
-
import Hls from 'hls.js';
|
|
10
11
|
import EventLite from "event-lite";
|
|
11
12
|
|
|
12
|
-
import '../assets/style/main.scss'; // TODO check if needed
|
|
13
|
-
|
|
14
13
|
import type {
|
|
15
14
|
CorePlayerEvents,
|
|
16
15
|
CoreOptions,
|
|
@@ -18,30 +17,26 @@ import type {
|
|
|
18
17
|
PlayerMediaSource,
|
|
19
18
|
} from "./internal.types.js";
|
|
20
19
|
import type {
|
|
20
|
+
BitrateInfo,
|
|
21
|
+
PlaybackType,
|
|
21
22
|
PlayerPlugin,
|
|
22
23
|
StreamMediaSource,
|
|
23
|
-
} from "./types";
|
|
24
|
-
|
|
25
|
-
import { reportError, trace } from "./trace/index.js";
|
|
24
|
+
} from "./types.js";
|
|
25
|
+
import { reportError } from "./trace/index.js";
|
|
26
26
|
import {
|
|
27
27
|
PlayerConfig,
|
|
28
|
-
|
|
29
|
-
TransportPreference,
|
|
28
|
+
PlayerEvent,
|
|
30
29
|
} from "./types.js";
|
|
30
|
+
import DashPlayback from './plugins/dash-playback/DashPlayback.js';
|
|
31
|
+
import HlsPlayback from './plugins/hls-playback/HlsPlayback.js';
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
Ready = 'ready',
|
|
34
|
-
Play = 'play',
|
|
35
|
-
Pause = 'pause',
|
|
36
|
-
Stop = 'stop',
|
|
37
|
-
Ended = 'ended',
|
|
38
|
-
}
|
|
33
|
+
import '../assets/style/main.scss'; // TODO check if needed
|
|
39
34
|
|
|
40
35
|
// TODO implement transport retry/failover and fallback logic
|
|
41
36
|
|
|
42
37
|
type PlayerEventHandler<T extends PlayerEvent> = () => void;
|
|
43
38
|
|
|
44
|
-
const T = "
|
|
39
|
+
const T = "GPlayer";
|
|
45
40
|
|
|
46
41
|
const DEFAULT_OPTIONS: Partial<PlayerConfig> = {
|
|
47
42
|
autoPlay: false,
|
|
@@ -49,6 +44,8 @@ const DEFAULT_OPTIONS: Partial<PlayerConfig> = {
|
|
|
49
44
|
loop: false,
|
|
50
45
|
}
|
|
51
46
|
|
|
47
|
+
export type PlaybackModule = 'dash' | 'hls' | 'native';
|
|
48
|
+
|
|
52
49
|
type PluginOptions = Record<string, unknown>;
|
|
53
50
|
|
|
54
51
|
/**
|
|
@@ -67,10 +64,36 @@ export class Player {
|
|
|
67
64
|
|
|
68
65
|
private tuneInEntered = false;
|
|
69
66
|
|
|
70
|
-
private supportedMediaTransports: MediaTransport[] = [];
|
|
71
|
-
|
|
72
67
|
private config: PlayerConfig;
|
|
73
68
|
|
|
69
|
+
private bitrateInfo: BitrateInfo | null = null;
|
|
70
|
+
|
|
71
|
+
get activePlayback(): PlaybackModule | null {
|
|
72
|
+
if (!this.player?.core.activePlayback) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
switch (this.player.core.activePlayback.name) {
|
|
76
|
+
case 'dash':
|
|
77
|
+
return 'dash';
|
|
78
|
+
case 'hls':
|
|
79
|
+
return 'hls';
|
|
80
|
+
default:
|
|
81
|
+
return 'native';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
get bitrate(): BitrateInfo | null {
|
|
86
|
+
return this.bitrateInfo;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get hd() {
|
|
90
|
+
return this.player?.core.activePlayback?.isHighDefinitionInUse || false;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get playbackType(): PlaybackType | undefined{
|
|
94
|
+
return this.player?.core.activePlayback?.getPlaybackType();
|
|
95
|
+
}
|
|
96
|
+
|
|
74
97
|
get playing() {
|
|
75
98
|
return this.player ? this.player.isPlaying() : false;
|
|
76
99
|
}
|
|
@@ -93,9 +116,13 @@ export class Player {
|
|
|
93
116
|
this.emitter.off(event, handler);
|
|
94
117
|
}
|
|
95
118
|
|
|
119
|
+
configure(config: Partial<PlayerConfig>) {
|
|
120
|
+
$.extend(true, this.config, config);
|
|
121
|
+
}
|
|
122
|
+
|
|
96
123
|
async init(playerElement: HTMLElement) {
|
|
97
124
|
assert.ok(!this.player, 'Player already initialized');
|
|
98
|
-
assert.ok(playerElement, 'Player element is required');
|
|
125
|
+
assert.ok(playerElement, 'Player container element is required');
|
|
99
126
|
if (
|
|
100
127
|
this.config.debug === 'all' ||
|
|
101
128
|
this.config.debug === 'clappr'
|
|
@@ -103,27 +130,25 @@ export class Player {
|
|
|
103
130
|
Log.setLevel(0);
|
|
104
131
|
}
|
|
105
132
|
|
|
106
|
-
Log.debug('Config', this.config);
|
|
107
|
-
|
|
108
|
-
this.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return this.initPlayer(coreOpts);
|
|
122
|
-
});
|
|
133
|
+
Log.debug(T, 'Config', this.config);
|
|
134
|
+
|
|
135
|
+
this.configurePlaybacks();
|
|
136
|
+
const coreOpts = this.buildCoreOptions(playerElement);
|
|
137
|
+
const {
|
|
138
|
+
core,
|
|
139
|
+
container,
|
|
140
|
+
} = Loader.registeredPlugins;
|
|
141
|
+
coreOpts.plugins = {
|
|
142
|
+
core: Object.values(core),
|
|
143
|
+
container: Object.values(container),
|
|
144
|
+
playback: Loader.registeredPlaybacks,
|
|
145
|
+
} as CorePluginOptions;
|
|
146
|
+
Log.debug(T, 'coreOpts', coreOpts);
|
|
147
|
+
return this.initPlayer(coreOpts);
|
|
123
148
|
}
|
|
124
149
|
|
|
125
150
|
destroy() {
|
|
126
|
-
|
|
151
|
+
Log.debug(T, 'destroy', { player: !!this.player });
|
|
127
152
|
if (this.player) {
|
|
128
153
|
this.player.destroy();
|
|
129
154
|
this.player = null;
|
|
@@ -154,8 +179,8 @@ export class Player {
|
|
|
154
179
|
Loader.registerPlugin(plugin);
|
|
155
180
|
}
|
|
156
181
|
|
|
157
|
-
|
|
158
|
-
|
|
182
|
+
static unregisterPlugin(plugin: PlayerPlugin) {
|
|
183
|
+
Loader.unregisterPlugin(plugin);
|
|
159
184
|
}
|
|
160
185
|
|
|
161
186
|
private initPlayer(coreOptions: CoreOptions) {
|
|
@@ -186,7 +211,7 @@ export class Player {
|
|
|
186
211
|
// TODO sort this out
|
|
187
212
|
private async tuneIn() {
|
|
188
213
|
assert.ok(this.player);
|
|
189
|
-
|
|
214
|
+
Log.debug(T, 'tuneIn enter', {
|
|
190
215
|
ready: this.clapprReady,
|
|
191
216
|
tuneInEntered: this.tuneInEntered,
|
|
192
217
|
});
|
|
@@ -195,6 +220,17 @@ export class Player {
|
|
|
195
220
|
}
|
|
196
221
|
this.tuneInEntered = true;
|
|
197
222
|
const player = this.player;
|
|
223
|
+
try {
|
|
224
|
+
this.emitter.emit(PlayerEvent.Ready);
|
|
225
|
+
} catch (e) {
|
|
226
|
+
reportError(e);
|
|
227
|
+
}
|
|
228
|
+
if (player.core.activeContainer) {
|
|
229
|
+
this.bindBitrateChangeHandler();
|
|
230
|
+
}
|
|
231
|
+
player.core.on(ClapprEvents.CORE_ACTIVE_CONTAINER_CHANGED, () => {
|
|
232
|
+
this.bindBitrateChangeHandler();
|
|
233
|
+
}, null);
|
|
198
234
|
if (
|
|
199
235
|
Browser.isiOS &&
|
|
200
236
|
player.core.activePlayback
|
|
@@ -212,40 +248,19 @@ export class Player {
|
|
|
212
248
|
}
|
|
213
249
|
}
|
|
214
250
|
|
|
215
|
-
private configurePlugins() {
|
|
216
|
-
if (!Browser.isiOS && this.config.multisources.some((el) => el.sourceDash)) {
|
|
217
|
-
this.scheduleLoad(async () => {
|
|
218
|
-
const module = await import('./plugins/dash-playback/DashPlayback.js');
|
|
219
|
-
Loader.registerPlayback(module.default);
|
|
220
|
-
})
|
|
221
|
-
}
|
|
222
|
-
// TODO remove !isiOS?
|
|
223
|
-
// if (!Browser.isiOS && this.config.multisources.some((el) => el.hls_mpegts_url)) {
|
|
224
|
-
if (this.config.multisources.some((el) => el.hlsMpegtsUrl || el.hlsCmafUrl || el.source.endsWith('.m3u8'))) {
|
|
225
|
-
this.scheduleLoad(async () => {
|
|
226
|
-
const module = await import('./plugins/hls-playback/HlsPlayback.js');
|
|
227
|
-
Loader.registerPlayback(module.default);
|
|
228
|
-
})
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
251
|
private events: CorePlayerEvents = {
|
|
233
252
|
onReady: () => {
|
|
253
|
+
Log.debug(T, 'onReady', { clapprReady: this.clapprReady, player: !!this.player, core: !!this.player?.core, activeContainer: !!this.player?.core.activeContainer });
|
|
234
254
|
if (this.clapprReady) {
|
|
235
255
|
return;
|
|
236
256
|
}
|
|
237
257
|
this.clapprReady = true;
|
|
258
|
+
// TODO figure out what's for
|
|
238
259
|
if (this.timer) {
|
|
239
260
|
clearTimeout(this.timer);
|
|
240
261
|
this.timer = null;
|
|
241
262
|
}
|
|
242
|
-
trace(`${T} onReady`);
|
|
243
263
|
setTimeout(() => this.tuneIn(), 0);
|
|
244
|
-
try {
|
|
245
|
-
this.emitter.emit(PlayerEvent.Ready);
|
|
246
|
-
} catch (e) {
|
|
247
|
-
reportError(e);
|
|
248
|
-
}
|
|
249
264
|
},
|
|
250
265
|
onPlay: () => {
|
|
251
266
|
try {
|
|
@@ -278,20 +293,21 @@ export class Player {
|
|
|
278
293
|
};
|
|
279
294
|
|
|
280
295
|
private buildCoreOptions(playerElement: HTMLElement): CoreOptions {
|
|
281
|
-
this.
|
|
282
|
-
const
|
|
283
|
-
const mediaSources =
|
|
284
|
-
const
|
|
285
|
-
const mainSourceUrl = unwrapSource(mainSource ? this.selectMediaTransport(mainSource, this.config.priorityTransport) : undefined);
|
|
296
|
+
const multisources = this.config.multisources;
|
|
297
|
+
const mainSource = this.config.playbackType === 'live' ? multisources.find(ms => ms.live !== false) : multisources[0];
|
|
298
|
+
const mediaSources = mainSource ? this.buildMediaSourcesList(mainSource): [];
|
|
299
|
+
const mainSourceUrl = mediaSources[0];
|
|
286
300
|
const poster = mainSource?.poster ?? this.config.poster;
|
|
287
301
|
|
|
288
302
|
const coreOptions: CoreOptions & PluginOptions = {
|
|
303
|
+
...this.config.pluginSettings,
|
|
289
304
|
autoPlay: this.config.autoPlay,
|
|
290
305
|
debug: this.config.debug || 'none',
|
|
291
306
|
events: this.events,
|
|
307
|
+
height: playerElement.clientHeight,
|
|
308
|
+
loop: this.config.loop,
|
|
292
309
|
multisources,
|
|
293
310
|
mute: this.config.mute,
|
|
294
|
-
...this.config.pluginSettings,
|
|
295
311
|
playback: {
|
|
296
312
|
controls: false,
|
|
297
313
|
preload: Browser.isiOS ? 'metadata' : 'none',
|
|
@@ -305,86 +321,62 @@ export class Player {
|
|
|
305
321
|
playbackType: this.config.playbackType,
|
|
306
322
|
poster,
|
|
307
323
|
width: playerElement.clientWidth,
|
|
308
|
-
height: playerElement.clientHeight,
|
|
309
|
-
loop: this.config.loop,
|
|
310
|
-
strings: this.config.strings,
|
|
311
324
|
source: mainSourceUrl,
|
|
312
325
|
sources: mediaSources,
|
|
326
|
+
strings: this.config.strings,
|
|
313
327
|
};
|
|
314
|
-
trace(`${T} buildCoreOptions`, coreOptions);
|
|
315
328
|
return coreOptions;
|
|
316
329
|
}
|
|
317
330
|
|
|
318
|
-
private
|
|
319
|
-
|
|
331
|
+
private configurePlaybacks() {
|
|
332
|
+
Loader.registerPlayback(DashPlayback);
|
|
333
|
+
Loader.registerPlayback(HlsPlayback);
|
|
334
|
+
Loader.registerPlayback(HTML5Video);
|
|
320
335
|
}
|
|
321
336
|
|
|
322
|
-
private
|
|
323
|
-
this.
|
|
337
|
+
private bindBitrateChangeHandler() {
|
|
338
|
+
this.player?.core.activeContainer.on(ClapprEvents.CONTAINER_BITRATE, (bitrate: BitrateInfo) => {
|
|
339
|
+
this.bitrateInfo = bitrate;
|
|
340
|
+
});
|
|
324
341
|
}
|
|
325
342
|
|
|
326
|
-
private
|
|
327
|
-
const
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
for (const mt of mts) {
|
|
334
|
-
switch (mt) {
|
|
335
|
-
case 'dash':
|
|
336
|
-
if (dashUrl) {
|
|
337
|
-
return dashUrl;
|
|
338
|
-
}
|
|
339
|
-
break;
|
|
340
|
-
case 'hls':
|
|
341
|
-
if (cmafUrl) {
|
|
342
|
-
return cmafUrl;
|
|
343
|
-
}
|
|
344
|
-
break;
|
|
345
|
-
default:
|
|
346
|
-
return mpegtsUrl || masterSource;
|
|
347
|
-
}
|
|
343
|
+
private buildMediaSourcesList(ms: StreamMediaSource): string[] {
|
|
344
|
+
const msl: string[] = [];
|
|
345
|
+
const sources: Record<'dash' | 'master' | 'hls' | 'mpegts', string | null> = {
|
|
346
|
+
dash: ms.sourceDash,
|
|
347
|
+
master: ms.source,
|
|
348
|
+
hls: ms.hlsCmafUrl,
|
|
349
|
+
mpegts: ms.hlsMpegtsUrl,
|
|
348
350
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
351
|
+
switch (this.config.priorityTransport) {
|
|
352
|
+
case 'dash':
|
|
353
|
+
if (sources.dash) {
|
|
354
|
+
msl.push(sources.dash);
|
|
355
|
+
sources.dash = null;
|
|
356
|
+
}
|
|
357
|
+
break;
|
|
358
|
+
case 'hls':
|
|
359
|
+
if (sources.hls) {
|
|
360
|
+
msl.push(sources.hls);
|
|
361
|
+
sources.hls = null;
|
|
362
|
+
}
|
|
363
|
+
if (sources.master?.endsWith('.m3u8')) {
|
|
364
|
+
msl.push(sources.master);
|
|
365
|
+
sources.master = null;
|
|
366
|
+
}
|
|
367
|
+
break;
|
|
368
|
+
case 'mpegts':
|
|
369
|
+
if (sources.mpegts) {
|
|
370
|
+
msl.push(sources.mpegts);
|
|
371
|
+
sources.mpegts = null
|
|
372
|
+
}
|
|
373
|
+
break;
|
|
357
374
|
}
|
|
358
|
-
|
|
359
|
-
if (
|
|
360
|
-
|
|
375
|
+
Object.values(sources).forEach(s => {
|
|
376
|
+
if (s) {
|
|
377
|
+
msl.push(s);
|
|
361
378
|
}
|
|
362
|
-
}
|
|
363
|
-
return
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
private checkMediaTransportsSupport() {
|
|
367
|
-
const isDashSupported = typeof (globalThis.MediaSource || (globalThis as any).WebKitMediaSource) === 'function';
|
|
368
|
-
if (isDashSupported) {
|
|
369
|
-
this.supportedMediaTransports.push('dash');
|
|
370
|
-
}
|
|
371
|
-
if (Hls.isSupported()) {
|
|
372
|
-
this.supportedMediaTransports.push('hls');
|
|
373
|
-
}
|
|
374
|
-
this.supportedMediaTransports.push('mpegts');
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
private processMultisources(transport?: TransportPreference): StreamMediaSource[] {
|
|
378
|
-
return this.config.multisources.map((ms: StreamMediaSource): StreamMediaSource => ({
|
|
379
|
-
...ms,
|
|
380
|
-
source: this.selectMediaTransport(ms, transport),
|
|
381
|
-
})).filter((el): el is StreamMediaSource => !!el.source);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
function unwrapSource(s: PlayerMediaSource | undefined): string | undefined {
|
|
386
|
-
if (!s) {
|
|
387
|
-
return;
|
|
379
|
+
});
|
|
380
|
+
return msl;
|
|
388
381
|
}
|
|
389
|
-
return typeof s === "string" ? s : s.source;
|
|
390
382
|
}
|
package/src/backend.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { StreamMediaSource, StreamMediaSourceDto } from "./types";
|
|
|
3
3
|
export function fromStreamMediaSourceDto(s: StreamMediaSourceDto): StreamMediaSource {
|
|
4
4
|
return ({
|
|
5
5
|
...s,
|
|
6
|
-
hlsCmafUrl: s.hls_cmaf_url,
|
|
7
|
-
hlsMpegtsUrl: s.hls_mpegts_url,
|
|
6
|
+
hlsCmafUrl: s.hls_cmaf_url ?? null,
|
|
7
|
+
hlsMpegtsUrl: s.hls_mpegts_url ?? null,
|
|
8
8
|
priorityTransport: s.priority_transport,
|
|
9
9
|
sourceDash: s.source_dash,
|
|
10
10
|
vtt: s.vtt,
|
package/src/index.ts
CHANGED
package/src/internal.types.ts
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
CorePlugin,
|
|
3
3
|
ContainerPlugin,
|
|
4
|
-
Playback as
|
|
5
|
-
ExternalTrack,
|
|
4
|
+
Playback as ClapprPlayback,
|
|
6
5
|
} from "@clappr/core";
|
|
7
6
|
import { PlaybackType, PlayerDebugTag, StreamMediaSource } from "./types";
|
|
8
7
|
|
|
8
|
+
type ExternalTrack = {
|
|
9
|
+
kind?: "subtitles" | "captions";
|
|
10
|
+
src: string;
|
|
11
|
+
label: string;
|
|
12
|
+
lang: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
type MediacontrolStyles = {
|
|
10
16
|
// TODO
|
|
11
17
|
seekbar?: string;
|
|
@@ -76,10 +82,12 @@ export type ClapprVersionSpec = {
|
|
|
76
82
|
// TODO
|
|
77
83
|
}
|
|
78
84
|
|
|
85
|
+
export type PlaybackPluginFactory = typeof ClapprPlayback;
|
|
86
|
+
|
|
79
87
|
export type CorePluginOptions = {
|
|
80
88
|
core?: CorePlugin[];
|
|
81
89
|
container?: ContainerPlugin[];
|
|
82
|
-
playback?:
|
|
90
|
+
playback?: PlaybackPluginFactory[];
|
|
83
91
|
loadExternalPluginsFirst?: boolean;
|
|
84
92
|
loadExternalPlaybacksFirst?: boolean;
|
|
85
93
|
}
|
|
@@ -12,7 +12,6 @@ import DASHJS, {
|
|
|
12
12
|
IManifestInfo
|
|
13
13
|
} from 'dashjs';
|
|
14
14
|
|
|
15
|
-
import { trace } from '../../trace/index.js';
|
|
16
15
|
import { Duration, TimePosition, TimeValue } from '../../playback.types.js';
|
|
17
16
|
|
|
18
17
|
const AUTO = -1;
|
|
@@ -243,7 +242,6 @@ export default class DashPlayback extends HTML5Video {
|
|
|
243
242
|
}
|
|
244
243
|
|
|
245
244
|
_setup() {
|
|
246
|
-
trace(`${T} _setup`, { el: this.el });
|
|
247
245
|
const dash = DASHJS.MediaPlayer().create();
|
|
248
246
|
this._dash = dash;
|
|
249
247
|
this._dash.initialize();
|
|
@@ -265,7 +263,6 @@ export default class DashPlayback extends HTML5Video {
|
|
|
265
263
|
|
|
266
264
|
this._dash.on(DASHJS.MediaPlayer.events.STREAM_INITIALIZED, () => {
|
|
267
265
|
const bitrates = dash.getBitrateInfoListFor('video');
|
|
268
|
-
trace(`${T} STREAM_INITIALIZED`, { bitrates });
|
|
269
266
|
|
|
270
267
|
this._updatePlaybackType();
|
|
271
268
|
this._fillLevels(bitrates);
|
|
@@ -279,13 +276,10 @@ export default class DashPlayback extends HTML5Video {
|
|
|
279
276
|
});
|
|
280
277
|
|
|
281
278
|
this._dash.on(DASHJS.MediaPlayer.events.METRIC_ADDED, (e: DashMetricEvent) => {
|
|
282
|
-
// console.log(`${T} onMetricAdded`, e);
|
|
283
|
-
// TODO
|
|
284
279
|
// Listen for the first manifest request in order to update player UI
|
|
285
280
|
if ((e.metric as string) === 'DVRInfo') { // TODO fix typings
|
|
286
281
|
assert.ok(this._dash, 'An instance of dashjs MediaPlayer is required to get metrics');
|
|
287
282
|
const dvrInfo = this._dash.getDashMetrics().getCurrentDVRInfo('video');
|
|
288
|
-
// trace(`${T} onMetricAdded DVRInfo`, {metric: e.metric, dvrInfo});
|
|
289
283
|
if (dvrInfo) {
|
|
290
284
|
// Extract time info
|
|
291
285
|
this.manifestInfo = dvrInfo.manifestInfo;
|
|
@@ -578,7 +572,6 @@ export default class DashPlayback extends HTML5Video {
|
|
|
578
572
|
}
|
|
579
573
|
|
|
580
574
|
play() {
|
|
581
|
-
trace(`${T} play`, { dash: !!this._dash });
|
|
582
575
|
if (!this._dash) {
|
|
583
576
|
this._setup();
|
|
584
577
|
}
|
|
@@ -622,13 +615,9 @@ export default class DashPlayback extends HTML5Video {
|
|
|
622
615
|
_updatePlaybackType() {
|
|
623
616
|
assert.ok(this._dash, 'An instance of dashjs MediaPlayer is required to update the playback type');
|
|
624
617
|
this._playbackType = this._dash.isDynamic() ? Playback.LIVE : Playback.VOD;
|
|
625
|
-
trace(`${T} _updatePlaybackType`, {
|
|
626
|
-
playbackType: this._playbackType,
|
|
627
|
-
});
|
|
628
618
|
}
|
|
629
619
|
|
|
630
620
|
_fillLevels(levels: BitrateInfo[]) {
|
|
631
|
-
// trace(`${T} _fillLevels`, {levels});
|
|
632
621
|
// TOOD check that levels[i].qualityIndex === i
|
|
633
622
|
this._levels = levels.map((level) => {
|
|
634
623
|
return { id: level.qualityIndex, level: level };
|
|
@@ -778,7 +767,6 @@ export default class DashPlayback extends HTML5Video {
|
|
|
778
767
|
// }
|
|
779
768
|
|
|
780
769
|
private onLevelSwitch(currentLevel: BitrateInfo) {
|
|
781
|
-
trace(`${T} onLevelSwitch`, {currentLevel});
|
|
782
770
|
this.trigger(Events.PLAYBACK_BITRATE, {
|
|
783
771
|
height: currentLevel.height,
|
|
784
772
|
width: currentLevel.width,
|
|
@@ -797,12 +785,11 @@ export default class DashPlayback extends HTML5Video {
|
|
|
797
785
|
}
|
|
798
786
|
|
|
799
787
|
DashPlayback.canPlay = function (resource, mimeType) {
|
|
800
|
-
console.log(`${T} canPlay resource:%s mimeType:%s`, resource, mimeType);
|
|
801
788
|
const resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || [];
|
|
802
789
|
const isDash = ((resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'mpd') ||
|
|
803
790
|
mimeType === 'application/dash+xml' || mimeType === 'video/mp4');
|
|
804
791
|
const ctor = window.MediaSource || ('WebKitMediaSource' in window ? window.WebKitMediaSource : undefined);
|
|
805
|
-
const
|
|
806
|
-
|
|
807
|
-
return !!(
|
|
792
|
+
const hasBrowserSupport = typeof ctor === 'function';
|
|
793
|
+
Log.debug(T, 'canPlay', {hasBrowserSupport, isDash});
|
|
794
|
+
return !!(hasBrowserSupport && isDash);
|
|
808
795
|
};
|