ogplayer 0.1.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/LICENSE.md +7 -0
- package/README.md +129 -0
- package/dist/ads/freewheel-provider.d.ts +159 -0
- package/dist/ads/freewheel.d.ts +52 -0
- package/dist/ads/ima.d.ts +157 -0
- package/dist/ads/provider.d.ts +56 -0
- package/dist/ads/types.d.ts +42 -0
- package/dist/core/errors.d.ts +14 -0
- package/dist/core/fairplay.d.ts +24 -0
- package/dist/core/license.d.ts +26 -0
- package/dist/core/player.d.ts +182 -0
- package/dist/core/thumbnails.d.ts +26 -0
- package/dist/core/types.d.ts +204 -0
- package/dist/index.d.ts +17 -0
- package/dist/ogplayer.global.js +285 -0
- package/dist/ogplayer.js +285 -0
- package/dist/ui/icons.d.ts +14 -0
- package/dist/ui/og-player.d.ts +167 -0
- package/dist/ui/tokens.d.ts +51 -0
- package/package.json +39 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Control glyphs — the EXACT vector paths from the Android SDK's
|
|
3
|
+
* `og_ic_*.xml` drawables (24×24 viewport, stroked, round caps/joins), so
|
|
4
|
+
* the three platforms render identical iconography. `filled` paths use fill
|
|
5
|
+
* instead of stroke (play/pause/volume body).
|
|
6
|
+
*/
|
|
7
|
+
export interface IconDef {
|
|
8
|
+
strokes?: string[];
|
|
9
|
+
fills?: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare const icons: Record<string, IconDef>;
|
|
12
|
+
export declare function iconSvg(name: string, size: number, color: string, strokeWidth?: number): string;
|
|
13
|
+
/** The OGPlayer identity mark (aperture + play triangle) — watermark lockup. */
|
|
14
|
+
export declare function brandMarkSvg(size: number, frameColor: string, accent: string): string;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { OGPlayer } from "../core/player.js";
|
|
2
|
+
import type { OGPlayerError } from "../core/types.js";
|
|
3
|
+
import { type OGControlColors, type OGControlDimens } from "./tokens.js";
|
|
4
|
+
/** A host-supplied icon button rendered left of the (future) cast position —
|
|
5
|
+
* icon-only, max 8, part of the chrome (mirrors Android/iOS `CustomAction`). */
|
|
6
|
+
export interface CustomAction {
|
|
7
|
+
/** Inline SVG markup (24×24 recommended); rendered with the chrome tint. */
|
|
8
|
+
svg: string;
|
|
9
|
+
accessibilityLabel?: string;
|
|
10
|
+
onClick: () => void;
|
|
11
|
+
}
|
|
12
|
+
/** Per-control visibility + behavior — Android's `OGUiConfig` counterpart. */
|
|
13
|
+
export interface OGUIConfig {
|
|
14
|
+
showProgressBar: boolean;
|
|
15
|
+
showTimeLabels: boolean;
|
|
16
|
+
showSeekButtons: boolean;
|
|
17
|
+
showVolumeButton: boolean;
|
|
18
|
+
showSpeedButton: boolean;
|
|
19
|
+
showQualityButton: boolean;
|
|
20
|
+
showAudioTrackButton: boolean;
|
|
21
|
+
showSubtitleButton: boolean;
|
|
22
|
+
showFullscreenButton: boolean;
|
|
23
|
+
showTitle: boolean;
|
|
24
|
+
showContentRatings: boolean;
|
|
25
|
+
controlsTimeoutMs: number;
|
|
26
|
+
titleTimeoutMs: number;
|
|
27
|
+
contentRatingsTimeoutMs: number;
|
|
28
|
+
doubleClickToSeek: boolean;
|
|
29
|
+
/** Yellow VMAP break dots on the scrubber (mobile parity). */
|
|
30
|
+
showAdCueMarkers: boolean;
|
|
31
|
+
customActions: CustomAction[];
|
|
32
|
+
/** Chrome theming — partial overrides merged over the OGPlayer defaults
|
|
33
|
+
* (mobile parity: OGControlColors / OGControlDimens). */
|
|
34
|
+
colors?: Partial<OGControlColors>;
|
|
35
|
+
dimens?: Partial<OGControlDimens>;
|
|
36
|
+
/** Extra CSS applied to the title overlay (mobile parity: titleTextStyle /
|
|
37
|
+
* titleFont), e.g. `font-size:22px; font-family:Georgia;`. */
|
|
38
|
+
titleStyle?: string;
|
|
39
|
+
/** Glyph overrides — inline SVG markup, tinted like the chrome
|
|
40
|
+
* (mobile parity: setPlayIcon / setPauseIcon / setSeekForwardIcon …). */
|
|
41
|
+
playIconSvg?: string;
|
|
42
|
+
pauseIconSvg?: string;
|
|
43
|
+
replayIconSvg?: string;
|
|
44
|
+
seekForwardIconSvg?: string;
|
|
45
|
+
seekBackwardIconSvg?: string;
|
|
46
|
+
fullscreenEnterIconSvg?: string;
|
|
47
|
+
fullscreenExitIconSvg?: string;
|
|
48
|
+
subtitlesIconSvg?: string;
|
|
49
|
+
audioTrackIconSvg?: string;
|
|
50
|
+
speedIconSvg?: string;
|
|
51
|
+
qualityIconSvg?: string;
|
|
52
|
+
volumeOnIconSvg?: string;
|
|
53
|
+
volumeMuteIconSvg?: string;
|
|
54
|
+
adPlayIconSvg?: string;
|
|
55
|
+
adPauseIconSvg?: string;
|
|
56
|
+
/** What happens when an ad blocker is detected (error 902):
|
|
57
|
+
* - "notice": content plays ad-free with a dismissible nudge (default)
|
|
58
|
+
* - "block": playback stops and the video is hidden until the viewer
|
|
59
|
+
* disables the blocker and reloads — the hard broadcaster line
|
|
60
|
+
* - "none": the SDK stays quiet; the host handles the 902 event itself */
|
|
61
|
+
adBlockerPolicy: "none" | "notice" | "block";
|
|
62
|
+
/** When set, the fullscreen-exit button calls this instead of leaving
|
|
63
|
+
* fullscreen — the host decides (typically: close the screen). Mobile
|
|
64
|
+
* parity: `onFullscreenExitRequest`. The browser's own Esc key still
|
|
65
|
+
* exits directly (platform behavior that cannot be intercepted). */
|
|
66
|
+
onFullscreenExitRequest?: () => void;
|
|
67
|
+
/** Show a Retry button on the error overlay (default true). Retry
|
|
68
|
+
* reloads the failed item — VOD resumes where playback stopped. */
|
|
69
|
+
showRetryButton: boolean;
|
|
70
|
+
/** Label of the Retry button (default "Retry"). */
|
|
71
|
+
retryButtonLabel: string;
|
|
72
|
+
/** Your own error-overlay text, in any language — called with the full
|
|
73
|
+
* OGPlayerError (stable codes: 2000 network, 3000 source, 4000 DRM,
|
|
74
|
+
* 5000 renderer, 6000 live, 9000 unknown). Return null/undefined for the
|
|
75
|
+
* SDK default. The error object still reaches onError unchanged. */
|
|
76
|
+
errorMessageProvider?: (error: OGPlayerError) => string | null | undefined;
|
|
77
|
+
}
|
|
78
|
+
export declare const defaultUIConfig: OGUIConfig;
|
|
79
|
+
/** Every control flag off — headless chrome in one call (mobile parity:
|
|
80
|
+
* `hideAllControls()`). Title/ratings stay, exactly like Android/iOS. */
|
|
81
|
+
export declare function hidingAllControls(overrides?: Partial<OGUIConfig>): Partial<OGUIConfig>;
|
|
82
|
+
/**
|
|
83
|
+
* `<og-player>` — the OGPlayer UI as a framework-agnostic custom element
|
|
84
|
+
* (works in plain HTML, React, Vue, Angular alike). Attach an `OGPlayer`
|
|
85
|
+
* engine via the `player` property; overlays (watermarks, logos) go into the
|
|
86
|
+
* nine named slots (`slot="top-end"` …), mirroring the Android/iOS
|
|
87
|
+
* `OverlaySlot` system including the clearance choreography.
|
|
88
|
+
*/
|
|
89
|
+
export declare class OGPlayerElement extends HTMLElement {
|
|
90
|
+
private playerRef;
|
|
91
|
+
private cfg;
|
|
92
|
+
private root;
|
|
93
|
+
private controlsVisible;
|
|
94
|
+
private hideTimer;
|
|
95
|
+
private bufferingTimer;
|
|
96
|
+
private scrubbing;
|
|
97
|
+
private openMenu;
|
|
98
|
+
private titleShownGeneration;
|
|
99
|
+
private ratingsShownGeneration;
|
|
100
|
+
private ratingRowVisible;
|
|
101
|
+
private lastSeenGeneration;
|
|
102
|
+
/** True after a fatal error: the chrome stays hidden until the next load. */
|
|
103
|
+
private errored;
|
|
104
|
+
private lastOverlayGeneration;
|
|
105
|
+
private lastCueKey;
|
|
106
|
+
private lastAdCueKey;
|
|
107
|
+
private col;
|
|
108
|
+
private dimE;
|
|
109
|
+
private dimF;
|
|
110
|
+
private overlayTimers;
|
|
111
|
+
private detachFns;
|
|
112
|
+
constructor();
|
|
113
|
+
get player(): OGPlayer | null;
|
|
114
|
+
set player(p: OGPlayer | null);
|
|
115
|
+
get config(): OGUIConfig;
|
|
116
|
+
set config(c: Partial<OGUIConfig>);
|
|
117
|
+
connectedCallback(): void;
|
|
118
|
+
disconnectedCallback(): void;
|
|
119
|
+
private get dims();
|
|
120
|
+
/** Configured override for a glyph, or the built-in vector. */
|
|
121
|
+
private glyph;
|
|
122
|
+
private mount;
|
|
123
|
+
private q;
|
|
124
|
+
private css;
|
|
125
|
+
private buildButtons;
|
|
126
|
+
private buildTopEnd;
|
|
127
|
+
private toggleMenu;
|
|
128
|
+
private closeMenu;
|
|
129
|
+
private bind;
|
|
130
|
+
private bindScrub;
|
|
131
|
+
/** Storyboard preview above the scrubber (mobile trick-play parity). */
|
|
132
|
+
private thumbPreviewSeq;
|
|
133
|
+
private showThumbPreview;
|
|
134
|
+
private hideThumbPreview;
|
|
135
|
+
private paintScrub;
|
|
136
|
+
private onState;
|
|
137
|
+
/** Title + content ratings: once per load, at content start, timed fade. */
|
|
138
|
+
private maybeShowOnceOverlays;
|
|
139
|
+
private ratingHtml;
|
|
140
|
+
/** While the rating row is shown, the top-end button row drops below it
|
|
141
|
+
* and top-row overlays clear both — the Android/iOS choreography. */
|
|
142
|
+
private setRatingRow;
|
|
143
|
+
private applyOverlayInsets;
|
|
144
|
+
private showControls;
|
|
145
|
+
private hideControls;
|
|
146
|
+
private armAutoHide;
|
|
147
|
+
private cancelAutoHide;
|
|
148
|
+
private syncAll;
|
|
149
|
+
private syncButtons;
|
|
150
|
+
private syncProgress;
|
|
151
|
+
/** Yellow dots on the track where VMAP breaks will play (mobile parity). */
|
|
152
|
+
private paintAdCues;
|
|
153
|
+
private syncPeriodic;
|
|
154
|
+
/** Break-mode UI: the SDK yields the chrome to the ad layer and draws its
|
|
155
|
+
* own yellow bar + AD chip + centered transport (mobile parity — IMA
|
|
156
|
+
* renders its own skip/clickthrough on top of its layer). */
|
|
157
|
+
private syncAdUi;
|
|
158
|
+
private syncWatermark;
|
|
159
|
+
private applyCueSize;
|
|
160
|
+
/** Enter fullscreen — must be called from a user gesture (browser policy);
|
|
161
|
+
* a "starts in fullscreen" flow calls this from its start button. */
|
|
162
|
+
enterFullscreen(): Promise<void>;
|
|
163
|
+
exitFullscreen(): void;
|
|
164
|
+
private toggleFullscreen;
|
|
165
|
+
private detach;
|
|
166
|
+
}
|
|
167
|
+
export declare function defineOGPlayerElement(): void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design tokens — Android's `OGControlColors` / `OGControlDimens`,
|
|
3
|
+
* token-for-token (dp → px at CSS-pixel scale, which is the same unit
|
|
4
|
+
* philosophy the Android/iOS SDKs use).
|
|
5
|
+
*/
|
|
6
|
+
export interface OGControlColors {
|
|
7
|
+
foreground: string;
|
|
8
|
+
foregroundMuted: string;
|
|
9
|
+
foregroundFaint: string;
|
|
10
|
+
trackPlayed: string;
|
|
11
|
+
trackBuffered: string;
|
|
12
|
+
trackRemaining: string;
|
|
13
|
+
thumb: string;
|
|
14
|
+
thumbHalo: string;
|
|
15
|
+
pressed: string;
|
|
16
|
+
liveEdge: string;
|
|
17
|
+
liveBehind: string;
|
|
18
|
+
adAccent: string;
|
|
19
|
+
menuSurface: string;
|
|
20
|
+
menuSelected: string;
|
|
21
|
+
menuBorder: string;
|
|
22
|
+
chipSurface: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const defaultColors: OGControlColors;
|
|
25
|
+
export interface OGControlDimens {
|
|
26
|
+
trackHeight: number;
|
|
27
|
+
trackHeightActive: number;
|
|
28
|
+
thumbSize: number;
|
|
29
|
+
thumbSizeActive: number;
|
|
30
|
+
thumbHaloSize: number;
|
|
31
|
+
scrubTouchHeight: number;
|
|
32
|
+
iconSize: number;
|
|
33
|
+
playButtonSize: number;
|
|
34
|
+
playGlyphSize: number;
|
|
35
|
+
seekButtonSize: number;
|
|
36
|
+
seekGlyphSize: number;
|
|
37
|
+
clusterGap: number;
|
|
38
|
+
bottomBarHeight: number;
|
|
39
|
+
edgeInset: number;
|
|
40
|
+
bottomScrimHeight: number;
|
|
41
|
+
topScrimHeight: number;
|
|
42
|
+
menuMinWidth: number;
|
|
43
|
+
menuMaxWidth: number;
|
|
44
|
+
menuItemHeight: number;
|
|
45
|
+
menuCorner: number;
|
|
46
|
+
chipHeight: number;
|
|
47
|
+
adCueMarkerSize: number;
|
|
48
|
+
}
|
|
49
|
+
export declare const embeddedDimens: OGControlDimens;
|
|
50
|
+
/** Fullscreen step-up (Android `forFullscreen()`). */
|
|
51
|
+
export declare const fullscreenDimens: OGControlDimens;
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ogplayer",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "OGPlayer web SDK — one video player API across Android, iOS and the web.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/ogplayer.js",
|
|
7
|
+
"module": "./dist/ogplayer.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/ogplayer.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "node build.mjs && tsc -p tsconfig.json --emitDeclarationOnly --outDir dist",
|
|
20
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
21
|
+
"test": "node --test test/",
|
|
22
|
+
"dev": "node build.mjs --serve",
|
|
23
|
+
"smoke": "node scripts/smoke.mjs"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"hls.js": "^1.5.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"esbuild": "^0.23.0",
|
|
30
|
+
"playwright": "^1.62.1",
|
|
31
|
+
"typedoc": "^0.28.20",
|
|
32
|
+
"typescript": "^5.5.0"
|
|
33
|
+
},
|
|
34
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
35
|
+
"homepage": "https://ogplayer.tv",
|
|
36
|
+
"repository": { "type": "git", "url": "https://github.com/ogplayer-sdk/ogplayer-web.git" },
|
|
37
|
+
"keywords": ["video", "player", "hls", "drm", "widevine", "fairplay", "ima", "ads", "web-component"],
|
|
38
|
+
"author": "OGPlayer (Inverse DOO) <hello@ogplayer.tv>"
|
|
39
|
+
}
|