@obipascal/player 1.0.6 → 1.0.8
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 +156 -4
- package/dist/src/file-info.d.ts +78 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/player.d.ts +3 -0
- package/dist/src/types.d.ts +3 -1
- package/dist/src/ui-controller.d.ts +4 -0
- package/dist/wontum-player.cjs.js +46 -26
- package/dist/wontum-player.esm.js +424 -194
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -240,6 +240,7 @@ function VideoPlayer({ videoUrl }: VideoPlayerProps) {
|
|
|
240
240
|
|
|
241
241
|
const s3config: S3Config = {
|
|
242
242
|
cloudFrontDomains: [url.hostname],
|
|
243
|
+
withCredentials: true, // Enable cookies for CloudFront signed cookies
|
|
243
244
|
signUrl: async (resourceUrl: string) => {
|
|
244
245
|
try {
|
|
245
246
|
const { data } = await refetch({
|
|
@@ -336,6 +337,7 @@ async function initializePlayer() {
|
|
|
336
337
|
container: "#player",
|
|
337
338
|
s3Config: {
|
|
338
339
|
cloudFrontDomains: ["media.yourdomain.com"], // Your CloudFront domain
|
|
340
|
+
withCredentials: true, // Enable cookies for all HLS requests (required for CloudFront signed cookies)
|
|
339
341
|
signUrl: async (url) => {
|
|
340
342
|
// This function is called when player needs to access a video
|
|
341
343
|
// Call your backend to refresh/set cookies if needed
|
|
@@ -734,9 +736,19 @@ interface WontumPlayerConfig {
|
|
|
734
736
|
poster?: string // Poster image URL
|
|
735
737
|
preload?: "none" | "metadata" | "auto" // Preload strategy
|
|
736
738
|
theme?: PlayerTheme // Custom theme
|
|
737
|
-
s3Config?: S3Config // S3 configuration
|
|
739
|
+
s3Config?: S3Config // S3/CloudFront configuration
|
|
738
740
|
analytics?: AnalyticsConfig // Analytics configuration
|
|
739
741
|
hlsConfig?: Partial<any> // HLS.js config override
|
|
742
|
+
subtitles?: SubtitleTrack[] // Subtitle tracks
|
|
743
|
+
stickyControls?: boolean // Keep controls always visible
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
interface S3Config {
|
|
747
|
+
signUrl?: (url: string) => Promise<string> // Sign URL and set cookies
|
|
748
|
+
cloudFrontDomains?: string[] // CloudFront domains (e.g., ['media.example.com'])
|
|
749
|
+
withCredentials?: boolean // Enable cookies for HLS requests (default: false, required for CloudFront signed cookies)
|
|
750
|
+
region?: string // S3 region
|
|
751
|
+
endpoint?: string // Custom S3 endpoint
|
|
740
752
|
}
|
|
741
753
|
```
|
|
742
754
|
|
|
@@ -758,11 +770,17 @@ player.setPlaybackRate(rate: number): void // 0.5, 1, 1.5, 2, etc.
|
|
|
758
770
|
|
|
759
771
|
// Quality control
|
|
760
772
|
player.setQuality(qualityIndex: number): void
|
|
773
|
+
player.getQualities(): QualityLevel[]
|
|
761
774
|
|
|
762
775
|
// Fullscreen
|
|
763
776
|
player.enterFullscreen(): void
|
|
764
777
|
player.exitFullscreen(): void
|
|
765
778
|
|
|
779
|
+
// Picture-in-Picture
|
|
780
|
+
player.enterPictureInPicture(): Promise<void>
|
|
781
|
+
player.exitPictureInPicture(): Promise<void>
|
|
782
|
+
player.togglePictureInPicture(): Promise<void>
|
|
783
|
+
|
|
766
784
|
// State
|
|
767
785
|
player.getState(): PlayerState
|
|
768
786
|
|
|
@@ -792,6 +810,8 @@ type PlayerEventType =
|
|
|
792
810
|
| "error"
|
|
793
811
|
| "qualitychange"
|
|
794
812
|
| "fullscreenchange"
|
|
813
|
+
| "pictureinpictureenter"
|
|
814
|
+
| "pictureinpictureexit"
|
|
795
815
|
```
|
|
796
816
|
|
|
797
817
|
### React Components
|
|
@@ -994,6 +1014,15 @@ player.on("qualitychange", (event) => {
|
|
|
994
1014
|
console.log("Quality changed to:", event.data.quality)
|
|
995
1015
|
})
|
|
996
1016
|
|
|
1017
|
+
// Picture-in-Picture events
|
|
1018
|
+
player.on("pictureinpictureenter", () => {
|
|
1019
|
+
console.log("Entered Picture-in-Picture mode")
|
|
1020
|
+
})
|
|
1021
|
+
|
|
1022
|
+
player.on("pictureinpictureexit", () => {
|
|
1023
|
+
console.log("Exited Picture-in-Picture mode")
|
|
1024
|
+
})
|
|
1025
|
+
|
|
997
1026
|
// Buffer events
|
|
998
1027
|
player.on("waiting", () => console.log("Buffering..."))
|
|
999
1028
|
player.on("canplay", () => console.log("Ready to play"))
|
|
@@ -1065,10 +1094,132 @@ player.setQuality(2) // Set to quality index 2
|
|
|
1065
1094
|
player.enterFullscreen()
|
|
1066
1095
|
player.exitFullscreen()
|
|
1067
1096
|
|
|
1097
|
+
// Picture-in-Picture
|
|
1098
|
+
await player.enterPictureInPicture()
|
|
1099
|
+
await player.exitPictureInPicture()
|
|
1100
|
+
await player.togglePictureInPicture()
|
|
1101
|
+
|
|
1068
1102
|
// Cleanup
|
|
1069
1103
|
player.destroy() // Remove player and clean up resources
|
|
1070
1104
|
```
|
|
1071
1105
|
|
|
1106
|
+
### Picture-in-Picture Mode
|
|
1107
|
+
|
|
1108
|
+
Enable floating video that stays on top while users work in other apps:
|
|
1109
|
+
|
|
1110
|
+
```typescript
|
|
1111
|
+
const player = new WontumPlayer({
|
|
1112
|
+
src: "https://example.com/video.m3u8",
|
|
1113
|
+
container: "#player",
|
|
1114
|
+
})
|
|
1115
|
+
|
|
1116
|
+
// Enter PiP mode
|
|
1117
|
+
await player.enterPictureInPicture()
|
|
1118
|
+
|
|
1119
|
+
// Listen for PiP events
|
|
1120
|
+
player.on("pictureinpictureenter", () => {
|
|
1121
|
+
console.log("Video is now floating!")
|
|
1122
|
+
})
|
|
1123
|
+
|
|
1124
|
+
player.on("pictureinpictureexit", () => {
|
|
1125
|
+
console.log("Back to normal mode")
|
|
1126
|
+
})
|
|
1127
|
+
|
|
1128
|
+
// Custom button to toggle PiP
|
|
1129
|
+
const pipButton = document.getElementById("pip-btn")
|
|
1130
|
+
pipButton.addEventListener("click", async () => {
|
|
1131
|
+
await player.togglePictureInPicture()
|
|
1132
|
+
})
|
|
1133
|
+
```
|
|
1134
|
+
|
|
1135
|
+
**Note:** Picture-in-Picture is supported in most modern browsers. The player includes a built-in PiP button in the controls.
|
|
1136
|
+
|
|
1137
|
+
### File Information Utility
|
|
1138
|
+
|
|
1139
|
+
The SDK includes a `WontumFileInfo` utility class to extract metadata from video files before uploading or processing them.
|
|
1140
|
+
|
|
1141
|
+
```typescript
|
|
1142
|
+
import { WontumFileInfo } from "@obipascal/player"
|
|
1143
|
+
|
|
1144
|
+
// Example: File input handling
|
|
1145
|
+
const fileInput = document.querySelector<HTMLInputElement>("#video-upload")
|
|
1146
|
+
|
|
1147
|
+
fileInput.addEventListener("change", async (event) => {
|
|
1148
|
+
const file = event.target.files?.[0]
|
|
1149
|
+
if (!file) return
|
|
1150
|
+
|
|
1151
|
+
try {
|
|
1152
|
+
// Create instance (validates it's a video file)
|
|
1153
|
+
const videoInfo = new WontumFileInfo(file)
|
|
1154
|
+
|
|
1155
|
+
// Extract metadata
|
|
1156
|
+
await videoInfo.extract()
|
|
1157
|
+
|
|
1158
|
+
// Access properties
|
|
1159
|
+
console.log("Video Information:")
|
|
1160
|
+
console.log("- Width:", videoInfo.width) // e.g., 1920
|
|
1161
|
+
console.log("- Height:", videoInfo.height) // e.g., 1080
|
|
1162
|
+
console.log("- Aspect Ratio:", videoInfo.aspectRatio) // e.g., "16:9"
|
|
1163
|
+
console.log("- Quality:", videoInfo.quality) // e.g., "Full HD (1080p)"
|
|
1164
|
+
console.log("- Duration (raw):", videoInfo.durationInSeconds, "seconds") // e.g., 125.5
|
|
1165
|
+
console.log("- Formatted Duration:", videoInfo.durationFormatted) // e.g., "02:05"
|
|
1166
|
+
console.log("- File Size (raw):", videoInfo.sizeInBytes, "bytes") // e.g., 52428800
|
|
1167
|
+
console.log("- Formatted Size:", videoInfo.sizeFormatted) // e.g., "50 MB"
|
|
1168
|
+
console.log("- MIME Type:", videoInfo.mimeType) // e.g., "video/mp4"
|
|
1169
|
+
console.log("- File Name:", videoInfo.fileName) // e.g., "my-video.mp4"
|
|
1170
|
+
console.log("- Extension:", videoInfo.fileExtension) // e.g., ".mp4"
|
|
1171
|
+
console.log("- Bitrate:", videoInfo.bitrate, "kbps") // e.g., 3500
|
|
1172
|
+
|
|
1173
|
+
// Get all info as object
|
|
1174
|
+
const allInfo = videoInfo.getInfo()
|
|
1175
|
+
console.log(allInfo)
|
|
1176
|
+
|
|
1177
|
+
// Clean up when done
|
|
1178
|
+
videoInfo.destroy()
|
|
1179
|
+
} catch (error) {
|
|
1180
|
+
console.error("Error extracting video info:", error.message)
|
|
1181
|
+
// Throws error if file is not a video
|
|
1182
|
+
}
|
|
1183
|
+
})
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
#### WontumFileInfo API
|
|
1187
|
+
|
|
1188
|
+
**Constructor:**
|
|
1189
|
+
|
|
1190
|
+
```typescript
|
|
1191
|
+
new WontumFileInfo(file: File)
|
|
1192
|
+
```
|
|
1193
|
+
|
|
1194
|
+
Throws an error if the file is not a valid video file.
|
|
1195
|
+
|
|
1196
|
+
**Methods:**
|
|
1197
|
+
|
|
1198
|
+
- `extract(): Promise<VideoFileInfo>` - Extracts metadata from the video file
|
|
1199
|
+
- `getInfo(): VideoFileInfo | null` - Returns the extracted information object
|
|
1200
|
+
- `destroy(): void` - Cleans up resources
|
|
1201
|
+
|
|
1202
|
+
**Properties (available after calling `extract()`):**
|
|
1203
|
+
|
|
1204
|
+
- `width: number` - Video width in pixels
|
|
1205
|
+
- `height: number` - Video height in pixels
|
|
1206
|
+
- `aspectRatio: string` - Aspect ratio (e.g., "16:9", "4:3", "21:9")
|
|
1207
|
+
- `quality: string` - Quality description (e.g., "4K (2160p)", "Full HD (1080p)")
|
|
1208
|
+
- `size: number` - File size in bytes (raw value for computation)
|
|
1209
|
+
- `sizeInBytes: number` - Alias for size (raw value for computation)
|
|
1210
|
+
- `sizeFormatted: string` - Human-readable size (e.g., "50 MB")
|
|
1211
|
+
- `duration: number` - Duration in seconds (raw value for computation)
|
|
1212
|
+
- `durationInSeconds: number` - Alias for duration (raw value for computation)
|
|
1213
|
+
- `durationFormatted: string` - Formatted duration (e.g., "01:23:45")
|
|
1214
|
+
- `mimeType: string` - MIME type (e.g., "video/mp4")
|
|
1215
|
+
- `fileName: string` - Original file name
|
|
1216
|
+
- `fileExtension: string` - File extension (e.g., ".mp4")
|
|
1217
|
+
- `bitrate: number | undefined` - Estimated bitrate in kbps
|
|
1218
|
+
|
|
1219
|
+
**Supported Video Formats:**
|
|
1220
|
+
|
|
1221
|
+
`.mp4`, `.webm`, `.ogg`, `.mov`, `.avi`, `.mkv`, `.flv`, `.wmv`, `.m4v`, `.3gp`, `.ts`, `.m3u8`
|
|
1222
|
+
|
|
1072
1223
|
## 📋 Complete API Reference
|
|
1073
1224
|
|
|
1074
1225
|
For detailed API documentation including all methods, events, types, and configuration options, see **[API-REFERENCE.md](./API-REFERENCE.md)**.
|
|
@@ -1083,6 +1234,7 @@ For detailed API documentation including all methods, events, types, and configu
|
|
|
1083
1234
|
- **Quality:** `setQuality(index)`, `getQualities()`
|
|
1084
1235
|
- **Playback Rate:** `setPlaybackRate(rate)`
|
|
1085
1236
|
- **Fullscreen:** `enterFullscreen()`, `exitFullscreen()`
|
|
1237
|
+
- **Picture-in-Picture:** `enterPictureInPicture()`, `exitPictureInPicture()`, `togglePictureInPicture()`
|
|
1086
1238
|
- **State:** `getState()`, `getCurrentTime()`, `getDuration()`
|
|
1087
1239
|
- **Lifecycle:** `destroy()`
|
|
1088
1240
|
|
|
@@ -1129,9 +1281,9 @@ Contributions are welcome! Please follow these steps:
|
|
|
1129
1281
|
|
|
1130
1282
|
## 💬 Support
|
|
1131
1283
|
|
|
1132
|
-
- **Issues:** [GitHub Issues](https://github.com/
|
|
1133
|
-
- **Discussions:** [GitHub Discussions](https://github.com/
|
|
1134
|
-
- **Email:**
|
|
1284
|
+
- **Issues:** [GitHub Issues](https://github.com/obipascal/wontum-player/issues)
|
|
1285
|
+
- **Discussions:** [GitHub Discussions](https://github.com/obipascal/wontum-player/discussions)
|
|
1286
|
+
- **Email:** pascalobi83@gmail.com
|
|
1135
1287
|
|
|
1136
1288
|
## 🙏 Acknowledgments
|
|
1137
1289
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Video file information extractor
|
|
3
|
+
* Extracts metadata from video files (width, height, duration, size, etc.)
|
|
4
|
+
*/
|
|
5
|
+
export interface VideoFileInfo {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
aspectRatio: string;
|
|
9
|
+
size: number;
|
|
10
|
+
sizeInBytes: number;
|
|
11
|
+
sizeFormatted: string;
|
|
12
|
+
duration: number;
|
|
13
|
+
durationInSeconds: number;
|
|
14
|
+
durationFormatted: string;
|
|
15
|
+
mimeType: string;
|
|
16
|
+
fileName: string;
|
|
17
|
+
fileExtension: string;
|
|
18
|
+
bitrate?: number;
|
|
19
|
+
frameRate?: number;
|
|
20
|
+
videoCodec?: string;
|
|
21
|
+
audioCodec?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare class WontumFileInfo {
|
|
24
|
+
private file;
|
|
25
|
+
private videoElement;
|
|
26
|
+
private info;
|
|
27
|
+
constructor(file: File);
|
|
28
|
+
/**
|
|
29
|
+
* Check if the file is a valid video file
|
|
30
|
+
*/
|
|
31
|
+
private isVideoFile;
|
|
32
|
+
/**
|
|
33
|
+
* Extract video metadata
|
|
34
|
+
*/
|
|
35
|
+
extract(): Promise<VideoFileInfo>;
|
|
36
|
+
/**
|
|
37
|
+
* Calculate aspect ratio (e.g., "16:9", "4:3")
|
|
38
|
+
*/
|
|
39
|
+
private calculateAspectRatio;
|
|
40
|
+
/**
|
|
41
|
+
* Get Greatest Common Divisor
|
|
42
|
+
*/
|
|
43
|
+
private getGCD;
|
|
44
|
+
/**
|
|
45
|
+
* Format bytes to human-readable size
|
|
46
|
+
*/
|
|
47
|
+
private formatBytes;
|
|
48
|
+
/**
|
|
49
|
+
* Format duration to HH:MM:SS
|
|
50
|
+
*/
|
|
51
|
+
private formatDuration;
|
|
52
|
+
/**
|
|
53
|
+
* Get file extension
|
|
54
|
+
*/
|
|
55
|
+
private getFileExtension;
|
|
56
|
+
get width(): number;
|
|
57
|
+
get height(): number;
|
|
58
|
+
get aspectRatio(): string;
|
|
59
|
+
get size(): number;
|
|
60
|
+
get sizeInBytes(): number;
|
|
61
|
+
get sizeFormatted(): string;
|
|
62
|
+
get duration(): number;
|
|
63
|
+
get durationInSeconds(): number;
|
|
64
|
+
get durationFormatted(): string;
|
|
65
|
+
get mimeType(): string;
|
|
66
|
+
get fileName(): string;
|
|
67
|
+
get fileExtension(): string;
|
|
68
|
+
get bitrate(): number | undefined;
|
|
69
|
+
get quality(): string;
|
|
70
|
+
/**
|
|
71
|
+
* Get all information as object
|
|
72
|
+
*/
|
|
73
|
+
getInfo(): VideoFileInfo | null;
|
|
74
|
+
/**
|
|
75
|
+
* Clean up resources
|
|
76
|
+
*/
|
|
77
|
+
destroy(): void;
|
|
78
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export { WontumPlayer } from './player';
|
|
|
2
2
|
export { Analytics } from './analytics';
|
|
3
3
|
export { S3Handler } from './s3-handler';
|
|
4
4
|
export { UIController } from './ui-controller';
|
|
5
|
+
export { WontumFileInfo } from './file-info';
|
|
5
6
|
export { WontumPlayerReact, useWontumPlayer, WontumPlayerProvider, useWontumPlayerContext } from './react';
|
|
6
7
|
export type { WontumPlayerConfig, PlayerTheme, S3Config, AnalyticsConfig, PlayerState, PlayerEvent, PlayerEventType, AnalyticsEvent, QualityLevel } from './types';
|
|
8
|
+
export type { VideoFileInfo } from './file-info';
|
|
7
9
|
export type { WontumPlayerReactProps } from './react';
|
package/dist/src/player.d.ts
CHANGED
|
@@ -36,6 +36,9 @@ export declare class WontumPlayer {
|
|
|
36
36
|
getQualities(): QualityLevel[];
|
|
37
37
|
enterFullscreen(): void;
|
|
38
38
|
exitFullscreen(): void;
|
|
39
|
+
enterPictureInPicture(): Promise<void>;
|
|
40
|
+
exitPictureInPicture(): Promise<void>;
|
|
41
|
+
togglePictureInPicture(): Promise<void>;
|
|
39
42
|
getState(): PlayerState;
|
|
40
43
|
getVideoElement(): HTMLVideoElement;
|
|
41
44
|
/**
|
package/dist/src/types.d.ts
CHANGED
|
@@ -45,6 +45,8 @@ export interface S3Config {
|
|
|
45
45
|
getPresignedUrl?: (key: string) => Promise<string>;
|
|
46
46
|
/** CloudFront domain patterns to match (e.g., ['media.domain.com']) */
|
|
47
47
|
cloudFrontDomains?: string[];
|
|
48
|
+
/** Enable credentials (cookies) for HLS requests - required for CloudFront signed cookies */
|
|
49
|
+
withCredentials?: boolean;
|
|
48
50
|
/** S3 bucket region */
|
|
49
51
|
region?: string;
|
|
50
52
|
/** Custom S3 endpoint */
|
|
@@ -82,7 +84,7 @@ export interface PlayerState {
|
|
|
82
84
|
/**
|
|
83
85
|
* Player events (compatible with Mux Player and HTML5 MediaElement events)
|
|
84
86
|
*/
|
|
85
|
-
export type PlayerEventType = "play" | "pause" | "playing" | "ended" | "timeupdate" | "volumechange" | "ratechange" | "seeked" | "seeking" | "waiting" | "loadstart" | "loadeddata" | "loadedmetadata" | "canplay" | "canplaythrough" | "durationchange" | "progress" | "error" | "abort" | "emptied" | "stalled" | "suspend" | "qualitychange" | "fullscreenchange" | "resize";
|
|
87
|
+
export type PlayerEventType = "play" | "pause" | "playing" | "ended" | "timeupdate" | "volumechange" | "ratechange" | "seeked" | "seeking" | "waiting" | "loadstart" | "loadeddata" | "loadedmetadata" | "canplay" | "canplaythrough" | "durationchange" | "progress" | "error" | "abort" | "emptied" | "stalled" | "suspend" | "qualitychange" | "fullscreenchange" | "pictureinpictureenter" | "pictureinpictureexit" | "resize";
|
|
86
88
|
export interface PlayerEvent {
|
|
87
89
|
type: PlayerEventType;
|
|
88
90
|
data?: any;
|
|
@@ -13,12 +13,15 @@ export declare class UIController {
|
|
|
13
13
|
private skipBackwardButton;
|
|
14
14
|
private skipForwardButton;
|
|
15
15
|
private volumeButton;
|
|
16
|
+
private volumeContainer;
|
|
16
17
|
private fullscreenButton;
|
|
18
|
+
private pipButton;
|
|
17
19
|
private settingsButton;
|
|
18
20
|
private volumeSlider;
|
|
19
21
|
private progressInput;
|
|
20
22
|
private hideControlsTimeout;
|
|
21
23
|
private stickyControls;
|
|
24
|
+
private isVolumeSliderActive;
|
|
22
25
|
constructor(container: HTMLElement, player: WontumPlayer);
|
|
23
26
|
private injectStyles;
|
|
24
27
|
private createProgressBar;
|
|
@@ -38,6 +41,7 @@ export declare class UIController {
|
|
|
38
41
|
private getVolumeIcon;
|
|
39
42
|
private getMutedIcon;
|
|
40
43
|
private getFullscreenIcon;
|
|
44
|
+
private getPipIcon;
|
|
41
45
|
private getSkipBackwardIcon;
|
|
42
46
|
private getSkipForwardIcon;
|
|
43
47
|
private getSettingsIcon;
|