@gcorevideo/player 0.0.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 (192) hide show
  1. package/assets/icons/new/arrow-left.svg +5 -0
  2. package/assets/icons/new/arrow-right.svg +5 -0
  3. package/assets/icons/new/check.svg +5 -0
  4. package/assets/icons/new/close.svg +12 -0
  5. package/assets/icons/new/full.svg +8 -0
  6. package/assets/icons/new/fullscreen-off.svg +14 -0
  7. package/assets/icons/new/fullscreen-on.svg +14 -0
  8. package/assets/icons/new/gear-hd.svg +16 -0
  9. package/assets/icons/new/gear.svg +12 -0
  10. package/assets/icons/new/hd.svg +8 -0
  11. package/assets/icons/new/pause.svg +5 -0
  12. package/assets/icons/new/pip.svg +5 -0
  13. package/assets/icons/new/play.svg +10 -0
  14. package/assets/icons/new/replayleft.svg +5 -0
  15. package/assets/icons/new/replayright.svg +5 -0
  16. package/assets/icons/new/speed.svg +5 -0
  17. package/assets/icons/new/stats.svg +3 -0
  18. package/assets/icons/new/stop.svg +3 -0
  19. package/assets/icons/new/subtitles-off.svg +5 -0
  20. package/assets/icons/new/subtitles-on.svg +6 -0
  21. package/assets/icons/new/volume-max.svg +5 -0
  22. package/assets/icons/new/volume-min.svg +5 -0
  23. package/assets/icons/new/volume-off.svg +5 -0
  24. package/assets/icons/old/cardboard.svg +4 -0
  25. package/assets/icons/old/close-share.svg +13 -0
  26. package/assets/icons/old/close.svg +13 -0
  27. package/assets/icons/old/fb.svg +13 -0
  28. package/assets/icons/old/fullscreen.svg +12 -0
  29. package/assets/icons/old/language.svg +1 -0
  30. package/assets/icons/old/pause.svg +12 -0
  31. package/assets/icons/old/play.svg +12 -0
  32. package/assets/icons/old/quality-arrow.svg +13 -0
  33. package/assets/icons/old/reload.svg +4 -0
  34. package/assets/icons/old/share.svg +13 -0
  35. package/assets/icons/old/sound-off.svg +15 -0
  36. package/assets/icons/old/sound-on.svg +15 -0
  37. package/assets/icons/old/streams.svg +3 -0
  38. package/assets/icons/old/twitter.svg +13 -0
  39. package/assets/icons/old/wn.svg +15 -0
  40. package/assets/icons/standard/01-play.svg +3 -0
  41. package/assets/icons/standard/02-pause.svg +3 -0
  42. package/assets/icons/standard/03-stop.svg +3 -0
  43. package/assets/icons/standard/04-volume.svg +3 -0
  44. package/assets/icons/standard/05-mute.svg +3 -0
  45. package/assets/icons/standard/06-expand.svg +3 -0
  46. package/assets/icons/standard/07-shrink.svg +3 -0
  47. package/assets/icons/standard/08-hd.svg +3 -0
  48. package/assets/icons/standard/09-cc.svg +8 -0
  49. package/assets/icons/standard/10-reload.svg +4 -0
  50. package/assets/style/main.scss +50 -0
  51. package/assets/style/theme.scss +42 -0
  52. package/assets/style/variables.scss +7 -0
  53. package/dist/DashPlayback-6wKK0_pL.js +666 -0
  54. package/dist/DashPlayback-8U6_s4Jc.js +666 -0
  55. package/dist/DashPlayback-BeZz7mN9.js +663 -0
  56. package/dist/DashPlayback-CRdja67F.js +667 -0
  57. package/dist/DashPlayback-D0df6zGg.js +663 -0
  58. package/dist/DashPlayback-D7egS-CZ.js +664 -0
  59. package/dist/DashPlayback-DH5lZMRR.js +663 -0
  60. package/dist/DashPlayback-DZfIc9sK.js +665 -0
  61. package/dist/DashPlayback-VhCxbQhn.js +666 -0
  62. package/dist/HlsPlayback-Avwy8-0O.js +749 -0
  63. package/dist/index.css +125 -0
  64. package/dist/index.js +467 -0
  65. package/lib/Player.d.ts +50 -0
  66. package/lib/Player.d.ts.map +1 -0
  67. package/lib/Player.js +310 -0
  68. package/lib/backend.d.ts +3 -0
  69. package/lib/backend.d.ts.map +1 -0
  70. package/lib/backend.js +10 -0
  71. package/lib/constants.d.ts +19 -0
  72. package/lib/constants.d.ts.map +1 -0
  73. package/lib/constants.js +18 -0
  74. package/lib/index.d.ts +10 -0
  75. package/lib/index.d.ts.map +1 -0
  76. package/lib/index.js +9 -0
  77. package/lib/internal.types.d.ts +105 -0
  78. package/lib/internal.types.d.ts.map +1 -0
  79. package/lib/internal.types.js +1 -0
  80. package/lib/playback.types.d.ts +13 -0
  81. package/lib/playback.types.d.ts.map +1 -0
  82. package/lib/playback.types.js +1 -0
  83. package/lib/plugins/audio-selector/AudioSelector.d.ts +48 -0
  84. package/lib/plugins/audio-selector/AudioSelector.d.ts.map +1 -0
  85. package/lib/plugins/audio-selector/AudioSelector.js +282 -0
  86. package/lib/plugins/big-mute-button/BigMuteButton.d.ts +33 -0
  87. package/lib/plugins/big-mute-button/BigMuteButton.d.ts.map +1 -0
  88. package/lib/plugins/big-mute-button/BigMuteButton.js +148 -0
  89. package/lib/plugins/bottom-gear/BottomGear.d.ts +30 -0
  90. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -0
  91. package/lib/plugins/bottom-gear/BottomGear.js +103 -0
  92. package/lib/plugins/click-to-pause/ClickToPause.d.ts +16 -0
  93. package/lib/plugins/click-to-pause/ClickToPause.d.ts.map +1 -0
  94. package/lib/plugins/click-to-pause/ClickToPause.js +73 -0
  95. package/lib/plugins/dash-playback/DashPlayback.d.ts +81 -0
  96. package/lib/plugins/dash-playback/DashPlayback.d.ts.map +1 -0
  97. package/lib/plugins/dash-playback/DashPlayback.js +658 -0
  98. package/lib/plugins/dash-plugin/DashPlayback.d.ts +86 -0
  99. package/lib/plugins/dash-plugin/DashPlayback.d.ts.map +1 -0
  100. package/lib/plugins/dash-plugin/DashPlayback.js +659 -0
  101. package/lib/plugins/disable-controls/DisableControls.d.ts +15 -0
  102. package/lib/plugins/disable-controls/DisableControls.d.ts.map +1 -0
  103. package/lib/plugins/disable-controls/DisableControls.js +69 -0
  104. package/lib/plugins/dvr-controls/DVRControls.d.ts +27 -0
  105. package/lib/plugins/dvr-controls/DVRControls.d.ts.map +1 -0
  106. package/lib/plugins/dvr-controls/DVRControls.js +110 -0
  107. package/lib/plugins/hls-playback/HlsPlayback.d.ts +102 -0
  108. package/lib/plugins/hls-playback/HlsPlayback.d.ts.map +1 -0
  109. package/lib/plugins/hls-playback/HlsPlayback.js +747 -0
  110. package/lib/plugins/level-selector/LevelSelector.d.ts +48 -0
  111. package/lib/plugins/level-selector/LevelSelector.d.ts.map +1 -0
  112. package/lib/plugins/level-selector/LevelSelector.js +287 -0
  113. package/lib/plugins/media-control/MediaControl.d.ts +186 -0
  114. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -0
  115. package/lib/plugins/media-control/MediaControl.js +1000 -0
  116. package/lib/plugins/poster/Poster.d.ts +41 -0
  117. package/lib/plugins/poster/Poster.d.ts.map +1 -0
  118. package/lib/plugins/poster/Poster.js +186 -0
  119. package/lib/trace/LogTracer.d.ts +12 -0
  120. package/lib/trace/LogTracer.d.ts.map +1 -0
  121. package/lib/trace/LogTracer.js +17 -0
  122. package/lib/trace/SentryTracer.d.ts +11 -0
  123. package/lib/trace/SentryTracer.d.ts.map +1 -0
  124. package/lib/trace/SentryTracer.js +18 -0
  125. package/lib/trace/Tracer.d.ts +13 -0
  126. package/lib/trace/Tracer.d.ts.map +1 -0
  127. package/lib/trace/Tracer.js +15 -0
  128. package/lib/trace/index.d.ts +18 -0
  129. package/lib/trace/index.d.ts.map +1 -0
  130. package/lib/trace/index.js +27 -0
  131. package/lib/trace/types.d.ts +8 -0
  132. package/lib/trace/types.d.ts.map +1 -0
  133. package/lib/trace/types.js +1 -0
  134. package/lib/types.d.ts +82 -0
  135. package/lib/types.d.ts.map +1 -0
  136. package/lib/types.js +1 -0
  137. package/lib/utils/Logger.d.ts +23 -0
  138. package/lib/utils/Logger.d.ts.map +1 -0
  139. package/lib/utils/Logger.js +81 -0
  140. package/lib/utils/canAutoplay.d.ts +6 -0
  141. package/lib/utils/canAutoplay.d.ts.map +1 -0
  142. package/lib/utils/canAutoplay.js +30 -0
  143. package/lib/utils/errors.d.ts +2 -0
  144. package/lib/utils/errors.d.ts.map +1 -0
  145. package/lib/utils/errors.js +6 -0
  146. package/lib/utils/queryParams.d.ts +2 -0
  147. package/lib/utils/queryParams.d.ts.map +1 -0
  148. package/lib/utils/queryParams.js +4 -0
  149. package/lib/utils/scripts-load.d.ts +2 -0
  150. package/lib/utils/scripts-load.d.ts.map +1 -0
  151. package/lib/utils/scripts-load.js +20 -0
  152. package/lib/utils/types.d.ts +4 -0
  153. package/lib/utils/types.d.ts.map +1 -0
  154. package/lib/utils/types.js +1 -0
  155. package/lib/utils/utils.d.ts +7 -0
  156. package/lib/utils/utils.d.ts.map +1 -0
  157. package/lib/utils/utils.js +57 -0
  158. package/package.json +57 -0
  159. package/rollup.config.js +34 -0
  160. package/src/Player.ts +390 -0
  161. package/src/backend.ts +12 -0
  162. package/src/constants.ts +17 -0
  163. package/src/index.ts +9 -0
  164. package/src/internal.types.ts +126 -0
  165. package/src/playback.types.ts +15 -0
  166. package/src/plugins/dash-playback/DashPlayback.ts +808 -0
  167. package/src/plugins/dash-playback/_DashPlayback.js +688 -0
  168. package/src/plugins/hls-playback/HlsPlayback.ts +909 -0
  169. package/src/plugins/hls-playback/hls.js +706 -0
  170. package/src/trace/LogTracer.ts +23 -0
  171. package/src/trace/SentryTracer.ts +18 -0
  172. package/src/trace/Tracer.ts +27 -0
  173. package/src/trace/index.ts +32 -0
  174. package/src/trace/types.ts +7 -0
  175. package/src/types.ts +100 -0
  176. package/src/typings/@clappr/core/error_mixin.d.ts +15 -0
  177. package/src/typings/@clappr/core/events.d.ts +7 -0
  178. package/src/typings/@clappr/core/html5_video.d.ts +28 -0
  179. package/src/typings/@clappr/core/playback.d.ts +5 -0
  180. package/src/typings/@clappr/core/player.d.ts +83 -0
  181. package/src/typings/@clappr/plugins.d.ts +29 -0
  182. package/src/typings/clappr-zepto.xd.xts +44 -0
  183. package/src/typings/globals.d.ts +8 -0
  184. package/src/utils/Logger.ts +107 -0
  185. package/src/utils/canAutoplay.ts +39 -0
  186. package/src/utils/errors.ts +6 -0
  187. package/src/utils/queryParams.ts +5 -0
  188. package/src/utils/scripts-load.ts +26 -0
  189. package/src/utils/types.ts +5 -0
  190. package/src/utils/utils.ts +64 -0
  191. package/tsconfig.json +43 -0
  192. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryParams.d.ts","sourceRoot":"","sources":["../../src/utils/queryParams.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ function isValidDebugTag(tag) {
2
+ return ['all', 'clappr', 'dash', 'hls', 'none'].includes(tag);
3
+ }
4
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function request(url: string, timeout: number): Promise<void>;
2
+ //# sourceMappingURL=scripts-load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scripts-load.d.ts","sourceRoot":"","sources":["../../src/utils/scripts-load.ts"],"names":[],"mappings":"AACA,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBnE"}
@@ -0,0 +1,20 @@
1
+ export function request(url, timeout) {
2
+ return new Promise((resolve) => {
3
+ const win = window, doc = document, el = 'script';
4
+ let timer;
5
+ const onLoad = () => {
6
+ win.clearTimeout(timer);
7
+ resolve();
8
+ };
9
+ const first = doc.getElementsByTagName(el)[0];
10
+ const script = doc.createElement(el);
11
+ script.src = url;
12
+ script.async = true;
13
+ script.onload = onLoad;
14
+ script.onerror = onLoad; // TODO reject?
15
+ first?.parentNode?.insertBefore(script, first);
16
+ if (timeout) {
17
+ timer = win.setTimeout(onLoad, timeout);
18
+ }
19
+ });
20
+ }
@@ -0,0 +1,4 @@
1
+ import { $ } from "@clappr/core";
2
+ export type ZeptoResult = ReturnType<typeof $>;
3
+ export type TimerId = ReturnType<typeof setTimeout>;
4
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAEjC,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;AAE/C,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ export declare function getLocation(href: string): HTMLAnchorElement;
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
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +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;AAGD,wBAAgB,YAAY,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAQrD;AAED,eAAO,MAAM,aAAa;uBACI,gBAAgB,KAAG,OAAO;CAYvD,CAAC"}
@@ -0,0 +1,57 @@
1
+ // import LogManager from './LogManager';
2
+ import { Browser } from '@clappr/core';
3
+ import assert from 'assert';
4
+ export function getLocation(href) {
5
+ const l = document.createElement('a');
6
+ l.href = href;
7
+ return l;
8
+ }
9
+ export function strtimeToMiliseconds(str) {
10
+ if (!str) {
11
+ return 0;
12
+ }
13
+ const arr = str.split(/:/);
14
+ let h = 0, m = 0, s = 0;
15
+ if (arr.length >= 3) {
16
+ h = parseInt(arr[arr.length - 3]) * 60 * 60;
17
+ }
18
+ else {
19
+ h = 0;
20
+ }
21
+ if (arr.length >= 2) {
22
+ m = parseInt(arr[arr.length - 2]) * 60;
23
+ }
24
+ else {
25
+ m = 0;
26
+ }
27
+ if (arr.length >= 1) {
28
+ s = parseInt(arr[arr.length - 1]);
29
+ }
30
+ else {
31
+ s = 0;
32
+ }
33
+ return (h + m + s);
34
+ }
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/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@gcorevideo/player",
3
+ "version": "0.0.1",
4
+ "description": "Gcore JavaScript video player",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "typings": "lib/index.d.ts",
8
+ "scripts": {
9
+ "build": "npm run build:ts && npm run build:bundle",
10
+ "build:1": "npm run build:ts && npm run build:bundle && date",
11
+ "build:ts": "tsc",
12
+ "build:bundle": "rollup -c",
13
+ "docs": "npm run docs:extract && npm run docs:build",
14
+ "docs:extract": "api-extractor run --local --verbose",
15
+ "docs:build": "api-documenter markdown --input-folder=temp --output-folder=docs/api",
16
+ "format": "prettier --write src/",
17
+ "lint": "oxlint -c ../../.oxlintrc.json --tsconfig=./tsconfig.json --fix --ignore-path=../../.gitignore src",
18
+ "ship": "npm run build && npm run build:bundle && npm publish --access public",
19
+ "test": "vitest --environment=jsdom run",
20
+ "test:watch": "vitest --environment=jsdom watch"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/G-Core/gcore-videoplayer-js.git"
25
+ },
26
+ "author": "Gcore",
27
+ "license": "Apache-2.0",
28
+ "bugs": {
29
+ "url": "https://github.com/G-Core/gcore-videoplayer-js/issues"
30
+ },
31
+ "homepage": "https://github.com/G-Core/gcore-videoplayer-js#readme",
32
+ "devDependencies": {
33
+ "@rollup/plugin-commonjs": "^28.0.1",
34
+ "@rollup/plugin-node-resolve": "^15.3.0",
35
+ "@types/can-autoplay": "^3.0.5",
36
+ "@types/node": "^22.10.1",
37
+ "@types/ua-parser-js": "^0.7.39",
38
+ "assert": "^2.1.0",
39
+ "rollup": "^4.27.4",
40
+ "rollup-plugin-sass": "^1.14.0",
41
+ "rollup-plugin-scss": "^4.0.1",
42
+ "rollup-plugin-string": "^3.0.0",
43
+ "sass": "^1.83.0",
44
+ "typescript": "^5.7.2"
45
+ },
46
+ "dependencies": {
47
+ "@clappr/core": "^0.11.3",
48
+ "@clappr/plugins": "^0.8.3",
49
+ "@sentry/browser": "^8.41.0",
50
+ "can-autoplay": "^3.0.2",
51
+ "dashjs": "^4.7.4",
52
+ "event-lite": "^1.0.0",
53
+ "hls.js": "^1.5.17",
54
+ "kibo": "file:../kibo",
55
+ "ua-parser-js": "^2.0.0"
56
+ }
57
+ }
@@ -0,0 +1,34 @@
1
+ // https://github.com/rollup/rollup-starter-lib
2
+ import resolve from '@rollup/plugin-node-resolve';
3
+ import commonjs from '@rollup/plugin-commonjs';
4
+ import sass from 'rollup-plugin-sass';
5
+ import { string } from 'rollup-plugin-string';
6
+
7
+ export default [
8
+ {
9
+ input: 'lib/index.js',
10
+ plugins: [
11
+ sass({
12
+ output: 'dist/index.css',
13
+ verbose: true,
14
+ }),
15
+ resolve({
16
+ resolveOnly: ["ms"],
17
+ }),
18
+ commonjs(),
19
+ string({
20
+ include: [
21
+ '**/*.ejs',
22
+ '**/*.svg',
23
+ ],
24
+ }),
25
+ ],
26
+ output: [
27
+ {
28
+ dir: 'dist',
29
+ format: 'es',
30
+ generatedCode: 'es2015',
31
+ }
32
+ ]
33
+ }
34
+ ];
package/src/Player.ts ADDED
@@ -0,0 +1,390 @@
1
+ import {
2
+ Browser,
3
+ Log,
4
+ Player as PlayerClappr,
5
+ $,
6
+ Loader,
7
+ } from '@clappr/core';
8
+ import assert from 'assert';
9
+ import Hls from 'hls.js';
10
+ import EventLite from "event-lite";
11
+
12
+ import '../assets/style/main.scss'; // TODO check if needed
13
+
14
+ import type {
15
+ CorePlayerEvents,
16
+ CoreOptions,
17
+ CorePluginOptions,
18
+ PlayerMediaSource,
19
+ } from "./internal.types.js";
20
+ import type {
21
+ PlayerPlugin,
22
+ StreamMediaSource,
23
+ } from "./types";
24
+
25
+ import { reportError, trace } from "./trace/index.js";
26
+ import {
27
+ PlayerConfig,
28
+ MediaTransport,
29
+ TransportPreference,
30
+ } from "./types.js";
31
+
32
+ export enum PlayerEvent {
33
+ Ready = 'ready',
34
+ Play = 'play',
35
+ Pause = 'pause',
36
+ Stop = 'stop',
37
+ Ended = 'ended',
38
+ }
39
+
40
+ // TODO implement transport retry/failover and fallback logic
41
+
42
+ type PlayerEventHandler<T extends PlayerEvent> = () => void;
43
+
44
+ const T = "Player";
45
+
46
+ const DEFAULT_OPTIONS: Partial<PlayerConfig> = {
47
+ autoPlay: false,
48
+ mute: false,
49
+ loop: false,
50
+ }
51
+
52
+ type PluginOptions = Record<string, unknown>;
53
+
54
+ /**
55
+ * @beta
56
+ */
57
+ export class Player {
58
+ private emitter = new EventLite();
59
+
60
+ private player: PlayerClappr | null = null;
61
+
62
+ private pluginLoaders: Array<() => Promise<void>> = [];
63
+
64
+ private clapprReady = false;
65
+
66
+ private timer: ReturnType<typeof setTimeout> | null = null;
67
+
68
+ private tuneInEntered = false;
69
+
70
+ private supportedMediaTransports: MediaTransport[] = [];
71
+
72
+ private config: PlayerConfig;
73
+
74
+ get playing() {
75
+ return this.player ? this.player.isPlaying() : false;
76
+ }
77
+
78
+ get ready() {
79
+ return this.clapprReady;
80
+ }
81
+
82
+ constructor(
83
+ config: PlayerConfig,
84
+ ) {
85
+ this.config = $.extend(true, {}, DEFAULT_OPTIONS, config);
86
+ }
87
+
88
+ on<T extends PlayerEvent>(event: T, handler: PlayerEventHandler<T>) {
89
+ this.emitter.on(event, handler);
90
+ }
91
+
92
+ off<T extends PlayerEvent>(event: T, handler: PlayerEventHandler<T>) {
93
+ this.emitter.off(event, handler);
94
+ }
95
+
96
+ async init(playerElement: HTMLElement) {
97
+ assert.ok(!this.player, 'Player already initialized');
98
+ assert.ok(playerElement, 'Player element is required');
99
+ if (
100
+ this.config.debug === 'all' ||
101
+ this.config.debug === 'clappr'
102
+ ) {
103
+ Log.setLevel(0);
104
+ }
105
+
106
+ Log.debug('Config', this.config);
107
+
108
+ this.configurePlugins();
109
+ return this.loadPlugins().then(async () => {
110
+ const coreOpts = this.buildCoreOptions(playerElement);
111
+ const {
112
+ core,
113
+ container,
114
+ } = Loader.registeredPlugins;
115
+ coreOpts.plugins = {
116
+ core: Object.values(core),
117
+ container: Object.values(container),
118
+ playback: Loader.registeredPlaybacks,
119
+ } as CorePluginOptions;
120
+ console.log('plugins', coreOpts.plugins);
121
+ return this.initPlayer(coreOpts);
122
+ });
123
+ }
124
+
125
+ destroy() {
126
+ trace(`${T} destroy`, { player: !!this.player });
127
+ if (this.player) {
128
+ this.player.destroy();
129
+ this.player = null;
130
+ }
131
+ }
132
+
133
+ pause() {
134
+ assert.ok(this.player, 'Player not initialized');
135
+ this.player.pause();
136
+ }
137
+
138
+ play() {
139
+ assert.ok(this.player, 'Player not initialized');
140
+ this.player.play();
141
+ }
142
+
143
+ seekTo(time: number) {
144
+ assert.ok(this.player, 'Player not initialized');
145
+ this.player.seek(time);
146
+ }
147
+
148
+ stop() {
149
+ assert.ok(this.player, 'Player not initialized');
150
+ this.player.stop();
151
+ }
152
+
153
+ static registerPlugin(plugin: PlayerPlugin) {
154
+ Loader.registerPlugin(plugin);
155
+ }
156
+
157
+ private loadPlugins(): Promise<void> {
158
+ return Promise.all(this.pluginLoaders.map((loader) => loader())).then(() => { });
159
+ }
160
+
161
+ private initPlayer(coreOptions: CoreOptions) {
162
+ assert.ok(!this.player, 'Player already initialized');
163
+
164
+ const player = new PlayerClappr(
165
+ coreOptions
166
+ );
167
+ this.player = player;
168
+
169
+ this.timer = globalThis.setTimeout(() => {
170
+ try {
171
+ if (
172
+ !this.clapprReady &&
173
+ player.core &&
174
+ player.core
175
+ .activePlayback
176
+ ) {
177
+ this.tuneIn();
178
+ // player.onReady = null; // TODO ?
179
+ }
180
+ } catch (e) {
181
+ reportError(e);
182
+ }
183
+ }, 4000);
184
+ }
185
+
186
+ // TODO sort this out
187
+ private async tuneIn() {
188
+ assert.ok(this.player);
189
+ trace(`${T} tuneIn enter`, {
190
+ ready: this.clapprReady,
191
+ tuneInEntered: this.tuneInEntered,
192
+ });
193
+ if (this.tuneInEntered) {
194
+ return;
195
+ }
196
+ this.tuneInEntered = true;
197
+ const player = this.player;
198
+ if (
199
+ Browser.isiOS &&
200
+ player.core.activePlayback
201
+ ) {
202
+ player.core.activePlayback.$el.on(
203
+ 'webkitendfullscreen',
204
+ () => {
205
+ try {
206
+ player.core.handleFullscreenChange();
207
+ } catch (e) {
208
+ reportError(e);
209
+ }
210
+ },
211
+ );
212
+ }
213
+ }
214
+
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
+ private events: CorePlayerEvents = {
233
+ onReady: () => {
234
+ if (this.clapprReady) {
235
+ return;
236
+ }
237
+ this.clapprReady = true;
238
+ if (this.timer) {
239
+ clearTimeout(this.timer);
240
+ this.timer = null;
241
+ }
242
+ trace(`${T} onReady`);
243
+ setTimeout(() => this.tuneIn(), 0);
244
+ try {
245
+ this.emitter.emit(PlayerEvent.Ready);
246
+ } catch (e) {
247
+ reportError(e);
248
+ }
249
+ },
250
+ onPlay: () => {
251
+ try {
252
+ this.emitter.emit(PlayerEvent.Play);
253
+ } catch (e) {
254
+ reportError(e);
255
+ }
256
+ },
257
+ onPause: () => {
258
+ try {
259
+ this.emitter.emit(PlayerEvent.Pause);
260
+ } catch (e) {
261
+ reportError(e);
262
+ }
263
+ },
264
+ onEnded: () => {
265
+ try {
266
+ this.emitter.emit(PlayerEvent.Ended);
267
+ } catch (e) {
268
+ reportError(e);
269
+ }
270
+ },
271
+ onStop: () => {
272
+ try {
273
+ this.emitter.emit(PlayerEvent.Stop);
274
+ } catch (e) {
275
+ reportError(e);
276
+ }
277
+ },
278
+ };
279
+
280
+ private buildCoreOptions(playerElement: HTMLElement): CoreOptions {
281
+ this.checkMediaTransportsSupport();
282
+ const multisources = this.processMultisources(this.config.priorityTransport);
283
+ const mediaSources = multisources.map(ms => ms.source);
284
+ const mainSource = this.findMainSource();
285
+ const mainSourceUrl = unwrapSource(mainSource ? this.selectMediaTransport(mainSource, this.config.priorityTransport) : undefined);
286
+ const poster = mainSource?.poster ?? this.config.poster;
287
+
288
+ const coreOptions: CoreOptions & PluginOptions = {
289
+ autoPlay: this.config.autoPlay,
290
+ debug: this.config.debug || 'none',
291
+ events: this.events,
292
+ multisources,
293
+ mute: this.config.mute,
294
+ ...this.config.pluginSettings,
295
+ playback: {
296
+ controls: false,
297
+ preload: Browser.isiOS ? 'metadata' : 'none',
298
+ playInline: true,
299
+ crossOrigin: 'anonymous', // TODO
300
+ hlsjsConfig: {
301
+ debug: this.config.debug === 'all' || this.config.debug === 'hls',
302
+ },
303
+ },
304
+ parent: playerElement,
305
+ playbackType: this.config.playbackType,
306
+ poster,
307
+ width: playerElement.clientWidth,
308
+ height: playerElement.clientHeight,
309
+ loop: this.config.loop,
310
+ strings: this.config.strings,
311
+ source: mainSourceUrl,
312
+ sources: mediaSources,
313
+ };
314
+ trace(`${T} buildCoreOptions`, coreOptions);
315
+ return coreOptions;
316
+ }
317
+
318
+ private findMainSource(): StreamMediaSource | undefined {
319
+ return this.config.multisources.find(ms => ms.live !== false);
320
+ }
321
+
322
+ private scheduleLoad(cb: () => Promise<void>) {
323
+ this.pluginLoaders.push(cb);
324
+ }
325
+
326
+ private selectMediaTransport(ms: StreamMediaSource, priorityTransport: TransportPreference = ms.priorityTransport): string {
327
+ const cmafUrl = ms.hlsCmafUrl || ms.source; // source is default url for hls
328
+ const mpegtsUrl = ms.hlsMpegtsUrl; // no-low-latency HLS
329
+ const dashUrl = ms.sourceDash;
330
+ const masterSource = ms.source;
331
+
332
+ const mts = this.getAvailableTransportsPreference(priorityTransport);
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
+ }
348
+ }
349
+ // no supported transport found
350
+ return '';
351
+ }
352
+
353
+ private getAvailableTransportsPreference(priorityTransport: TransportPreference): MediaTransport[] {
354
+ const mtp: MediaTransport[] = [];
355
+ if (priorityTransport !== 'auto' && this.supportedMediaTransports.includes(priorityTransport)) {
356
+ mtp.push(priorityTransport);
357
+ }
358
+ for (const mt of this.supportedMediaTransports) {
359
+ if (mt !== priorityTransport) {
360
+ mtp.push(mt);
361
+ }
362
+ }
363
+ return mtp;
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;
388
+ }
389
+ return typeof s === "string" ? s : s.source;
390
+ }
package/src/backend.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { StreamMediaSource, StreamMediaSourceDto } from "./types";
2
+
3
+ export function fromStreamMediaSourceDto(s: StreamMediaSourceDto): StreamMediaSource {
4
+ return ({
5
+ ...s,
6
+ hlsCmafUrl: s.hls_cmaf_url,
7
+ hlsMpegtsUrl: s.hls_mpegts_url,
8
+ priorityTransport: s.priority_transport,
9
+ sourceDash: s.source_dash,
10
+ vtt: s.vtt,
11
+ });
12
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @deprecated
3
+ */
4
+ export const SentryLogLevel = {
5
+ FATAL: 'fatal',
6
+ ERROR: 'error',
7
+ WARNING: 'warning',
8
+ LOG: 'log',
9
+ INFO: 'info',
10
+ DEBUG: 'debug'
11
+ };
12
+
13
+ export enum QueryParams {
14
+ DEBUG = "debug",
15
+ NO_LOW_LATENCY = 'no_low_latency',
16
+ SUBTITLES_LANGUAGE = 'sub_lang',
17
+ };
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ export * from "./Player.js"
2
+ export * from "./backend.js";
3
+ export * from "./playback.types.js";
4
+ export * from "./trace/LogTracer.js";
5
+ export * from "./trace/SentryTracer.js";
6
+ export * from "./trace/index.js";
7
+ export * from "./trace/types.js";
8
+ export * from "./types.js";
9
+ export * from "./utils/Logger.js";