boss-web-player-sdk 2.0.1 → 2.0.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/README.md CHANGED
@@ -1,366 +1,366 @@
1
- # boss-web-player-sdk
2
-
3
- A unified, high-performance OTT web video player SDK for adaptive streaming — HLS/DASH, token-based DRM, dynamic watermarking, captions, chapters, casting, and premium UI controls.
4
-
5
- > **Heads up:** the high-level `<BossVideoPlayer>` component is **tenant-gated**. It validates your GoBOSS player key before playback starts, and resolves its feature set (subtitles, DRM, chromecast, etc.) from your plan. Obtain a player key from the GoBOSS dashboard and supply it from your app config (never commit real keys). For a generic, ungated player use the [headless core entry](#headless-core-no-react).
6
-
7
- ## Features
8
-
9
- - **Adaptive streaming** — HLS (bundled `hls.js`) and DASH (bundled `dashjs`) with automatic quality switching
10
- - **DRM** — token-based authorization, FairPlay / Widevine, dynamic watermarking
11
- - **Rich controls** — quality, playback speed, subtitles, PiP, fullscreen, chapters/key-moments
12
- - **Casting** — Chromecast and AirPlay
13
- - **Server-side ads (SSAI)** — AWS MediaTailor ad-break tracking and skip-ad flow
14
- - **Episodic playback** — Skip Intro and an auto-advancing Next Episode chip, for series content
15
- - **Analytics** — first-party session/event telemetry, plus an `onAnalyticsEvent` callback
16
- - **Framework-agnostic** — React component, a vanilla `createPlayer()` mount, and a zero-React headless core
17
-
18
- ## Installation
19
-
20
- ```bash
21
- npm install boss-web-player-sdk
22
- ```
23
-
24
- ### Peer dependencies
25
-
26
- | Package | Required? | Notes |
27
- |---|---|---|
28
- | `react`, `react-dom` (`^18` or `^19`) | **Required** for the React component & `createPlayer` | Not needed if you only use the headless `/core` entry |
29
-
30
- > **DASH works out of the box.** `dashjs` is bundled into the SDK (lazily, like `hls.js`) — you do **not** need to install it separately. The DASH engine is only fetched by the browser when a `.mpd` stream actually plays, so HLS-only apps never download it.
31
-
32
- ### CSS — required, import once
33
-
34
- > **The player stylesheet must be imported separately.** The SDK ships CSS as a standalone
35
- > file so your bundler can handle it correctly (critical for SSR frameworks like Next.js).
36
- > Forgetting this import will result in a broken, unstyled player.
37
-
38
- ```ts
39
- import 'boss-web-player-sdk/css';
40
- ```
41
-
42
- Import it once at your app entry point (e.g. `main.tsx`, `_app.tsx`, `layout.tsx`) and it
43
- applies globally — you do not need to import it in every file that uses `<BossVideoPlayer>`.
44
-
45
- ## Quick start (React)
46
-
47
- ```tsx
48
- import { BossVideoPlayer } from 'boss-web-player-sdk';
49
- import 'boss-web-player-sdk/css';
50
-
51
- export default function App() {
52
- return (
53
- <BossVideoPlayer
54
- playerKey={process.env.NEXT_PUBLIC_PLAYER_KEY!} // from your app config / env (required)
55
- src="https://cdn.example.com/video.m3u8" // HLS (.m3u8) or DASH (.mpd)
56
- title="My Video"
57
- themeColor="#6366f1"
58
- autoplay
59
- muted
60
- />
61
- );
62
- }
63
- ```
64
-
65
- The component shows a loading spinner while it validates the player key, then renders the
66
- player. If the key is invalid or the API is unreachable, it renders an error state instead.
67
-
68
- ## Next.js
69
-
70
- The SDK works in Next.js (both Pages Router and App Router). The player is entirely
71
- client-side — it uses browser APIs (`HTMLVideoElement`, `window`, `navigator`) that do not
72
- exist on the server.
73
-
74
- **App Router** — mark any file that imports the player as a Client Component:
75
-
76
- ```tsx
77
- // app/watch/page.tsx
78
- 'use client';
79
-
80
- import { BossVideoPlayer } from 'boss-web-player-sdk';
81
-
82
- export default function WatchPage() {
83
- return (
84
- <BossVideoPlayer
85
- playerKey={process.env.NEXT_PUBLIC_PLAYER_KEY!}
86
- src="https://cdn.example.com/video.m3u8"
87
- autoplay
88
- muted
89
- />
90
- );
91
- }
92
- ```
93
-
94
- Import the CSS in your root layout so it loads once for the whole app:
95
-
96
- ```tsx
97
- // app/layout.tsx
98
- import 'boss-web-player-sdk/css';
99
-
100
- export default function RootLayout({ children }: { children: React.ReactNode }) {
101
- return <html><body>{children}</body></html>;
102
- }
103
- ```
104
-
105
- **Pages Router** — import the CSS in `_app.tsx` (or `_app.js`):
106
-
107
- ```tsx
108
- // pages/_app.tsx
109
- import 'boss-web-player-sdk/css';
110
- import type { AppProps } from 'next/app';
111
-
112
- export default function App({ Component, pageProps }: AppProps) {
113
- return <Component {...pageProps} />;
114
- }
115
- ```
116
-
117
- No `'use client'` directive is needed in the Pages Router — all pages are client-rendered
118
- by default.
119
-
120
- ## `<BossVideoPlayer>` props
121
-
122
- ```ts
123
- interface BossVideoPlayerProps {
124
- // ── Required ──────────────────────────────────────────────
125
- playerKey: string; // from your GoBOSS dashboard — supply via app config/env
126
- src: string; // HLS (.m3u8) or DASH (.mpd) URL
127
-
128
- // ── Identity / theming ────────────────────────────────────
129
- title?: string; // Title shown in the player UI
130
- watermark?: string; // Watermark text stamped on the video
131
- themeColor?: string; // Accent color (hex). Default '#6366f1'
132
- licenseKey?: string; // Required by DRM-enabled plans (presence-checked)
133
-
134
- // ── Networking ────────────────────────────────────────────
135
- apiBaseUrl?: string; // API base override: reverse proxy path, or the staging host
136
- proxyDomains?: string; // CORS proxy map, "host=/path,host2=/path2" (see CORS)
137
-
138
- // ── Ads (AWS MediaTailor SSAI) ────────────────────────────
139
- adTrackingUrl?: string; // Ad-break tracking URL
140
- overlayAdUrl?: string; // Overlay ad tracking URL
141
- enableSkipAd?: boolean;
142
- skipAdAfterSeconds?: number;
143
-
144
- // ── Series / episodic ─────────────────────────────────────
145
- introStartTime?: number; // Content-relative intro start, in seconds
146
- introEndTime?: number; // Content-relative intro end, in seconds — Skip Intro seeks here
147
- hasNextEpisode?: boolean; // Whether another episode is available to auto-advance into
148
- outroStartTime?: number; // Content-relative outro/credits start, in seconds — reveals the Next Episode chip
149
- nextEpisodeLabel?: string; // Label on the Next Episode chip. Default 'Next Episode'
150
- nextEpisodeAutoAdvanceSeconds?: number; // Seconds before auto-advancing once the chip is shown. Default 5
151
- onNextEpisode?: () => void; // Called on chip click, or when the auto-advance timer fires
152
-
153
- // ── Behavior / UI ─────────────────────────────────────────
154
- autoplay?: boolean; // Default false
155
- muted?: boolean; // Default false (use with autoplay — browsers block unmuted autoplay)
156
- autoFullscreen?: boolean;
157
- enableControls?: boolean; // Default true
158
- chaptersDisplayMode?: 'strip' | 'panel'; // Default 'strip'
159
- volumeControlType?: 'slider' | 'button'; // Default 'slider'
160
- subtitleStyle?: { size?: 'small'|'medium'|'large'; background?: 'none'|'dim'|'solid'; color?: string };
161
-
162
- // ── Integrations ──────────────────────────────────────────
163
- drmConfig?: DRMConfig; // DRM license / token configuration
164
-
165
- // ── Callbacks ─────────────────────────────────────────────
166
- onAnalyticsEvent?: (event: AnalyticsEvent) => void; // Every analytics event
167
- onKeyMomentsLoaded?: (keyMoments: Chapter[]) => void; // When chapters parse from the stream
168
- onTimeUpdate?: (currentTime: number) => void; // Every timeupdate — use to persist watch progress
169
-
170
- // ── Resume playback ───────────────────────────────────────
171
- initialTime?: number; // Seek to this position (seconds) once the video is ready
172
- }
173
- ```
174
-
175
- ### Skip Intro / Next Episode (series)
176
-
177
- Both are driven entirely by props — the SDK owns the timing, the chip UI, and the seek/auto-advance
178
- behavior. All times are **content-relative** (the original episode timeline), so they stay correct
179
- even if the stream has spliced ad breaks.
180
-
181
- ```tsx
182
- <BossVideoPlayer
183
- playerKey={playerKey}
184
- src="https://cdn.example.com/episode-04.m3u8"
185
- introStartTime={0}
186
- introEndTime={78} // Skip Intro shows between 0s–78s, seeks to 78s on click
187
- hasNextEpisode={true}
188
- outroStartTime={1230} // Next Episode chip appears once playback reaches 1230s
189
- nextEpisodeLabel="S2 · E5" // optional — defaults to "Next Episode"
190
- nextEpisodeAutoAdvanceSeconds={5} // optional — auto-advances 5s after the chip appears
191
- onNextEpisode={() => loadNextEpisode()}
192
- />
193
- ```
194
-
195
- > Feature availability (subtitles, chromecast, DRM, multiple resolutions, etc.) is **resolved from your
196
- > plan** by the GoBOSS API at init — it is not toggled by individual props on this component.
197
-
198
- ## Use without JSX — `createPlayer()`
199
-
200
- For Vue, Angular, Svelte, or vanilla JS. Renders the same gated `<BossVideoPlayer>` into any element.
201
-
202
- ```ts
203
- import { createPlayer } from 'boss-web-player-sdk';
204
- import 'boss-web-player-sdk/css';
205
-
206
- const player = createPlayer(document.getElementById('player')!, {
207
- playerKey, // from your app config / env
208
- src: 'https://cdn.example.com/video.m3u8',
209
- autoplay: true,
210
- muted: true,
211
- });
212
-
213
- player.update({ src: 'https://cdn.example.com/other.m3u8' }); // re-render with new props
214
- player.destroy(); // unmount & release resources
215
- ```
216
-
217
- ## Headless core (no React)
218
-
219
- Import from the `/core` subpath for a zero-React, zero-UI player and modules. This entry is **not**
220
- player-key gated — you drive everything yourself.
221
-
222
- ```ts
223
- import { VideoPlayerSDK } from 'boss-web-player-sdk/core';
224
-
225
- const player = new VideoPlayerSDK({
226
- container: document.getElementById('player')!,
227
- src: 'https://cdn.example.com/video.m3u8',
228
- autoplay: false,
229
- muted: false,
230
- });
231
-
232
- // Playback
233
- player.play();
234
- player.pause();
235
- player.seek(30);
236
- player.setVolume(0.8);
237
- player.setMute(false);
238
- player.setPlaybackRate(1.5);
239
- player.setQuality(qualityId); // id from a `qualitylevels` event entry
240
-
241
- // Events (EventEmitter-style)
242
- player.on('play', () => {});
243
- player.on('qualitychange', (q) => {});
244
- player.on('subtitlesloaded', (tracks) => {});
245
-
246
- player.destroy(); // clean up
247
- ```
248
-
249
- **Emitted events:** `play`, `pause`, `ended`, `timeupdate`, `seeking`, `buffering`, `volumechange`,
250
- `ratechange`, `pipchange`, `error`, `qualitylevels`, `qualitychange`, `subtitlesloaded`,
251
- `audiotracksloaded`, `audiotrackchange`, `keymomentsloaded`, `chaptersloaded`, `adbreaksloaded`,
252
- `adbreakchange`.
253
-
254
- The `/core` entry also exposes the individual modules: `AnalyticsModule`,
255
- `SubtitlesModule`, `ThumbnailsModule`, `KeyMomentsModule`, `ChaptersModule`, `CastingModule`,
256
- `DRMModule`, and `BasePlayerPlugin`.
257
-
258
- ## CORS & proxying
259
-
260
- The player fetches the manifest and media segments **from the browser**, so those origins must send CORS
261
- headers. Two tools help:
262
-
263
- - **`apiBaseUrl`** — optional override for GoBOSS API calls. Use it for a same-origin reverse proxy
264
- during local development, or to point a non-production build at the staging API
265
- (`apiBaseUrl="https://dev-api.go-boss.com"`). Omit it in production, where the default is the
266
- production API host.
267
- - **`proxyDomains`** — a comma-separated `"<host>=/<proxyPath>"` map. Any stream URL whose host matches is
268
- rewritten to `<proxyPath><pathname><search>`, and applied to the manifest **and** every segment/key
269
- request. Back each `<proxyPath>` with a same-origin dev proxy.
270
-
271
- ```tsx
272
- <BossVideoPlayer
273
- playerKey={playerKey}
274
- src="https://master.example.com/index.m3u8"
275
- apiBaseUrl="/api-proxy"
276
- proxyDomains="segments.example.com=/seg-proxy,master.example.com=/mt-proxy"
277
- />
278
- ```
279
-
280
- > Proxying is a **development** convenience. For production, configure CORS on the content origin
281
- > (S3 / CloudFront / MediaTailor) — you cannot proxy every viewer's traffic.
282
-
283
- ## DRM
284
-
285
- ```ts
286
- const drmConfig = {
287
- authToken: 'bearer-token', // sent with license/segment requests
288
- watermarkText: 'Your Brand',
289
- fairplayLicenseUrl: 'https://...', // Safari / Apple
290
- widevineServiceUrl: 'https://...', // Chrome / Android
291
- };
292
- ```
293
-
294
- `licenseKey` is a separate, plan-level gate: when your resolved plan has DRM enabled, a non-empty
295
- `licenseKey` must be provided or the player shows a "Playback restricted" overlay.
296
-
297
- ## Analytics
298
-
299
- Every player event flows through `onAnalyticsEvent`:
300
-
301
- ```tsx
302
- <BossVideoPlayer
303
- playerKey={playerKey}
304
- src="https://cdn.example.com/video.m3u8"
305
- onAnalyticsEvent={(e) => console.log(e.eventType, e)}
306
- />
307
- ```
308
-
309
- To forward events anywhere else — your own warehouse, a third-party analytics product — use
310
- `onAnalyticsEvent` and send them on from there. The SDK reports session and event telemetry to the
311
- GoBOSS backend on its own; `onAnalyticsEvent` is purely additive and does not replace it.
312
-
313
- ## Keyboard shortcuts
314
-
315
- | Key | Action |
316
- |---|---|
317
- | `Space` / `K` | Play / Pause |
318
- | `J` / `←` | Seek back 10s |
319
- | `L` / `→` | Seek forward 10s |
320
- | `↑` / `↓` | Volume ±10% |
321
- | `M` | Mute toggle |
322
- | `F` | Fullscreen toggle |
323
- | `P` | Picture-in-Picture toggle |
324
- | `C` | Subtitles toggle |
325
-
326
- ## Exports
327
-
328
- ```ts
329
- // React component (gated, drop-in)
330
- import { BossVideoPlayer, type BossVideoPlayerProps } from 'boss-web-player-sdk';
331
-
332
- // Framework-agnostic mount
333
- import { createPlayer, type PlayerProps, type PlayerInstance } from 'boss-web-player-sdk';
334
-
335
- // Lower-level React UI / headless core
336
- import { WebVideoPlayer, VideoPlayerSDK } from 'boss-web-player-sdk';
337
-
338
- // Advanced: raw SDK API calls
339
- import { initSdk, startSession, sendHeartbeat, endSession, sendEvent } from 'boss-web-player-sdk';
340
-
341
- // Types
342
- import type {
343
- AnalyticsEvent, AnalyticsCallback, Chapter, KeyMoment, SubtitleTrack,
344
- VideoQuality, ThumbnailConfig, DRMConfig, PlayerSDKOptions,
345
- FeatureFlags, SubtitleStyle,
346
- } from 'boss-web-player-sdk';
347
- ```
348
-
349
- ## Browser support
350
-
351
- | Browser | Version |
352
- |---|---|
353
- | Chrome / Edge | 90+ |
354
- | Firefox | 88+ |
355
- | Safari (incl. iOS) | 14+ |
356
- | Android Chrome | 90+ |
357
-
358
- ## Module formats
359
-
360
- Ships **ES Module** (`dist/index.js`) and **CommonJS** (`dist/index.cjs`) builds with bundled TypeScript
361
- definitions and an extracted stylesheet (`boss-web-player-sdk/css`). `react` and `react-dom` are
362
- externalized (see peer dependencies); `hls.js` and `dashjs` are bundled (lazily).
363
-
364
- ## License
365
-
366
- MIT — see [LICENSE](./LICENSE).
1
+ # boss-web-player-sdk
2
+
3
+ A unified, high-performance OTT web video player SDK for adaptive streaming — HLS/DASH, token-based DRM, dynamic watermarking, captions, chapters, casting, and premium UI controls.
4
+
5
+ > **Heads up:** the high-level `<BossVideoPlayer>` component is **tenant-gated**. It validates your GoBOSS player key before playback starts, and resolves its feature set (subtitles, DRM, chromecast, etc.) from your plan. Obtain a player key from the GoBOSS dashboard and supply it from your app config (never commit real keys). For a generic, ungated player use the [headless core entry](#headless-core-no-react).
6
+
7
+ ## Features
8
+
9
+ - **Adaptive streaming** — HLS (bundled `hls.js`) and DASH (bundled `dashjs`) with automatic quality switching
10
+ - **DRM** — token-based authorization, FairPlay / Widevine, dynamic watermarking
11
+ - **Rich controls** — quality, playback speed, subtitles, PiP, fullscreen, chapters/key-moments
12
+ - **Casting** — Chromecast and AirPlay
13
+ - **Server-side ads (SSAI)** — AWS MediaTailor ad-break tracking and skip-ad flow
14
+ - **Episodic playback** — Skip Intro and an auto-advancing Next Episode chip, for series content
15
+ - **Analytics** — first-party session/event telemetry, plus an `onAnalyticsEvent` callback
16
+ - **Framework-agnostic** — React component, a vanilla `createPlayer()` mount, and a zero-React headless core
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install boss-web-player-sdk
22
+ ```
23
+
24
+ ### Peer dependencies
25
+
26
+ | Package | Required? | Notes |
27
+ |---|---|---|
28
+ | `react`, `react-dom` (`^18` or `^19`) | **Required** for the React component & `createPlayer` | Not needed if you only use the headless `/core` entry |
29
+
30
+ > **DASH works out of the box.** `dashjs` is bundled into the SDK (lazily, like `hls.js`) — you do **not** need to install it separately. The DASH engine is only fetched by the browser when a `.mpd` stream actually plays, so HLS-only apps never download it.
31
+
32
+ ### CSS — required, import once
33
+
34
+ > **The player stylesheet must be imported separately.** The SDK ships CSS as a standalone
35
+ > file so your bundler can handle it correctly (critical for SSR frameworks like Next.js).
36
+ > Forgetting this import will result in a broken, unstyled player.
37
+
38
+ ```ts
39
+ import 'boss-web-player-sdk/css';
40
+ ```
41
+
42
+ Import it once at your app entry point (e.g. `main.tsx`, `_app.tsx`, `layout.tsx`) and it
43
+ applies globally — you do not need to import it in every file that uses `<BossVideoPlayer>`.
44
+
45
+ ## Quick start (React)
46
+
47
+ ```tsx
48
+ import { BossVideoPlayer } from 'boss-web-player-sdk';
49
+ import 'boss-web-player-sdk/css';
50
+
51
+ export default function App() {
52
+ return (
53
+ <BossVideoPlayer
54
+ playerKey={process.env.NEXT_PUBLIC_PLAYER_KEY!} // from your app config / env (required)
55
+ src="https://cdn.example.com/video.m3u8" // HLS (.m3u8) or DASH (.mpd)
56
+ title="My Video"
57
+ themeColor="#6366f1"
58
+ autoplay
59
+ muted
60
+ />
61
+ );
62
+ }
63
+ ```
64
+
65
+ The component shows a loading spinner while it validates the player key, then renders the
66
+ player. If the key is invalid or the API is unreachable, it renders an error state instead.
67
+
68
+ ## Next.js
69
+
70
+ The SDK works in Next.js (both Pages Router and App Router). The player is entirely
71
+ client-side — it uses browser APIs (`HTMLVideoElement`, `window`, `navigator`) that do not
72
+ exist on the server.
73
+
74
+ **App Router** — mark any file that imports the player as a Client Component:
75
+
76
+ ```tsx
77
+ // app/watch/page.tsx
78
+ 'use client';
79
+
80
+ import { BossVideoPlayer } from 'boss-web-player-sdk';
81
+
82
+ export default function WatchPage() {
83
+ return (
84
+ <BossVideoPlayer
85
+ playerKey={process.env.NEXT_PUBLIC_PLAYER_KEY!}
86
+ src="https://cdn.example.com/video.m3u8"
87
+ autoplay
88
+ muted
89
+ />
90
+ );
91
+ }
92
+ ```
93
+
94
+ Import the CSS in your root layout so it loads once for the whole app:
95
+
96
+ ```tsx
97
+ // app/layout.tsx
98
+ import 'boss-web-player-sdk/css';
99
+
100
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
101
+ return <html><body>{children}</body></html>;
102
+ }
103
+ ```
104
+
105
+ **Pages Router** — import the CSS in `_app.tsx` (or `_app.js`):
106
+
107
+ ```tsx
108
+ // pages/_app.tsx
109
+ import 'boss-web-player-sdk/css';
110
+ import type { AppProps } from 'next/app';
111
+
112
+ export default function App({ Component, pageProps }: AppProps) {
113
+ return <Component {...pageProps} />;
114
+ }
115
+ ```
116
+
117
+ No `'use client'` directive is needed in the Pages Router — all pages are client-rendered
118
+ by default.
119
+
120
+ ## `<BossVideoPlayer>` props
121
+
122
+ ```ts
123
+ interface BossVideoPlayerProps {
124
+ // ── Required ──────────────────────────────────────────────
125
+ playerKey: string; // from your GoBOSS dashboard — supply via app config/env
126
+ src: string; // HLS (.m3u8) or DASH (.mpd) URL
127
+
128
+ // ── Identity / theming ────────────────────────────────────
129
+ title?: string; // Title shown in the player UI
130
+ watermark?: string; // Watermark text stamped on the video
131
+ themeColor?: string; // Accent color (hex). Default '#6366f1'
132
+ licenseKey?: string; // Required by DRM-enabled plans (presence-checked)
133
+
134
+ // ── Networking ────────────────────────────────────────────
135
+ apiBaseUrl?: string; // API base override: reverse proxy path, or the staging host
136
+ proxyDomains?: string; // CORS proxy map, "host=/path,host2=/path2" (see CORS)
137
+
138
+ // ── Ads (AWS MediaTailor SSAI) ────────────────────────────
139
+ adTrackingUrl?: string; // Ad-break tracking URL
140
+ overlayAdUrl?: string; // Overlay ad tracking URL
141
+ enableSkipAd?: boolean;
142
+ skipAdAfterSeconds?: number;
143
+
144
+ // ── Series / episodic ─────────────────────────────────────
145
+ introStartTime?: number; // Content-relative intro start, in seconds
146
+ introEndTime?: number; // Content-relative intro end, in seconds — Skip Intro seeks here
147
+ hasNextEpisode?: boolean; // Whether another episode is available to auto-advance into
148
+ outroStartTime?: number; // Content-relative outro/credits start, in seconds — reveals the Next Episode chip
149
+ nextEpisodeLabel?: string; // Label on the Next Episode chip. Default 'Next Episode'
150
+ nextEpisodeAutoAdvanceSeconds?: number; // Seconds before auto-advancing once the chip is shown. Default 5
151
+ onNextEpisode?: () => void; // Called on chip click, or when the auto-advance timer fires
152
+
153
+ // ── Behavior / UI ─────────────────────────────────────────
154
+ autoplay?: boolean; // Default false
155
+ muted?: boolean; // Default false (use with autoplay — browsers block unmuted autoplay)
156
+ autoFullscreen?: boolean;
157
+ enableControls?: boolean; // Default true
158
+ chaptersDisplayMode?: 'strip' | 'panel'; // Default 'strip'
159
+ volumeControlType?: 'slider' | 'button'; // Default 'slider'
160
+ subtitleStyle?: { size?: 'small'|'medium'|'large'; background?: 'none'|'dim'|'solid'; color?: string };
161
+
162
+ // ── Integrations ──────────────────────────────────────────
163
+ drmConfig?: DRMConfig; // DRM license / token configuration
164
+
165
+ // ── Callbacks ─────────────────────────────────────────────
166
+ onAnalyticsEvent?: (event: AnalyticsEvent) => void; // Every analytics event
167
+ onKeyMomentsLoaded?: (keyMoments: Chapter[]) => void; // When chapters parse from the stream
168
+ onTimeUpdate?: (currentTime: number) => void; // Every timeupdate — use to persist watch progress
169
+
170
+ // ── Resume playback ───────────────────────────────────────
171
+ initialTime?: number; // Seek to this position (seconds) once the video is ready
172
+ }
173
+ ```
174
+
175
+ ### Skip Intro / Next Episode (series)
176
+
177
+ Both are driven entirely by props — the SDK owns the timing, the chip UI, and the seek/auto-advance
178
+ behavior. All times are **content-relative** (the original episode timeline), so they stay correct
179
+ even if the stream has spliced ad breaks.
180
+
181
+ ```tsx
182
+ <BossVideoPlayer
183
+ playerKey={playerKey}
184
+ src="https://cdn.example.com/episode-04.m3u8"
185
+ introStartTime={0}
186
+ introEndTime={78} // Skip Intro shows between 0s–78s, seeks to 78s on click
187
+ hasNextEpisode={true}
188
+ outroStartTime={1230} // Next Episode chip appears once playback reaches 1230s
189
+ nextEpisodeLabel="S2 · E5" // optional — defaults to "Next Episode"
190
+ nextEpisodeAutoAdvanceSeconds={5} // optional — auto-advances 5s after the chip appears
191
+ onNextEpisode={() => loadNextEpisode()}
192
+ />
193
+ ```
194
+
195
+ > Feature availability (subtitles, chromecast, DRM, multiple resolutions, etc.) is **resolved from your
196
+ > plan** by the GoBOSS API at init — it is not toggled by individual props on this component.
197
+
198
+ ## Use without JSX — `createPlayer()`
199
+
200
+ For Vue, Angular, Svelte, or vanilla JS. Renders the same gated `<BossVideoPlayer>` into any element.
201
+
202
+ ```ts
203
+ import { createPlayer } from 'boss-web-player-sdk';
204
+ import 'boss-web-player-sdk/css';
205
+
206
+ const player = createPlayer(document.getElementById('player')!, {
207
+ playerKey, // from your app config / env
208
+ src: 'https://cdn.example.com/video.m3u8',
209
+ autoplay: true,
210
+ muted: true,
211
+ });
212
+
213
+ player.update({ src: 'https://cdn.example.com/other.m3u8' }); // re-render with new props
214
+ player.destroy(); // unmount & release resources
215
+ ```
216
+
217
+ ## Headless core (no React)
218
+
219
+ Import from the `/core` subpath for a zero-React, zero-UI player and modules. This entry is **not**
220
+ player-key gated — you drive everything yourself.
221
+
222
+ ```ts
223
+ import { VideoPlayerSDK } from 'boss-web-player-sdk/core';
224
+
225
+ const player = new VideoPlayerSDK({
226
+ container: document.getElementById('player')!,
227
+ src: 'https://cdn.example.com/video.m3u8',
228
+ autoplay: false,
229
+ muted: false,
230
+ });
231
+
232
+ // Playback
233
+ player.play();
234
+ player.pause();
235
+ player.seek(30);
236
+ player.setVolume(0.8);
237
+ player.setMute(false);
238
+ player.setPlaybackRate(1.5);
239
+ player.setQuality(qualityId); // id from a `qualitylevels` event entry
240
+
241
+ // Events (EventEmitter-style)
242
+ player.on('play', () => {});
243
+ player.on('qualitychange', (q) => {});
244
+ player.on('subtitlesloaded', (tracks) => {});
245
+
246
+ player.destroy(); // clean up
247
+ ```
248
+
249
+ **Emitted events:** `play`, `pause`, `ended`, `timeupdate`, `seeking`, `buffering`, `volumechange`,
250
+ `ratechange`, `pipchange`, `error`, `qualitylevels`, `qualitychange`, `subtitlesloaded`,
251
+ `audiotracksloaded`, `audiotrackchange`, `keymomentsloaded`, `chaptersloaded`, `adbreaksloaded`,
252
+ `adbreakchange`.
253
+
254
+ The `/core` entry also exposes the individual modules: `AnalyticsModule`,
255
+ `SubtitlesModule`, `ThumbnailsModule`, `KeyMomentsModule`, `ChaptersModule`, `CastingModule`,
256
+ `DRMModule`, and `BasePlayerPlugin`.
257
+
258
+ ## CORS & proxying
259
+
260
+ The player fetches the manifest and media segments **from the browser**, so those origins must send CORS
261
+ headers. Two tools help:
262
+
263
+ - **`apiBaseUrl`** — optional override for GoBOSS API calls. Use it for a same-origin reverse proxy
264
+ during local development, or to point a non-production build at the staging API
265
+ (`apiBaseUrl="https://dev-api.go-boss.com"`). Omit it in production, where the default is the
266
+ production API host.
267
+ - **`proxyDomains`** — a comma-separated `"<host>=/<proxyPath>"` map. Any stream URL whose host matches is
268
+ rewritten to `<proxyPath><pathname><search>`, and applied to the manifest **and** every segment/key
269
+ request. Back each `<proxyPath>` with a same-origin dev proxy.
270
+
271
+ ```tsx
272
+ <BossVideoPlayer
273
+ playerKey={playerKey}
274
+ src="https://master.example.com/index.m3u8"
275
+ apiBaseUrl="/api-proxy"
276
+ proxyDomains="segments.example.com=/seg-proxy,master.example.com=/mt-proxy"
277
+ />
278
+ ```
279
+
280
+ > Proxying is a **development** convenience. For production, configure CORS on the content origin
281
+ > (S3 / CloudFront / MediaTailor) — you cannot proxy every viewer's traffic.
282
+
283
+ ## DRM
284
+
285
+ ```ts
286
+ const drmConfig = {
287
+ authToken: 'bearer-token', // sent with license/segment requests
288
+ watermarkText: 'Your Brand',
289
+ fairplayLicenseUrl: 'https://...', // Safari / Apple
290
+ widevineServiceUrl: 'https://...', // Chrome / Android
291
+ };
292
+ ```
293
+
294
+ `licenseKey` is a separate, plan-level gate: when your resolved plan has DRM enabled, a non-empty
295
+ `licenseKey` must be provided or the player shows a "Playback restricted" overlay.
296
+
297
+ ## Analytics
298
+
299
+ Every player event flows through `onAnalyticsEvent`:
300
+
301
+ ```tsx
302
+ <BossVideoPlayer
303
+ playerKey={playerKey}
304
+ src="https://cdn.example.com/video.m3u8"
305
+ onAnalyticsEvent={(e) => console.log(e.eventType, e)}
306
+ />
307
+ ```
308
+
309
+ To forward events anywhere else — your own warehouse, a third-party analytics product — use
310
+ `onAnalyticsEvent` and send them on from there. The SDK reports session and event telemetry to the
311
+ GoBOSS backend on its own; `onAnalyticsEvent` is purely additive and does not replace it.
312
+
313
+ ## Keyboard shortcuts
314
+
315
+ | Key | Action |
316
+ |---|---|
317
+ | `Space` / `K` | Play / Pause |
318
+ | `J` / `←` | Seek back 10s |
319
+ | `L` / `→` | Seek forward 10s |
320
+ | `↑` / `↓` | Volume ±10% |
321
+ | `M` | Mute toggle |
322
+ | `F` | Fullscreen toggle |
323
+ | `P` | Picture-in-Picture toggle |
324
+ | `C` | Subtitles toggle |
325
+
326
+ ## Exports
327
+
328
+ ```ts
329
+ // React component (gated, drop-in)
330
+ import { BossVideoPlayer, type BossVideoPlayerProps } from 'boss-web-player-sdk';
331
+
332
+ // Framework-agnostic mount
333
+ import { createPlayer, type PlayerProps, type PlayerInstance } from 'boss-web-player-sdk';
334
+
335
+ // Lower-level React UI / headless core
336
+ import { WebVideoPlayer, VideoPlayerSDK } from 'boss-web-player-sdk';
337
+
338
+ // Advanced: raw SDK API calls
339
+ import { initSdk, startSession, sendHeartbeat, endSession, sendEvent } from 'boss-web-player-sdk';
340
+
341
+ // Types
342
+ import type {
343
+ AnalyticsEvent, AnalyticsCallback, Chapter, KeyMoment, SubtitleTrack,
344
+ VideoQuality, ThumbnailConfig, DRMConfig, PlayerSDKOptions,
345
+ FeatureFlags, SubtitleStyle,
346
+ } from 'boss-web-player-sdk';
347
+ ```
348
+
349
+ ## Browser support
350
+
351
+ | Browser | Version |
352
+ |---|---|
353
+ | Chrome / Edge | 90+ |
354
+ | Firefox | 88+ |
355
+ | Safari (incl. iOS) | 14+ |
356
+ | Android Chrome | 90+ |
357
+
358
+ ## Module formats
359
+
360
+ Ships **ES Module** (`dist/index.js`) and **CommonJS** (`dist/index.cjs`) builds with bundled TypeScript
361
+ definitions and an extracted stylesheet (`boss-web-player-sdk/css`). `react` and `react-dom` are
362
+ externalized (see peer dependencies); `hls.js` and `dashjs` are bundled (lazily).
363
+
364
+ ## License
365
+
366
+ MIT — see [LICENSE](./LICENSE).