@obipascal/player 1.0.1 โ†’ 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.
Files changed (2) hide show
  1. package/README.md +261 -40
  2. package/package.json +1 -1
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
@@ -98,7 +102,7 @@ yarn add @obipascal/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
@@ -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:
221
+
222
+ ### Scenario 1: Public Videos (Easiest - No Authentication Required)
223
+
224
+ **When to use:** Your videos are publicly accessible and don't require user authentication.
217
225
 
218
- For secure video delivery, use CloudFront with signed cookies:
226
+ **Setup:** Just provide the video URL!
219
227
 
220
228
  ```typescript
221
229
  import { WontumPlayer } from "@obipascal/player"
222
230
 
223
- // Your backend sets signed cookies for CloudFront
224
- // Cookie names: CloudFront-Policy, CloudFront-Signature, CloudFront-Key-Pair-Id
225
-
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:**
253
+
254
+ ```typescript
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):**
239
295
 
240
296
  ```typescript
241
- // Node.js backend example
242
- import { CloudFrontClient } from "@aws-sdk/client-cloudfront"
297
+ import express from "express"
243
298
  import { getSignedCookies } from "@aws-sdk/cloudfront-signer"
299
+ import fs from "fs"
300
+
301
+ const app = express()
302
+
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
+ }
244
309
 
245
- app.get("/api/video-auth", async (req, res) => {
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
+ ---
430
+
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)
287
440
 
288
- For public videos:
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 "@obipascal/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
@@ -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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obipascal/player",
3
- "version": "1.0.1",
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",