ogplayer 1.2.1 → 1.3.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.
package/README.md CHANGED
@@ -64,17 +64,28 @@ el.config = {
64
64
  };
65
65
  ```
66
66
 
67
+ ## Keyboard shortcuts
68
+
69
+ While the player has focus (it takes focus on any click) the keys viewers
70
+ expect just work: `Space`/`K` play-pause, `←`/`→` and `J`/`L` seek by the seek
71
+ increment, `↑`/`↓` volume, `M` mute, `F` fullscreen, `C` subtitles, `0`–`9` jump
72
+ to 0–90 % on VOD, `Home`/`End` start/end (live edge on live), `Esc` leaves
73
+ fullscreen. Seek keys obey the live rules and stay inert during ads; modifier
74
+ chords and unmapped keys reach the page untouched. Turn it off with
75
+ `el.config = { keyboardShortcuts: false }` or change single keys with
76
+ `el.config = { keymap: { m: null, p: "toggleMute" } }`.
77
+
67
78
  ## How it ships
68
79
 
69
80
  1. **npm** (the web's Maven Central): `npm install ogplayer` — ESM module
70
81
  with TypeScript types, hls.js pulled in as a dependency. Publishing is one
71
- `npm publish` from CI; scoped to the `@ogplayer` org.
82
+ `scripts/release.sh <version>` run (build, tests, tarball guard, `npm publish`).
72
83
  2. **CDN script tag** for no-build websites: `dist/ogplayer.global.js` is a
73
84
  single self-contained file (hls.js included) exposing `window.OGPlayerSDK`.
74
- Hosted on our own domain (e.g. `cdn.ogplayer.tv`) or jsDelivr once public.
85
+ Served straight from the npm package via unpkg (or any CDN mirror of npm).
75
86
 
76
87
  ```html
77
- <script src="https://cdn.ogplayer.tv/0.1.0/ogplayer.global.js"></script>
88
+ <script src="https://unpkg.com/ogplayer@1.3.1/dist/ogplayer.global.js"></script>
78
89
  <script>
79
90
  const player = new OGPlayerSDK.OGPlayer();
80
91
  document.querySelector("og-player").player = player;
@@ -2,8 +2,7 @@ import type { AdBreakConfig } from "./types.js";
2
2
  import type { AdsProvider, AdsProviderCallbacks } from "./provider.js";
3
3
  /**
4
4
  * Native FreeWheel (MRM) implementation of the OGPlayer ads SPI — the web
5
- * counterpart of Android's `FreewheelAdsProvider` (whose `FreewheelSession`
6
- * this mirrors: request → slot schedule → preroll/midroll/catch-up/postroll,
5
+ * flow: request slot schedule → preroll/midroll/catch-up/postroll,
7
6
  * a watchdog that abandons a slot that never renders, exactly-once content
8
7
  * resume per gate).
9
8
  *
@@ -1,6 +1,6 @@
1
1
  import type { AdBreakConfig } from "./types.js";
2
2
  /**
3
- * FreeWheel ad configuration — the web counterpart of the Android/iOS
3
+ * FreeWheel ad configuration
4
4
  * `FreewheelConfig`, field-for-field. Pure data: no FreeWheel SDK
5
5
  * dependency.
6
6
  *
@@ -9,7 +9,7 @@ import type { AdBreakConfig } from "./types.js";
9
9
  * builds the network's `/ad/g/1` VMAP request; play it with
10
10
  * `ImaAdsProvider` via `adBreaks: { adTagUri }`. Works today.
11
11
  * (b) A native FreeWheel HTML5 provider (their customer-licensed
12
- * AdManager.js) — ships later as an adapter, like the iOS one.
12
+ * AdManager.js) — ships later as an adapter.
13
13
  *
14
14
  * Consent and identity parameters (`_fw_gdpr`, `_fw_gdpr_consent`, device
15
15
  * ids…) are the HOST's responsibility via `globalParameters` — the SDK
@@ -47,6 +47,6 @@ export declare function isFreewheelConfig(c: AdBreakConfig): c is FreewheelConfi
47
47
  /**
48
48
  * Build the VMAP tag URL for a FreeWheel network — integration option (a):
49
49
  * feed the result to the IMA provider as a plain ad tag. Matches the request
50
- * shape of the Android `asVmapTag` reference implementation.
50
+ * shape of the `asVmapTag` reference implementation.
51
51
  */
52
52
  export declare function freewheelVmapTagUrl(cfg: FreewheelConfig): string;
package/dist/ads/ima.d.ts CHANGED
@@ -2,7 +2,6 @@ import type { AdBreakConfig } from "./types.js";
2
2
  import type { AdsProvider, AdsProviderCallbacks } from "./provider.js";
3
3
  /**
4
4
  * Google IMA (HTML5) implementation of the OGPlayer ads SPI — the web
5
- * counterpart of Android's `ImaAdsProvider` / iOS's `IMAAdsProvider`.
6
5
  * Client-side VAST/VMAP: IMA plays the ad in its own layer over the paused
7
6
  * content element, then hands playback back.
8
7
  *
@@ -1,7 +1,7 @@
1
1
  import type { AdBreakConfig, AdBreakType, AdInfo, OGAdError } from "./types.js";
2
2
  /**
3
3
  * Events an `AdsProvider` reports back to the player — the web counterpart
4
- * of the Android/iOS `AdsProviderCallbacks`. Implemented by `OGPlayer`. In
4
+ * Implemented by `OGPlayer`. In
5
5
  * addition to the ad lifecycle, the provider drives content pause/resume
6
6
  * (client-side ads play while the content element is paused).
7
7
  */
@@ -12,6 +12,14 @@ export interface AdsProviderCallbacks {
12
12
  onAdCompleted(ad: AdInfo): void;
13
13
  onAdBreakCompleted(breakType: AdBreakType): void;
14
14
  onAdPaused(ad: AdInfo): void;
15
+ /** The viewer tapped/clicked the ad itself — not its skip, clickthrough or
16
+ * AdChoices control. Providers that own the layer over the video (IMA)
17
+ * report it and the SDK toggles the ad's playback; a provider that draws
18
+ * nothing there never needs to (the stage click handles that). Optional. */
19
+ onAdTapped?(ad: AdInfo): void;
20
+ /** The viewer opened the ad's clickthrough: a new tab/window covers the page.
21
+ * The SDK pauses the ad and resumes it when the page is visible again. Optional. */
22
+ onAdClicked?(ad: AdInfo): void;
15
23
  onAdResumed(ad: AdInfo): void;
16
24
  onAdProgress(ad: AdInfo, positionMs: number, durationMs: number): void;
17
25
  onAdError(error: OGAdError): void;
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Ads SPI — same shape as Android's `com.ogplayer.api.ads`. Web ad providers
2
+ * Ads SPI. Web ad providers
3
3
  * (Google IMA HTML5, native slot providers) plug in behind this; the first
4
4
  * provider ships in a later release, the types are stable now so host code
5
5
  * written against them doesn't churn.
6
6
  */
7
- /** Marker for per-item ad configuration (mirrors Android `AdBreakConfig`). */
7
+ /** Marker for per-item ad configuration (. */
8
8
  export interface AdBreakConfig {
9
9
  }
10
10
  /** A VAST/VMAP ad tag (consumed by an IMA-style provider). */
@@ -36,6 +36,8 @@ export interface AdListener {
36
36
  onAdBreakCompleted?(breakType: AdBreakType): void;
37
37
  onAdPaused?(ad: AdInfo): void;
38
38
  onAdResumed?(ad: AdInfo): void;
39
+ /** The viewer opened the ad's clickthrough; the SDK pauses the ad and resumes it when the page is visible again. */
40
+ onAdClicked?(ad: AdInfo): void;
39
41
  onAdProgress?(ad: AdInfo, positionMs: number, durationMs: number): void;
40
42
  onAdSkippableStateChanged?(ad: AdInfo, isSkippable: boolean, skipOffsetMs: number): void;
41
43
  onAdError?(error: OGAdError): void;
@@ -14,7 +14,7 @@ export interface FairPlayConfig {
14
14
  }
15
15
  /**
16
16
  * FairPlay Streaming via standard EME on Safari's NATIVE HLS path — the web
17
- * counterpart of the iOS SDK's `AVContentKeySession` flow: fetch the app
17
+ * flow: fetch the app
18
18
  * certificate, then for every encrypted key request POST the SPC to the
19
19
  * license server and feed the CKC back. Widevine/PlayReady run through
20
20
  * hls.js's EME controller instead; this module only ever engages on Safari.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Offline license verification — the web counterpart of the Android/iOS
2
+ * Offline license verification
3
3
  * `LicenseVerifier`, using the SAME ECDSA P-256 keypair: one license issued
4
4
  * by the shared private key unlocks all three platforms. No network, ever.
5
5
  *
@@ -5,7 +5,7 @@ import type { AdsProvider } from "../ads/provider.js";
5
5
  export interface OGPlayerOptions {
6
6
  /** Offline license key (`OGP1.…`); without one the watermark shows. */
7
7
  licenseKey?: string;
8
- /** onProgress cadence, default 250ms (Android DEFAULT_PROGRESS_INTERVAL_MS). */
8
+ /** onProgress cadence, default 250ms. */
9
9
  progressUpdateIntervalMs?: number;
10
10
  /** Seek button increments, default 10s each way. */
11
11
  seekForwardIncrementMs?: number;
@@ -32,8 +32,7 @@ export interface LoadOptions {
32
32
  autoplay?: boolean;
33
33
  }
34
34
  /**
35
- * The OGPlayer playback engine — the web counterpart of the Android
36
- * `OGPlayer` (the reference platform), wrapping an HTML `<video>` element:
35
+ * The OGPlayer playback engine
37
36
  * HLS via hls.js (MSE) everywhere, natively on Safari, progressive files
38
37
  * directly. UI is `<og-player>` from the `ui` module; the engine also works
39
38
  * fully headless.
@@ -90,6 +89,10 @@ export declare class OGPlayer {
90
89
  private isPlayingAdFlag;
91
90
  private adsPendingFlag;
92
91
  private adPausedFlag;
92
+ /** A clickthrough paused the ad and its tab covers the page — see onAdClicked. */
93
+ private adClickthroughPending;
94
+ private readonly onVisibilityForClickthrough;
95
+ private clearClickthrough;
93
96
  private adProgressValue;
94
97
  private adCuePointsValue;
95
98
  private lastAdInfo;
@@ -117,14 +120,13 @@ export declare class OGPlayer {
117
120
  get isMuted(): boolean;
118
121
  set isMuted(v: boolean);
119
122
  /** Loop the current item seamlessly (native `<video loop>`); survives
120
- * across load() calls, mirroring Android/iOS `setLooping`. */
123
+ * across load() calls,. */
121
124
  get isLooping(): boolean;
122
125
  setLooping(v: boolean): void;
123
126
  /**
124
127
  * Buffer discipline for pooled players (the vertical feed): STANDBY caps
125
128
  * appetite (10s forward / 8MB, no back-buffer, metadata-only preload for
126
- * progressive sources); ACTIVE restores full defaults. Mirrors Android's
127
- * `setBufferRole` / iOS `setPreferredForwardBufferDuration`.
129
+ * progressive sources); ACTIVE restores full defaults.
128
130
  */
129
131
  setBufferRole(role: "STANDBY" | "ACTIVE"): void;
130
132
  /** Web routes all volume to the element; kept for API parity. */
@@ -163,12 +165,12 @@ export declare class OGPlayer {
163
165
  removeAdListener(l: AdListener): void;
164
166
  private dispatch;
165
167
  /** Single exit for analytics: every event leaves stamped with the session
166
- * id and asset URL of the load it belongs to (Android parity). */
168
+ * id and asset URL of the load it belongs to. */
167
169
  private emit;
168
170
  /** @internal Feeds a view-layer analytics event into this player's stream,
169
171
  * session-stamped like every other event. Called by the SDK's own elements
170
172
  * (`<og-player>`) — not host-app API (the web `emitViewAnalytics` of
171
- * Android's internal hook; kept off the docs surface via `@internal`). */
173
+ * an internal hook; kept off the docs surface via `@internal`). */
172
174
  emitViewAnalytics(e: Extract<AnalyticsEvent, {
173
175
  type: "FullscreenChanged" | "OrientationChanged";
174
176
  }>): void;
@@ -251,7 +253,7 @@ export declare class OGPlayer {
251
253
  pause(): void;
252
254
  skipAd(): void;
253
255
  clickAd(): void;
254
- /** Ad-break cue positions in ms, Android encoding (postroll = duration). */
256
+ /** Ad-break cue positions in ms (postroll = duration). */
255
257
  get adCuePositionsMs(): number[];
256
258
  /** True when the current item carries a storyboard (trick-play) track. */
257
259
  get hasThumbnails(): boolean;
@@ -4,7 +4,7 @@ import type { BufferReason } from "./types.js";
4
4
  * (`BufferReason`) and time-to-first-frame. Reset by every load; driven by
5
5
  * the media-element events the player receives ('seeking', 'seeked',
6
6
  * 'canplay'/'playing'). Pure logic — unit-tested in node without a DOM.
7
- * The web port of Android's `PlaybackSessionTracker` (the reference).
7
+ * The web.
8
8
  */
9
9
  export declare class PlaybackSessionTracker {
10
10
  private readySeen;
@@ -1,6 +1,6 @@
1
1
  import type { DrmTokenProvider, DrmTokenRequest } from "./types.js";
2
2
  /**
3
- * Fenced DRM token fetch — the web counterpart of the Android SDK's
3
+ * Fenced DRM token fetch
4
4
  * `OGMediaDrmCallback.fetchToken()`: a hung token service must never hold
5
5
  * playback forever. Bounded attempts with a per-attempt timeout and a
6
6
  * progressive backoff; the last failure propagates so callers map it to
@@ -9,7 +9,7 @@ import type { DrmTokenProvider, DrmTokenRequest } from "./types.js";
9
9
  export declare const TOKEN_ATTEMPTS = 3;
10
10
  export declare const TOKEN_TIMEOUT_MS = 8000;
11
11
  /** Whole-call deadline for license/certificate HTTP requests — the web
12
- * mirror of Android's `boundedHttpClient` callTimeout and iOS's
12
+ *
13
13
  * `timeoutIntervalForResource` (15 s on every platform). */
14
14
  export declare const LICENSE_CALL_TIMEOUT_MS = 15000;
15
15
  export declare function fetchTokenHeaders(provider: DrmTokenProvider, request: DrmTokenRequest, timeoutMs?: number): Promise<Record<string, string>>;
@@ -1,7 +1,5 @@
1
1
  /**
2
- * OGPlayer web SDK — public model types. The web counterpart of Android's
3
- * `com.ogplayer.api` (the reference platform): same names, same semantics,
4
- * so code and docs translate 1:1 across Android / iOS / web.
2
+ * OGPlayer web SDK — public model types.
5
3
  */
6
4
  export type StreamType = "VOD" | "LIVE" | "LIVE_DVR";
7
5
  export type PlaybackState = "IDLE" | "BUFFERING" | "READY" | "ENDED";
@@ -56,15 +54,14 @@ export interface DrmTokenRequest {
56
54
  }
57
55
  /**
58
56
  * Fresh headers for every license request — the web counterpart of the
59
- * Android/iOS token providers. Called per request (renewals included) so
57
+ * token providers. Called per request (renewals included) so
60
58
  * expiring tokens can rotate; the result is merged OVER the scheme's static
61
59
  * `headers`. Failures surface as DRM_TOKEN_FETCH_FAILED (4002).
62
60
  */
63
61
  export type DrmTokenProvider = (request: DrmTokenRequest) => Promise<Record<string, string>>;
64
62
  /**
65
- * Multi-DRM configuration the web counterpart of Android's `DrmConfig` /
66
- * iOS's `FairPlayConfig`, unified: configure every scheme you have and the
67
- * SDK picks whichever the visitor's browser supports (Chrome/Firefox/Android
63
+ * Multi-DRM configuration: configure every scheme you have and the
64
+ * SDK picks whichever the visitor's browser supports (Chrome/Firefox
68
65
  * → Widevine, Edge → PlayReady or Widevine, Safari → FairPlay).
69
66
  */
70
67
  export interface DrmConfig {
@@ -119,7 +116,7 @@ export interface LiveInfo {
119
116
  latencyMs: number;
120
117
  playheadWallClockMs: number | null;
121
118
  }
122
- /** Android's PlaybackListener, method-for-method. All members optional. */
119
+ /** Playback lifecycle callbacks. All members optional. */
123
120
  export interface PlaybackListener {
124
121
  onStateChanged?(state: PlaybackState): void;
125
122
  onPlay?(): void;
@@ -169,7 +166,7 @@ export interface AnalyticsEventBase {
169
166
  assetUrl?: string;
170
167
  }
171
168
  /** Why a `PlaybackRecovered` happened. Web values are the hls.js self-healing
172
- * classes; the Android values (`DRM_RENEWAL_AFTERSHOCK`, `CODEC_RESTART`,
169
+ * classes; the native values (`DRM_RENEWAL_AFTERSHOCK`, `CODEC_RESTART`,
173
170
  * `LIVE_WINDOW_RESET`) are listed so shared mappers can switch over one type. */
174
171
  export type RecoveryReason = "NETWORK_RETRY" | "BUFFER_STALL" | "DRM_RETRY" | "MEDIA_RETRY" | "DRM_RENEWAL_AFTERSHOCK" | "CODEC_RESTART" | "LIVE_WINDOW_RESET";
175
172
  export type AnalyticsEvent = AnalyticsEventBase & ({
@@ -252,8 +249,7 @@ export type AnalyticsEvent = AnalyticsEventBase & ({
252
249
  * `onError` did not fire, but the viewer may have seen a short rebuffer.
253
250
  * Count these for QoE; they are recoveries, not failures. On web this is
254
251
  * hls.js's own retry/stall handling (`detail` carries the hls.js error
255
- * detail for diagnosis); Android reports its silent re-prepares here
256
- * under its own reasons. */
252
+ * detail for diagnosis). */
257
253
  | {
258
254
  type: "PlaybackRecovered";
259
255
  reason: RecoveryReason;
@@ -282,7 +278,7 @@ export type AnalyticsEvent = AnalyticsEventBase & ({
282
278
  error: OGPlayerError;
283
279
  });
284
280
  export type OGAnalyticsListener = (event: AnalyticsEvent) => void;
285
- /** Error taxonomy — same numeric codes as Android/iOS. */
281
+ /** Error taxonomy — the same numeric codes on every platform. */
286
282
  export declare const ErrorCodes: {
287
283
  readonly NETWORK_CONNECTION_FAILED: 2000;
288
284
  readonly NETWORK_TIMEOUT: 2001;
@@ -2,8 +2,7 @@ import { OGPlayer } from "./player.js";
2
2
  import type { AnalyticsEvent, OGMediaItem, OGPlayerError } from "./types.js";
3
3
  /**
4
4
  * Vertical feed data model + player pool — the web counterpart of the
5
- * Android `VerticalFeedPlayerPool` (the reference implementation) and its
6
- * iOS mirror. The pool owns at most `preloadAhead + keepBehind + 1` (≤3)
5
+ * native pools. The pool owns at most `preloadAhead + keepBehind + 1` (≤3)
7
6
  * engine instances: neighbours of the visible page sit PREPARED — muted,
8
7
  * paused at 0, on capped standby buffers — so swipes start instantly;
9
8
  * pages outside the window are recycled; everything is released on dispose.
@@ -47,7 +46,7 @@ export interface OGVerticalFeedItem {
47
46
  /** Marks an ad item: "Sponsored" chip, never loops, auto-advances. */
48
47
  isSponsored?: boolean;
49
48
  }
50
- /** All knobs, mirroring the Android `OGVerticalFeedConfig` names. */
49
+ /** All knobs,. */
51
50
  export interface OGVerticalFeedConfig {
52
51
  preloadAhead: number;
53
52
  keepBehind: number;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * OGPlayer web SDK — one video player API across Android, iOS and the web.
2
+ * OGPlayer web SDK.
3
3
  * A product of Inverse DOO.
4
4
  */
5
5
  export { OGPlayer, type OGPlayerOptions, type LoadOptions } from "./core/player.js";
@@ -14,6 +14,7 @@ export { OGPlayerElement, defineOGPlayerElement, hidingAllControls, type OGUICon
14
14
  export { VerticalFeedPlayerPool, defaultVerticalFeedConfig, type OGVerticalFeedItem, type OGVerticalFeedConfig, type RailAction, type SplitAudioSource, type TextPlacement, type VerticalFeedContentFit, } from "./core/vertical-feed.js";
15
15
  export { OGVerticalFeedElement, defineOGVerticalFeedElement } from "./ui/og-vertical-feed.js";
16
16
  export type { OGControlColors, OGControlDimens } from "./ui/tokens.js";
17
+ export { DEFAULT_KEYMAP, type OGKeyAction, type OGKeymap } from "./ui/keymap.js";
17
18
  export { defaultColors, embeddedDimens, fullscreenDimens } from "./ui/tokens.js";
18
19
  /** Build timestamp of this bundle (diagnosing stale caches). */
19
20
  export declare const OGPLAYER_BUILD: string;