@obipascal/player 1.0.0 → 1.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
@@ -5,6 +5,7 @@ A modern, feature-rich HLS video player SDK for educational platforms with Cloud
5
5
  ## ✨ Features
6
6
 
7
7
  ### Core Playback
8
+
8
9
  - 🎬 **HLS Streaming**: Full HLS.js support with adaptive bitrate streaming
9
10
  - 🔒 **CloudFront Integration**: Native support for CloudFront signed cookies and S3-hosted videos
10
11
  - 🎯 **Skip Controls**: 10-second forward/backward skip with circular arrow buttons
@@ -13,11 +14,13 @@ A modern, feature-rich HLS video player SDK for educational platforms with Cloud
13
14
  - 🎛️ **Playback Rate**: Adjustable speed (0.5x - 2x)
14
15
 
15
16
  ### Subtitle & Accessibility
17
+
16
18
  - 📝 **Subtitle Support**: Full subtitle/caption support with programmatic API
17
19
  - 🌐 **Multi-language**: Support for multiple subtitle tracks with language selection
18
20
  - ♿ **Accessibility**: WCAG compliant with keyboard navigation
19
21
 
20
22
  ### UI & Controls
23
+
21
24
  - 🎨 **Modern UI Design**: Beautiful controls with blur effects, gradients, and smooth animations
22
25
  - 🖱️ **Smart Controls**: Auto-hide on inactivity, fade on hover
23
26
  - 📍 **Sticky Controls**: Optional persistent controls (toggle in settings)
@@ -27,6 +30,7 @@ A modern, feature-rich HLS video player SDK for educational platforms with Cloud
27
30
  - 🎨 **Custom Theming**: Full CSS variable theming with 8 customizable properties
28
31
 
29
32
  ### Developer Experience
33
+
30
34
  - ⚛️ **React Support**: Component, Hook, and Context Provider patterns
31
35
  - 🔧 **TypeScript**: Full TypeScript support with comprehensive type definitions
32
36
  - 📊 **Analytics & QoE**: Built-in analytics tracking and Quality of Experience metrics
@@ -37,13 +41,13 @@ A modern, feature-rich HLS video player SDK for educational platforms with Cloud
37
41
  ## 📦 Installation
38
42
 
39
43
  ```bash
40
- npm install @wontum/player hls.js
44
+ npm install @obipascal/player hls.js
41
45
  ```
42
46
 
43
47
  Or with yarn:
44
48
 
45
49
  ```bash
46
- yarn add @wontum/player hls.js
50
+ yarn add @obipascal/player hls.js
47
51
  ```
48
52
 
49
53
  ## 🚀 Quick Start
@@ -60,7 +64,7 @@ yarn add @wontum/player hls.js
60
64
  <div id="player-container"></div>
61
65
 
62
66
  <script type="module">
63
- import { WontumPlayer } from "@wontum/player"
67
+ import { WontumPlayer } from "@obipascal/player"
64
68
 
65
69
  const player = new WontumPlayer({
66
70
  src: "https://media.example.com/video/playlist.m3u8",
@@ -98,7 +102,7 @@ yarn add @wontum/player hls.js
98
102
  player.on("timeupdate", (event) => {
99
103
  console.log("Current time:", event.data.currentTime)
100
104
  })
101
-
105
+
102
106
  // Programmatic subtitle control
103
107
  player.enableSubtitles(0) // Enable first subtitle track
104
108
  player.toggleSubtitles() // Toggle subtitles on/off
@@ -110,7 +114,7 @@ yarn add @wontum/player hls.js
110
114
  ### React Component
111
115
 
112
116
  ```tsx
113
- import { WontumPlayerReact } from "@wontum/player"
117
+ import { WontumPlayerReact } from "@obipascal/player"
114
118
 
115
119
  function VideoPlayer() {
116
120
  return (
@@ -146,7 +150,7 @@ function VideoPlayer() {
146
150
  ### React Hook (Custom Controls)
147
151
 
148
152
  ```tsx
149
- import { useWontumPlayer } from "@wontum/player"
153
+ import { useWontumPlayer } from "@obipascal/player"
150
154
 
151
155
  function CustomPlayer() {
152
156
  const { containerRef, player, state } = useWontumPlayer({
@@ -182,7 +186,7 @@ function CustomPlayer() {
182
186
  ### React Context Provider
183
187
 
184
188
  ```tsx
185
- import { WontumPlayerProvider, useWontumPlayerContext } from "@wontum/player"
189
+ import { WontumPlayerProvider, useWontumPlayerContext } from "@obipascal/player"
186
190
 
187
191
  function App() {
188
192
  return (
@@ -213,43 +217,165 @@ function ControlPanel() {
213
217
 
214
218
  ## 🔒 CloudFront & S3 Integration
215
219
 
216
- ### CloudFront with Signed Cookies (Recommended)
220
+ This player supports **three video hosting scenarios**. Choose the one that fits your needs:
217
221
 
218
- For secure video delivery, use CloudFront with signed cookies:
222
+ ### Scenario 1: Public Videos (Easiest - No Authentication Required)
219
223
 
220
- ```typescript
221
- import { WontumPlayer } from "@wontum/player"
224
+ **When to use:** Your videos are publicly accessible and don't require user authentication.
225
+
226
+ **Setup:** Just provide the video URL!
222
227
 
223
- // Your backend sets signed cookies for CloudFront
224
- // Cookie names: CloudFront-Policy, CloudFront-Signature, CloudFront-Key-Pair-Id
228
+ ```typescript
229
+ import { WontumPlayer } from "@obipascal/player"
225
230
 
226
231
  const player = new WontumPlayer({
227
- src: "https://media.yourdomain.com/video/playlist.m3u8",
232
+ src: "https://d1234567890.cloudfront.net/video/playlist.m3u8",
228
233
  container: "#player",
229
- s3Config: {
230
- cloudfront: {
231
- domain: "media.yourdomain.com",
232
- // Cookies are automatically sent by browser
233
- },
234
- },
235
234
  })
236
235
  ```
237
236
 
238
- ### CloudFront Signed Cookie Setup (Backend)
237
+ **That's it!** No backend needed. Works for public S3 buckets or CloudFront distributions.
238
+
239
+ ---
240
+
241
+ ### Scenario 2: Private Videos with CloudFront Signed Cookies (Recommended)
242
+
243
+ **When to use:** You want to restrict video access to authorized users (e.g., paid courses, premium content).
244
+
245
+ **How it works:**
246
+
247
+ 1. User logs into your app
248
+ 2. Your backend verifies the user and sets CloudFront signed cookies
249
+ 3. Player automatically sends these cookies with every video request
250
+ 4. CloudFront checks the cookies and allows/denies access
251
+
252
+ **Frontend Setup:**
239
253
 
240
254
  ```typescript
241
- // Node.js backend example
242
- import { CloudFrontClient } from "@aws-sdk/client-cloudfront"
255
+ import { WontumPlayer } from "@obipascal/player"
256
+
257
+ // STEP 1: Call your backend to set signed cookies BEFORE creating the player
258
+ async function initializePlayer() {
259
+ // This endpoint sets CloudFront cookies in the browser
260
+ await fetch("/api/auth/video-access", {
261
+ credentials: "include", // Important: include cookies
262
+ })
263
+
264
+ // STEP 2: Create player - it will automatically use the cookies
265
+ const player = new WontumPlayer({
266
+ src: "https://media.yourdomain.com/videos/lesson-1/playlist.m3u8",
267
+ container: "#player",
268
+ s3Config: {
269
+ cloudFrontDomains: ["media.yourdomain.com"], // Your CloudFront domain
270
+ signUrl: async (url) => {
271
+ // This function is called when player needs to access a video
272
+ // Call your backend to refresh/set cookies if needed
273
+ const response = await fetch("/api/auth/sign-url", {
274
+ method: "POST",
275
+ headers: { "Content-Type": "application/json" },
276
+ credentials: "include",
277
+ body: JSON.stringify({ url }),
278
+ })
279
+
280
+ if (!response.ok) {
281
+ throw new Error("Failed to authenticate video access")
282
+ }
283
+
284
+ // Backend sets cookies, return the URL
285
+ return url
286
+ },
287
+ },
288
+ })
289
+ }
290
+
291
+ initializePlayer()
292
+ ```
293
+
294
+ **Backend Setup (Node.js/Express):**
295
+
296
+ ```typescript
297
+ import express from "express"
243
298
  import { getSignedCookies } from "@aws-sdk/cloudfront-signer"
299
+ import fs from "fs"
300
+
301
+ const app = express()
244
302
 
245
- app.get("/api/video-auth", async (req, res) => {
303
+ // STEP 1: Create endpoint that sets CloudFront signed cookies
304
+ app.get("/api/auth/video-access", (req, res) => {
305
+ // Check if user is logged in (your authentication logic)
306
+ if (!req.user) {
307
+ return res.status(401).json({ error: "Not authenticated" })
308
+ }
309
+
310
+ // Define what resources user can access
311
+ const policy = {
312
+ Statement: [
313
+ {
314
+ Resource: "https://media.yourdomain.com/*", // All videos on this domain
315
+ Condition: {
316
+ DateLessThan: {
317
+ "AWS:EpochTime": Math.floor(Date.now() / 1000) + 3600, // Expires in 1 hour
318
+ },
319
+ },
320
+ },
321
+ ],
322
+ }
323
+
324
+ // Generate CloudFront signed cookies
325
+ const cookies = getSignedCookies({
326
+ keyPairId: process.env.CLOUDFRONT_KEY_PAIR_ID!, // Your CloudFront key pair ID
327
+ privateKey: fs.readFileSync("./cloudfront-private-key.pem", "utf8"), // Your private key
328
+ policy: JSON.stringify(policy),
329
+ })
330
+
331
+ // Set the three required cookies
332
+ res.cookie("CloudFront-Policy", cookies["CloudFront-Policy"], {
333
+ domain: ".yourdomain.com", // Use your domain
334
+ path: "/",
335
+ secure: true, // HTTPS only
336
+ httpOnly: true, // Prevent JavaScript access
337
+ sameSite: "none",
338
+ })
339
+
340
+ res.cookie("CloudFront-Signature", cookies["CloudFront-Signature"], {
341
+ domain: ".yourdomain.com",
342
+ path: "/",
343
+ secure: true,
344
+ httpOnly: true,
345
+ sameSite: "none",
346
+ })
347
+
348
+ res.cookie("CloudFront-Key-Pair-Id", cookies["CloudFront-Key-Pair-Id"], {
349
+ domain: ".yourdomain.com",
350
+ path: "/",
351
+ secure: true,
352
+ httpOnly: true,
353
+ sameSite: "none",
354
+ })
355
+
356
+ res.json({ success: true })
357
+ })
358
+
359
+ // STEP 2: Optional endpoint for on-demand signing (called by signUrl function)
360
+ app.post("/api/auth/sign-url", (req, res) => {
361
+ const { url } = req.body
362
+
363
+ // Verify user is authorized
364
+ if (!req.user) {
365
+ return res.status(401).json({ error: "Not authenticated" })
366
+ }
367
+
368
+ // You can add additional authorization logic here
369
+ // For example, check if user has access to this specific video
370
+
371
+ // Refresh cookies (same code as above)
246
372
  const policy = {
247
373
  Statement: [
248
374
  {
249
375
  Resource: "https://media.yourdomain.com/*",
250
376
  Condition: {
251
377
  DateLessThan: {
252
- "AWS:EpochTime": Math.floor(Date.now() / 1000) + 3600, // 1 hour
378
+ "AWS:EpochTime": Math.floor(Date.now() / 1000) + 3600,
253
379
  },
254
380
  },
255
381
  },
@@ -257,43 +383,142 @@ app.get("/api/video-auth", async (req, res) => {
257
383
  }
258
384
 
259
385
  const cookies = getSignedCookies({
260
- keyPairId: process.env.CLOUDFRONT_KEY_PAIR_ID,
261
- privateKey: process.env.CLOUDFRONT_PRIVATE_KEY,
386
+ keyPairId: process.env.CLOUDFRONT_KEY_PAIR_ID!,
387
+ privateKey: fs.readFileSync("./cloudfront-private-key.pem", "utf8"),
262
388
  policy: JSON.stringify(policy),
263
389
  })
264
390
 
265
- // Set cookies
266
391
  res.cookie("CloudFront-Policy", cookies["CloudFront-Policy"], {
267
392
  domain: ".yourdomain.com",
393
+ path: "/",
268
394
  secure: true,
269
395
  httpOnly: true,
396
+ sameSite: "none",
270
397
  })
398
+
271
399
  res.cookie("CloudFront-Signature", cookies["CloudFront-Signature"], {
272
400
  domain: ".yourdomain.com",
401
+ path: "/",
273
402
  secure: true,
274
403
  httpOnly: true,
404
+ sameSite: "none",
275
405
  })
406
+
276
407
  res.cookie("CloudFront-Key-Pair-Id", cookies["CloudFront-Key-Pair-Id"], {
277
408
  domain: ".yourdomain.com",
409
+ path: "/",
278
410
  secure: true,
279
411
  httpOnly: true,
412
+ sameSite: "none",
280
413
  })
281
414
 
282
415
  res.json({ success: true })
283
416
  })
284
417
  ```
285
418
 
286
- ### Public S3/CloudFront (No Authentication)
419
+ **AWS CloudFront Setup:**
420
+
421
+ 1. Create a CloudFront key pair in AWS Console → CloudFront → Key pairs
422
+ 2. Download the private key file
423
+ 3. Set up environment variables:
424
+ ```bash
425
+ CLOUDFRONT_KEY_PAIR_ID=APKA...
426
+ ```
427
+ 4. Configure your CloudFront distribution to require signed cookies
428
+
429
+ ---
287
430
 
288
- For public videos:
431
+ ### Scenario 3: Private S3 Videos with Presigned URLs
432
+
433
+ **When to use:** Videos are in private S3 buckets without CloudFront.
434
+
435
+ **How it works:**
436
+
437
+ 1. Your backend generates temporary presigned URLs for S3 objects
438
+ 2. Player uses these URLs to access videos
439
+ 3. URLs expire after a set time (e.g., 1 hour)
440
+
441
+ **Frontend Setup:**
289
442
 
290
443
  ```typescript
444
+ import { WontumPlayer } from "@obipascal/player"
445
+
291
446
  const player = new WontumPlayer({
292
- src: "https://d1234567890.cloudfront.net/video/playlist.m3u8",
447
+ src: "s3://my-bucket/videos/lesson-1/playlist.m3u8", // S3 URI
293
448
  container: "#player",
449
+ s3Config: {
450
+ getPresignedUrl: async (s3Key) => {
451
+ // Call your backend to generate presigned URL
452
+ const response = await fetch("/api/s3/presigned-url", {
453
+ method: "POST",
454
+ headers: { "Content-Type": "application/json" },
455
+ body: JSON.stringify({ key: s3Key }),
456
+ })
457
+
458
+ if (!response.ok) {
459
+ throw new Error("Failed to get presigned URL")
460
+ }
461
+
462
+ const data = await response.json()
463
+ return data.url // Return the presigned URL
464
+ },
465
+ },
294
466
  })
295
467
  ```
296
468
 
469
+ **Backend Setup (Node.js):**
470
+
471
+ ```typescript
472
+ import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3"
473
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
474
+
475
+ const s3Client = new S3Client({
476
+ region: "us-east-1",
477
+ credentials: {
478
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
479
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
480
+ },
481
+ })
482
+
483
+ app.post("/api/s3/presigned-url", async (req, res) => {
484
+ const { key } = req.body
485
+
486
+ // Verify user is authorized to access this video
487
+ if (!req.user) {
488
+ return res.status(401).json({ error: "Not authenticated" })
489
+ }
490
+
491
+ try {
492
+ // Generate presigned URL
493
+ const command = new GetObjectCommand({
494
+ Bucket: "my-bucket",
495
+ Key: key, // e.g., "videos/lesson-1/playlist.m3u8"
496
+ })
497
+
498
+ const url = await getSignedUrl(s3Client, command, {
499
+ expiresIn: 3600, // URL valid for 1 hour
500
+ })
501
+
502
+ res.json({ url })
503
+ } catch (error) {
504
+ console.error("Error generating presigned URL:", error)
505
+ res.status(500).json({ error: "Failed to generate presigned URL" })
506
+ }
507
+ })
508
+ ```
509
+
510
+ ---
511
+
512
+ ### Which Method Should I Use?
513
+
514
+ | Method | Best For | Complexity | Performance |
515
+ | ---------------------- | ---------------------------------------------- | ----------- | ------------ |
516
+ | **Public Videos** | Free content, marketing videos | ⭐ Easy | ⚡ Fast |
517
+ | **CloudFront Cookies** | ⭐ **Recommended** for paid courses, premium | ⭐⭐ Medium | ⚡⚡ Fastest |
518
+ | **S3 Presigned URLs** | Direct S3 access, simple private video hosting | ⭐⭐ Medium | ⚡ Good |
519
+
520
+ 💡 **Tip:** Use CloudFront with signed cookies for production. It's more secure and performant for HLS videos (which have many file segments).
521
+
297
522
  ## 📝 Subtitle Support
298
523
 
299
524
  ### Adding Subtitles
@@ -568,15 +793,7 @@ function CustomPlayer() {
568
793
  Wontum Player comes with 7 beautiful pre-made themes:
569
794
 
570
795
  ```typescript
571
- import {
572
- netflixTheme,
573
- youtubeTheme,
574
- modernTheme,
575
- greenTheme,
576
- cyberpunkTheme,
577
- pastelTheme,
578
- educationTheme,
579
- } from "@wontum/player"
796
+ import { netflixTheme, youtubeTheme, modernTheme, greenTheme, cyberpunkTheme, pastelTheme, educationTheme } from "@obipascal/player"
580
797
 
581
798
  const player = new WontumPlayer({
582
799
  src: "https://media.example.com/video/playlist.m3u8",
@@ -586,6 +803,7 @@ const player = new WontumPlayer({
586
803
  ```
587
804
 
588
805
  **Available Themes:**
806
+
589
807
  - `netflixTheme()` - Netflix-inspired red and black
590
808
  - `youtubeTheme()` - YouTube-inspired red and white
591
809
  - `modernTheme()` - Modern blue gradient
@@ -620,7 +838,7 @@ const player = new WontumPlayer({
620
838
  Quick brand color presets:
621
839
 
622
840
  ```typescript
623
- import { BrandPresets } from "@wontum/player"
841
+ import { BrandPresets } from "@obipascal/player"
624
842
 
625
843
  const player = new WontumPlayer({
626
844
  src: "https://media.example.com/video/playlist.m3u8",
@@ -634,6 +852,7 @@ const player = new WontumPlayer({
634
852
  ```
635
853
 
636
854
  **Available Brand Colors:**
855
+
637
856
  - `blue`, `lightBlue`, `darkBlue`
638
857
  - `red`, `lightRed`, `darkRed`
639
858
  - `green`, `lightGreen`, `darkGreen`
@@ -788,6 +1007,7 @@ For detailed API documentation including all methods, events, types, and configu
788
1007
  ### Quick Reference
789
1008
 
790
1009
  **Player Methods:**
1010
+
791
1011
  - **Playback:** `play()`, `pause()`, `seek(time)`, `skipForward(seconds)`, `skipBackward(seconds)`
792
1012
  - **Volume:** `setVolume(level)`, `mute()`, `unmute()`
793
1013
  - **Subtitles:** `enableSubtitles(index)`, `disableSubtitles()`, `toggleSubtitles()`, `getSubtitleTracks()`, `areSubtitlesEnabled()`
@@ -798,6 +1018,7 @@ For detailed API documentation including all methods, events, types, and configu
798
1018
  - **Lifecycle:** `destroy()`
799
1019
 
800
1020
  **Events (25 total):**
1021
+
801
1022
  - **Playback:** `play`, `pause`, `ended`, `timeupdate`, `durationchange`
802
1023
  - **Loading:** `loadstart`, `loadedmetadata`, `loadeddata`, `canplay`, `canplaythrough`
803
1024
  - **Buffering:** `waiting`, `playing`, `stalled`, `suspend`, `abort`
@@ -812,13 +1033,13 @@ For detailed API documentation including all methods, events, types, and configu
812
1033
 
813
1034
  ## 🌐 Browser Support
814
1035
 
815
- | Browser | Minimum Version |
816
- |---------|----------------|
817
- | Chrome | Latest 2 versions |
818
- | Edge | Latest 2 versions |
819
- | Firefox | Latest 2 versions |
820
- | Safari | Latest 2 versions |
821
- | iOS Safari | iOS 12+ |
1036
+ | Browser | Minimum Version |
1037
+ | -------------- | ----------------- |
1038
+ | Chrome | Latest 2 versions |
1039
+ | Edge | Latest 2 versions |
1040
+ | Firefox | Latest 2 versions |
1041
+ | Safari | Latest 2 versions |
1042
+ | iOS Safari | iOS 12+ |
822
1043
  | Android Chrome | Latest 2 versions |
823
1044
 
824
1045
  **Note:** HLS playback requires HLS.js support. Native HLS playback is supported on Safari.
@@ -14,7 +14,7 @@ export declare function cloudFrontWithRetryExample(): WontumPlayer;
14
14
  * Note: This is a code example as a string. For actual React usage,
15
15
  * copy this to a .tsx file in your project.
16
16
  */
17
- export declare const ReactCloudFrontPlayerExample = "\nimport React from \"react\"\nimport { WontumPlayerReact } from \"@wontum/player\"\n\nexport function CloudFrontPlayer({ videoUrl, userId }: { videoUrl: string; userId: string }) {\n\t// Sign URL function\n\tasync function signUrl(url: string): Promise<string> {\n\t\tconst response = await fetch(\"/api/cloudfront/sign\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({ url, userId }),\n\t\t\tcredentials: \"include\",\n\t\t})\n\n\t\tconst data = await response.json()\n\t\treturn data.url\n\t}\n\n\treturn (\n\t\t<WontumPlayerReact\n\t\t\tsrc={videoUrl}\n\t\t\twidth=\"100%\"\n\t\t\theight=\"500px\"\n\t\t\ts3Config={{\n\t\t\t\tsignUrl,\n\t\t\t\tcloudFrontDomains: [\"media.domain.com\", \"cdn.domain.com\"], // Multiple domains\n\t\t\t}}\n\t\t\tanalytics={{\n\t\t\t\tenabled: true,\n\t\t\t\tuserId,\n\t\t\t\tvideoId: videoUrl,\n\t\t\t}}\n\t\t\tonError={(error) => {\n\t\t\t\tconsole.error(\"Player error:\", error)\n\t\t\t\t// Handle signing errors\n\t\t\t\tif (error?.message?.includes(\"sign\")) {\n\t\t\t\t\talert(\"Failed to authenticate video. Please refresh and try again.\")\n\t\t\t\t}\n\t\t\t}}\n\t\t/>\n\t)\n}\n";
17
+ export declare const ReactCloudFrontPlayerExample = "\nimport React from \"react\"\nimport { WontumPlayerReact } from \"@obipascal/player\"\n\nexport function CloudFrontPlayer({ videoUrl, userId }: { videoUrl: string; userId: string }) {\n\t// Sign URL function\n\tasync function signUrl(url: string): Promise<string> {\n\t\tconst response = await fetch(\"/api/cloudfront/sign\", {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({ url, userId }),\n\t\t\tcredentials: \"include\",\n\t\t})\n\n\t\tconst data = await response.json()\n\t\treturn data.url\n\t}\n\n\treturn (\n\t\t<WontumPlayerReact\n\t\t\tsrc={videoUrl}\n\t\t\twidth=\"100%\"\n\t\t\theight=\"500px\"\n\t\t\ts3Config={{\n\t\t\t\tsignUrl,\n\t\t\t\tcloudFrontDomains: [\"media.domain.com\", \"cdn.domain.com\"], // Multiple domains\n\t\t\t}}\n\t\t\tanalytics={{\n\t\t\t\tenabled: true,\n\t\t\t\tuserId,\n\t\t\t\tvideoId: videoUrl,\n\t\t\t}}\n\t\t\tonError={(error) => {\n\t\t\t\tconsole.error(\"Player error:\", error)\n\t\t\t\t// Handle signing errors\n\t\t\t\tif (error?.message?.includes(\"sign\")) {\n\t\t\t\t\talert(\"Failed to authenticate video. Please refresh and try again.\")\n\t\t\t\t}\n\t\t\t}}\n\t\t/>\n\t)\n}\n";
18
18
  /**
19
19
  * Example 4: Backend Implementation (Node.js/Express)
20
20
  */
@@ -31,7 +31,7 @@ export declare function educationTheme(): WontumPlayer;
31
31
  /**
32
32
  * React Example with Custom Theme
33
33
  */
34
- export declare const ReactCustomThemeExample = "\nimport React from 'react';\nimport { WontumPlayerReact } from '@wontum/player';\n\nfunction CustomStyledPlayer() {\n return (\n <WontumPlayerReact\n src=\"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8\"\n theme={{\n primaryColor: '#ff6b6b', // Coral red\n accentColor: '#ee5a6f',\n fontFamily: 'Helvetica, Arial, sans-serif',\n controlsBackground: 'linear-gradient(to top, rgba(0,0,0,0.85), transparent)',\n buttonHoverBg: 'rgba(255, 107, 107, 0.25)',\n progressHeight: '5px',\n borderRadius: '8px'\n }}\n />\n );\n}\n";
34
+ export declare const ReactCustomThemeExample = "\nimport React from 'react';\nimport { WontumPlayerReact } from '@obipascal/player';\n\nfunction CustomStyledPlayer() {\n return (\n <WontumPlayerReact\n src=\"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8\"\n theme={{\n primaryColor: '#ff6b6b', // Coral red\n accentColor: '#ee5a6f',\n fontFamily: 'Helvetica, Arial, sans-serif',\n controlsBackground: 'linear-gradient(to top, rgba(0,0,0,0.85), transparent)',\n buttonHoverBg: 'rgba(255, 107, 107, 0.25)',\n progressHeight: '5px',\n borderRadius: '8px'\n }}\n />\n );\n}\n";
35
35
  /**
36
36
  * All Available Theme Options
37
37
  */
@@ -40,7 +40,7 @@ export declare function minimalEventExample(): void;
40
40
  /**
41
41
  * React example with all events
42
42
  */
43
- export declare const ReactAllEventsExample = "\nimport React from 'react';\nimport { WontumPlayerReact } from '@wontum/player';\n\nfunction VideoPlayerWithEvents() {\n return (\n <WontumPlayerReact\n src=\"https://media.domain.com/video.m3u8\"\n \n {/* Playback Events */}\n onPlay={(e) => console.log('Play', e)}\n onPause={(e) => console.log('Pause', e)}\n onPlaying={(e) => console.log('Playing', e)}\n onEnded={(e) => console.log('Ended', e)}\n onTimeupdate={(e) => console.log('Time:', e.data.currentTime)}\n \n {/* Seeking */}\n onSeeking={(e) => console.log('Seeking', e)}\n onSeeked={(e) => console.log('Seeked', e)}\n \n {/* Loading Events */}\n onLoadstart={(e) => console.log('Load Start', e)}\n onLoadeddata={(e) => console.log('Loaded Data', e)}\n onLoadedmetadata={(e) => console.log('Metadata', e)}\n onCanplay={(e) => console.log('Can Play', e)}\n onCanplaythrough={(e) => console.log('Can Play Through', e)}\n onProgress={(e) => console.log('Progress', e)}\n onWaiting={(e) => console.log('Buffering', e)}\n onDurationchange={(e) => console.log('Duration', e)}\n \n {/* Media State */}\n onVolumechange={(e) => console.log('Volume', e)}\n onRatechange={(e) => console.log('Rate', e)}\n onResize={(e) => console.log('Resize', e)}\n \n {/* Network/Error */}\n onAbort={(e) => console.log('Abort', e)}\n onEmptied={(e) => console.log('Emptied', e)}\n onStalled={(e) => console.log('Stalled', e)}\n onSuspend={(e) => console.log('Suspend', e)}\n onError={(e) => console.error('Error', e)}\n \n {/* Custom Events */}\n onQualitychange={(e) => console.log('Quality', e)}\n onFullscreenchange={(e) => console.log('Fullscreen', e)}\n />\n );\n}\n";
43
+ export declare const ReactAllEventsExample = "\nimport React from 'react';\nimport { WontumPlayerReact } from '@obipascal/player';\n\nfunction VideoPlayerWithEvents() {\n return (\n <WontumPlayerReact\n src=\"https://media.domain.com/video.m3u8\"\n \n {/* Playback Events */}\n onPlay={(e) => console.log('Play', e)}\n onPause={(e) => console.log('Pause', e)}\n onPlaying={(e) => console.log('Playing', e)}\n onEnded={(e) => console.log('Ended', e)}\n onTimeupdate={(e) => console.log('Time:', e.data.currentTime)}\n \n {/* Seeking */}\n onSeeking={(e) => console.log('Seeking', e)}\n onSeeked={(e) => console.log('Seeked', e)}\n \n {/* Loading Events */}\n onLoadstart={(e) => console.log('Load Start', e)}\n onLoadeddata={(e) => console.log('Loaded Data', e)}\n onLoadedmetadata={(e) => console.log('Metadata', e)}\n onCanplay={(e) => console.log('Can Play', e)}\n onCanplaythrough={(e) => console.log('Can Play Through', e)}\n onProgress={(e) => console.log('Progress', e)}\n onWaiting={(e) => console.log('Buffering', e)}\n onDurationchange={(e) => console.log('Duration', e)}\n \n {/* Media State */}\n onVolumechange={(e) => console.log('Volume', e)}\n onRatechange={(e) => console.log('Rate', e)}\n onResize={(e) => console.log('Resize', e)}\n \n {/* Network/Error */}\n onAbort={(e) => console.log('Abort', e)}\n onEmptied={(e) => console.log('Emptied', e)}\n onStalled={(e) => console.log('Stalled', e)}\n onSuspend={(e) => console.log('Suspend', e)}\n onError={(e) => console.error('Error', e)}\n \n {/* Custom Events */}\n onQualitychange={(e) => console.log('Quality', e)}\n onFullscreenchange={(e) => console.log('Fullscreen', e)}\n />\n );\n}\n";
44
44
  /**
45
45
  * Compare with Mux Player events
46
46
  */
@@ -35,4 +35,4 @@ export declare const htmlExample = "\n<!DOCTYPE html>\n<html>\n<head>\n <title>
35
35
  /**
36
36
  * React example with public stream
37
37
  */
38
- export declare const reactPublicStreamExample = "\nimport React from 'react';\nimport { WontumPlayerReact } from '@wontum/player';\n\nfunction App() {\n return (\n <div style={{ width: '100%', height: '600px', background: '#000' }}>\n <WontumPlayerReact\n src=\"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8\"\n autoplay\n onLoadedmetadata={(e) => console.log('Duration:', e.data.duration)}\n onPlay={() => console.log('Playing!')}\n onError={(e) => console.error('Error:', e.data)}\n />\n </div>\n );\n}\n\nexport default App;\n";
38
+ export declare const reactPublicStreamExample = "\nimport React from 'react';\nimport { WontumPlayerReact } from '@obipascal/player';\n\nfunction App() {\n return (\n <div style={{ width: '100%', height: '600px', background: '#000' }}>\n <WontumPlayerReact\n src=\"https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8\"\n autoplay\n onLoadedmetadata={(e) => console.log('Duration:', e.data.duration)}\n onPlay={() => console.log('Playing!')}\n onError={(e) => console.error('Error:', e.data)}\n />\n </div>\n );\n}\n\nexport default App;\n";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obipascal/player",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A modern HLS video player SDK for educational platforms with S3 integration",
5
5
  "main": "dist/wontum-player.cjs.js",
6
6
  "module": "dist/wontum-player.esm.js",