unified-video-framework 1.4.412 → 1.4.414

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 (147) hide show
  1. package/package.json +6 -1
  2. package/packages/core/dist/interfaces/IVideoPlayer.d.ts +0 -22
  3. package/packages/core/dist/interfaces/IVideoPlayer.d.ts.map +1 -1
  4. package/packages/core/src/BasePlayer.d.ts +61 -0
  5. package/packages/core/src/BasePlayer.d.ts.map +1 -0
  6. package/packages/core/src/BasePlayer.js +175 -0
  7. package/packages/core/src/BasePlayer.js.map +1 -0
  8. package/packages/core/src/VideoPlayerFactory.d.ts +8 -0
  9. package/packages/core/src/VideoPlayerFactory.d.ts.map +1 -0
  10. package/packages/core/src/VideoPlayerFactory.js +95 -0
  11. package/packages/core/src/VideoPlayerFactory.js.map +1 -0
  12. package/packages/core/src/analytics/adapters/PlayerAnalyticsAdapter.d.ts +18 -0
  13. package/packages/core/src/analytics/adapters/PlayerAnalyticsAdapter.d.ts.map +1 -0
  14. package/packages/core/src/analytics/adapters/PlayerAnalyticsAdapter.js +117 -0
  15. package/packages/core/src/analytics/adapters/PlayerAnalyticsAdapter.js.map +1 -0
  16. package/packages/core/src/analytics/core/AnalyticsProvider.d.ts +18 -0
  17. package/packages/core/src/analytics/core/AnalyticsProvider.d.ts.map +1 -0
  18. package/packages/core/src/analytics/core/AnalyticsProvider.js +99 -0
  19. package/packages/core/src/analytics/core/AnalyticsProvider.js.map +1 -0
  20. package/packages/core/src/analytics/core/DynamicAnalyticsManager.d.ts +20 -0
  21. package/packages/core/src/analytics/core/DynamicAnalyticsManager.d.ts.map +1 -0
  22. package/packages/core/src/analytics/core/DynamicAnalyticsManager.js +161 -0
  23. package/packages/core/src/analytics/core/DynamicAnalyticsManager.js.map +1 -0
  24. package/packages/core/src/analytics/core/EventBatcher.d.ts +32 -0
  25. package/packages/core/src/analytics/core/EventBatcher.d.ts.map +1 -0
  26. package/packages/core/src/analytics/core/EventBatcher.js +98 -0
  27. package/packages/core/src/analytics/core/EventBatcher.js.map +1 -0
  28. package/packages/core/src/analytics/core/PlayerAnalytics.d.ts +19 -0
  29. package/packages/core/src/analytics/core/PlayerAnalytics.d.ts.map +1 -0
  30. package/packages/core/src/analytics/core/PlayerAnalytics.js +80 -0
  31. package/packages/core/src/analytics/core/PlayerAnalytics.js.map +1 -0
  32. package/packages/core/src/analytics/index.d.ts +13 -0
  33. package/packages/core/src/analytics/index.d.ts.map +1 -0
  34. package/packages/core/src/analytics/index.js +13 -0
  35. package/packages/core/src/analytics/index.js.map +1 -0
  36. package/packages/core/src/analytics/types/AnalyticsTypes.d.ts +239 -0
  37. package/packages/core/src/analytics/types/AnalyticsTypes.d.ts.map +1 -0
  38. package/packages/core/src/analytics/types/AnalyticsTypes.js +8 -0
  39. package/packages/core/src/analytics/types/AnalyticsTypes.js.map +1 -0
  40. package/packages/core/src/analytics/utils/DeviceDetection.d.ts +27 -0
  41. package/packages/core/src/analytics/utils/DeviceDetection.d.ts.map +1 -0
  42. package/packages/core/src/analytics/utils/DeviceDetection.js +184 -0
  43. package/packages/core/src/analytics/utils/DeviceDetection.js.map +1 -0
  44. package/packages/core/src/chapter-manager.d.ts +39 -0
  45. package/packages/core/src/chapter-manager.d.ts.map +1 -0
  46. package/packages/core/src/chapter-manager.js +173 -0
  47. package/packages/core/src/chapter-manager.js.map +1 -0
  48. package/packages/core/src/index.d.ts +10 -0
  49. package/packages/core/src/index.d.ts.map +1 -0
  50. package/packages/core/src/index.js +8 -0
  51. package/packages/core/src/index.js.map +1 -0
  52. package/packages/core/src/interfaces/IVideoPlayer.d.ts +229 -0
  53. package/packages/core/src/interfaces/IVideoPlayer.d.ts.map +1 -0
  54. package/packages/core/src/interfaces/IVideoPlayer.js +2 -0
  55. package/packages/core/src/interfaces/IVideoPlayer.js.map +1 -0
  56. package/packages/core/src/interfaces/IVideoPlayer.ts +0 -27
  57. package/packages/core/src/interfaces.d.ts +455 -0
  58. package/packages/core/src/interfaces.d.ts.map +1 -0
  59. package/packages/core/src/interfaces.js +32 -0
  60. package/packages/core/src/interfaces.js.map +1 -0
  61. package/packages/core/src/utils/EventEmitter.d.ts +14 -0
  62. package/packages/core/src/utils/EventEmitter.d.ts.map +1 -0
  63. package/packages/core/src/utils/EventEmitter.js +55 -0
  64. package/packages/core/src/utils/EventEmitter.js.map +1 -0
  65. package/packages/web/dist/WebPlayer.d.ts +0 -4
  66. package/packages/web/dist/WebPlayer.d.ts.map +1 -1
  67. package/packages/web/dist/WebPlayer.js +62 -73
  68. package/packages/web/dist/WebPlayer.js.map +1 -1
  69. package/packages/web/dist/drm/DRMManager.d.ts +16 -9
  70. package/packages/web/dist/drm/DRMManager.d.ts.map +1 -1
  71. package/packages/web/dist/drm/DRMManager.js +109 -42
  72. package/packages/web/dist/drm/DRMManager.js.map +1 -1
  73. package/packages/web/dist/drm/index.d.ts +15 -0
  74. package/packages/web/dist/drm/index.d.ts.map +1 -0
  75. package/packages/web/dist/drm/index.js +13 -0
  76. package/packages/web/dist/drm/index.js.map +1 -0
  77. package/packages/web/dist/drm/providers/BunnyNetProvider.d.ts +19 -0
  78. package/packages/web/dist/drm/providers/BunnyNetProvider.d.ts.map +1 -0
  79. package/packages/web/dist/drm/providers/BunnyNetProvider.js +112 -0
  80. package/packages/web/dist/drm/providers/BunnyNetProvider.js.map +1 -0
  81. package/packages/web/dist/drm/providers/GenericProvider.d.ts +30 -0
  82. package/packages/web/dist/drm/providers/GenericProvider.d.ts.map +1 -0
  83. package/packages/web/dist/drm/providers/GenericProvider.js +104 -0
  84. package/packages/web/dist/drm/providers/GenericProvider.js.map +1 -0
  85. package/packages/web/dist/drm/systems/BaseDRM.d.ts +18 -0
  86. package/packages/web/dist/drm/systems/BaseDRM.d.ts.map +1 -0
  87. package/packages/web/dist/drm/systems/BaseDRM.js +29 -0
  88. package/packages/web/dist/drm/systems/BaseDRM.js.map +1 -0
  89. package/packages/web/dist/drm/systems/FairPlayDRM.d.ts +32 -0
  90. package/packages/web/dist/drm/systems/FairPlayDRM.d.ts.map +1 -0
  91. package/packages/web/dist/drm/systems/FairPlayDRM.js +198 -0
  92. package/packages/web/dist/drm/systems/FairPlayDRM.js.map +1 -0
  93. package/packages/web/dist/drm/systems/PlayReadyDRM.d.ts +9 -0
  94. package/packages/web/dist/drm/systems/PlayReadyDRM.d.ts.map +1 -0
  95. package/packages/web/dist/drm/systems/PlayReadyDRM.js +92 -0
  96. package/packages/web/dist/drm/systems/PlayReadyDRM.js.map +1 -0
  97. package/packages/web/dist/drm/systems/WidevineDRM.d.ts +9 -0
  98. package/packages/web/dist/drm/systems/WidevineDRM.d.ts.map +1 -0
  99. package/packages/web/dist/drm/systems/WidevineDRM.js +73 -0
  100. package/packages/web/dist/drm/systems/WidevineDRM.js.map +1 -0
  101. package/packages/web/dist/drm/types/BunnyNetTypes.d.ts +20 -0
  102. package/packages/web/dist/drm/types/BunnyNetTypes.d.ts.map +1 -0
  103. package/packages/web/dist/drm/types/BunnyNetTypes.js +8 -0
  104. package/packages/web/dist/drm/types/BunnyNetTypes.js.map +1 -0
  105. package/packages/web/dist/drm/types/DRMTypes.d.ts +56 -49
  106. package/packages/web/dist/drm/types/DRMTypes.d.ts.map +1 -1
  107. package/packages/web/dist/drm/types/DRMTypes.js +19 -13
  108. package/packages/web/dist/drm/types/DRMTypes.js.map +1 -1
  109. package/packages/web/dist/drm/utils/BrowserDetector.d.ts +20 -0
  110. package/packages/web/dist/drm/utils/BrowserDetector.d.ts.map +1 -0
  111. package/packages/web/dist/drm/utils/BrowserDetector.js +168 -0
  112. package/packages/web/dist/drm/utils/BrowserDetector.js.map +1 -0
  113. package/packages/web/dist/drm/utils/CertificateManager.d.ts +15 -0
  114. package/packages/web/dist/drm/utils/CertificateManager.d.ts.map +1 -0
  115. package/packages/web/dist/drm/utils/CertificateManager.js +46 -0
  116. package/packages/web/dist/drm/utils/CertificateManager.js.map +1 -0
  117. package/packages/web/dist/drm/utils/DRMErrorHandler.d.ts +7 -0
  118. package/packages/web/dist/drm/utils/DRMErrorHandler.d.ts.map +1 -0
  119. package/packages/web/dist/drm/utils/DRMErrorHandler.js +49 -0
  120. package/packages/web/dist/drm/utils/DRMErrorHandler.js.map +1 -0
  121. package/packages/web/dist/drm/utils/LicenseRequestHandler.d.ts +15 -0
  122. package/packages/web/dist/drm/utils/LicenseRequestHandler.d.ts.map +1 -0
  123. package/packages/web/dist/drm/utils/LicenseRequestHandler.js +110 -0
  124. package/packages/web/dist/drm/utils/LicenseRequestHandler.js.map +1 -0
  125. package/packages/web/dist/react/WebPlayerView.d.ts +1 -18
  126. package/packages/web/dist/react/WebPlayerView.d.ts.map +1 -1
  127. package/packages/web/dist/react/WebPlayerView.js +0 -5
  128. package/packages/web/dist/react/WebPlayerView.js.map +1 -1
  129. package/packages/web/src/WebPlayer.ts +79 -106
  130. package/packages/web/src/drm/DRMManager.ts +214 -99
  131. package/packages/web/src/drm/index.ts +37 -0
  132. package/packages/web/src/drm/providers/BunnyNetProvider.ts +171 -0
  133. package/packages/web/src/drm/providers/GenericProvider.ts +151 -0
  134. package/packages/web/src/drm/systems/BaseDRM.ts +68 -0
  135. package/packages/web/src/drm/systems/FairPlayDRM.ts +306 -0
  136. package/packages/web/src/drm/systems/PlayReadyDRM.ts +132 -0
  137. package/packages/web/src/drm/systems/WidevineDRM.ts +106 -0
  138. package/packages/web/src/drm/types/BunnyNetTypes.ts +35 -0
  139. package/packages/web/src/drm/types/DRMTypes.ts +92 -97
  140. package/packages/web/src/drm/utils/BrowserDetector.ts +233 -0
  141. package/packages/web/src/drm/utils/CertificateManager.ts +86 -0
  142. package/packages/web/src/drm/utils/DRMErrorHandler.ts +84 -0
  143. package/packages/web/src/drm/utils/LicenseRequestHandler.ts +180 -0
  144. package/packages/web/src/react/WebPlayerView.tsx +1 -28
  145. package/packages/web/src/drm/BunnyCDNDRMProvider.ts +0 -104
  146. package/packages/web/src/drm/FairPlayDRMHandler.ts +0 -322
  147. package/packages/web/src/drm/WidevineDRMHandler.ts +0 -246
@@ -1,97 +1,92 @@
1
- /**
2
- * DRM Types and Interfaces
3
- * Core types for the web DRM system supporting Bunny CDN and generic DRM providers
4
- */
5
-
6
- // Token provider interface - allows flexible token injection strategies
7
- export interface DRMTokenProvider {
8
- // Get token for manifest/playlist requests
9
- getManifestToken(): Promise<DRMToken | null>;
10
-
11
- // Get token for media segment requests
12
- getSegmentToken(): Promise<DRMToken | null>;
13
-
14
- // Get token for license server requests
15
- getLicenseToken(): Promise<DRMToken | null>;
16
-
17
- // Check if token needs renewal
18
- shouldRenewToken(token: DRMToken): boolean;
19
-
20
- // Refresh/renew token
21
- renewToken(token: DRMToken): Promise<DRMToken>;
22
- }
23
-
24
- // Token structure
25
- export interface DRMToken {
26
- token: string; // The actual token value
27
- expires: number; // Unix timestamp (seconds)
28
- tokenVer?: string; // Optional token version
29
- }
30
-
31
- // Bunny CDN specific configuration
32
- export interface BunnyCDNDRMConfig {
33
- libraryId: string; // Bunny CDN library ID
34
- videoId: string; // Video ID on Bunny CDN
35
- pullZoneUrl: string; // e.g., "stream.example.com"
36
- tokenProvider: DRMTokenProvider; // Token provider implementation
37
- certificateUrl?: string; // Override default FairPlay certificate URL
38
- licenseUrl?: string; // Override default license URL
39
- enableReferrerProtection?: boolean; // Enable referrer header validation
40
- }
41
-
42
- // Generic DRM configuration (for non-Bunny providers)
43
- export interface GenericDRMConfig {
44
- type: 'widevine' | 'fairplay';
45
- licenseUrl: string;
46
- certificateUrl?: string; // Required for FairPlay
47
- headers?: Record<string, string>; // Custom headers for license requests
48
- certificateHeaders?: Record<string, string>; // Custom headers for certificate requests
49
- }
50
-
51
- // Unified DRM configuration
52
- export interface WebDRMConfig {
53
- // Provider type
54
- provider: 'bunny' | 'generic';
55
-
56
- // Provider-specific config
57
- bunny?: BunnyCDNDRMConfig;
58
- generic?: GenericDRMConfig;
59
- }
60
-
61
- // DRM Handler interface (implemented by Widevine and FairPlay handlers)
62
- export interface IDRMHandler {
63
- // Initialize DRM system
64
- initialize(): Promise<void>;
65
-
66
- // Setup DRM for video element
67
- setupDRM(videoElement: HTMLVideoElement, manifestUrl: string): Promise<void>;
68
-
69
- // Handle license requests
70
- onLicenseRequest(licenseRequest: ArrayBuffer): Promise<ArrayBuffer>;
71
-
72
- // Cleanup resources
73
- destroy(): void;
74
-
75
- // Check if DRM is supported in current browser
76
- isSupported(): boolean;
77
- }
78
-
79
- // EME key system identifiers
80
- export const DRM_KEY_SYSTEMS = {
81
- WIDEVINE: 'com.widevine.alpha',
82
- FAIRPLAY: 'com.apple.fps.1_0',
83
- PLAYREADY: 'com.microsoft.playready',
84
- CLEARKEY: 'org.w3.clearkey'
85
- } as const;
86
-
87
- // Error types
88
- export class DRMError extends Error {
89
- constructor(
90
- message: string,
91
- public code: string,
92
- public details?: any
93
- ) {
94
- super(message);
95
- this.name = 'DRMError';
96
- }
97
- }
1
+ /**
2
+ * DRM Type Definitions
3
+ * Core type definitions and enums for DRM functionality
4
+ */
5
+
6
+ import type { DRMConfig, DRMType } from '@unified-video/core';
7
+ import { DRMType as DRMTypeEnum } from '@unified-video/core';
8
+
9
+ // Extended DRM configuration for internal use
10
+ export interface ExtendedDRMConfig extends DRMConfig {
11
+ // Provider-specific settings
12
+ provider?: 'bunny' | 'generic' | string;
13
+
14
+ // Library/Video IDs for Bunny.net
15
+ libraryId?: string;
16
+ videoId?: string;
17
+
18
+ // Advanced options
19
+ retryConfig?: {
20
+ maxRetries: number;
21
+ retryDelay: number;
22
+ };
23
+
24
+ // Debugging
25
+ debug?: boolean;
26
+ }
27
+
28
+ // Browser DRM capabilities
29
+ export interface DRMCapabilities {
30
+ widevine: boolean;
31
+ fairplay: boolean;
32
+ playready: boolean;
33
+ supportedType: DRMType | null;
34
+ }
35
+
36
+ // License request/response types
37
+ export interface LicenseRequest {
38
+ url: string;
39
+ method: 'POST' | 'GET';
40
+ headers: Record<string, string>;
41
+ body: ArrayBuffer | string;
42
+ responseType: 'arraybuffer' | 'text' | 'json';
43
+ }
44
+
45
+ export interface LicenseResponse {
46
+ license: ArrayBuffer;
47
+ metadata?: any;
48
+ }
49
+
50
+ // EME event types
51
+ export interface EMEMessageEvent {
52
+ messageType: string;
53
+ message: ArrayBuffer;
54
+ }
55
+
56
+ // DRM initialization result
57
+ export interface DRMInitResult {
58
+ success: boolean;
59
+ drmType: DRMType;
60
+ keySystem: string;
61
+ error?: DRMError;
62
+ }
63
+
64
+ // DRM-specific errors
65
+ export interface DRMError {
66
+ code: DRMErrorCode;
67
+ message: string;
68
+ fatal: boolean;
69
+ details?: any;
70
+ systemError?: any;
71
+ }
72
+
73
+ export enum DRMErrorCode {
74
+ UNSUPPORTED_BROWSER = 'DRM_UNSUPPORTED_BROWSER',
75
+ CERTIFICATE_LOAD_FAILED = 'DRM_CERTIFICATE_LOAD_FAILED',
76
+ LICENSE_REQUEST_FAILED = 'DRM_LICENSE_REQUEST_FAILED',
77
+ KEY_SYSTEM_ACCESS_DENIED = 'DRM_KEY_SYSTEM_ACCESS_DENIED',
78
+ MEDIA_KEYS_CREATION_FAILED = 'DRM_MEDIA_KEYS_CREATION_FAILED',
79
+ SESSION_CREATION_FAILED = 'DRM_SESSION_CREATION_FAILED',
80
+ LICENSE_INVALID = 'DRM_LICENSE_INVALID',
81
+ CONFIGURATION_ERROR = 'DRM_CONFIGURATION_ERROR',
82
+ NETWORK_ERROR = 'DRM_NETWORK_ERROR',
83
+ TIMEOUT = 'DRM_TIMEOUT',
84
+ }
85
+
86
+ // Key system mappings
87
+ export const KEY_SYSTEMS: Record<DRMType, string[]> = {
88
+ [DRMTypeEnum.WIDEVINE]: ['com.widevine.alpha'],
89
+ [DRMTypeEnum.PLAYREADY]: ['com.microsoft.playready', 'com.microsoft.playready.recommendation'],
90
+ [DRMTypeEnum.FAIRPLAY]: ['com.apple.fps.1_0', 'com.apple.fps'],
91
+ [DRMTypeEnum.CLEARKEY]: ['webkit-org.w3.clearkey', 'org.w3.clearkey'],
92
+ };
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Browser DRM Detector
3
+ * Detects browser capabilities and determines optimal DRM system
4
+ */
5
+
6
+ import type { DRMType } from '@unified-video/core';
7
+ import { DRMCapabilities, KEY_SYSTEMS } from '../types/DRMTypes';
8
+ import { DRMType as DRMTypeEnum } from '@unified-video/core';
9
+
10
+ export class BrowserDetector {
11
+ private static instance: BrowserDetector;
12
+ private capabilities: DRMCapabilities | null = null;
13
+
14
+ private constructor() {}
15
+
16
+ static getInstance(): BrowserDetector {
17
+ if (!BrowserDetector.instance) {
18
+ BrowserDetector.instance = new BrowserDetector();
19
+ }
20
+ return BrowserDetector.instance;
21
+ }
22
+
23
+ /**
24
+ * Detect DRM capabilities of current browser
25
+ */
26
+ async detectCapabilities(): Promise<DRMCapabilities> {
27
+ if (this.capabilities) {
28
+ return this.capabilities;
29
+ }
30
+
31
+ const capabilities: DRMCapabilities = {
32
+ widevine: false,
33
+ fairplay: false,
34
+ playready: false,
35
+ supportedType: null,
36
+ };
37
+
38
+ // Check for FairPlay (Safari/iOS) - highest priority on Apple devices
39
+ if (this.isSafari() || this.isWebKitBased()) {
40
+ capabilities.fairplay = await this.checkFairPlaySupport();
41
+ if (capabilities.fairplay) {
42
+ capabilities.supportedType = DRMTypeEnum.FAIRPLAY;
43
+ }
44
+ }
45
+
46
+ // Check for Widevine (Chrome, Firefox, Edge)
47
+ if (!capabilities.supportedType) {
48
+ capabilities.widevine = await this.checkWidevineSupport();
49
+ if (capabilities.widevine) {
50
+ capabilities.supportedType = DRMTypeEnum.WIDEVINE;
51
+ }
52
+ }
53
+
54
+ // Check for PlayReady (Edge, IE)
55
+ if (!capabilities.supportedType && this.isEdge()) {
56
+ capabilities.playready = await this.checkPlayReadySupport();
57
+ if (capabilities.playready) {
58
+ capabilities.supportedType = DRMTypeEnum.PLAYREADY;
59
+ }
60
+ }
61
+
62
+ this.capabilities = capabilities;
63
+ return capabilities;
64
+ }
65
+
66
+ /**
67
+ * Get recommended DRM type for current browser
68
+ */
69
+ async getRecommendedDRMType(): Promise<DRMType | null> {
70
+ const caps = await this.detectCapabilities();
71
+ return caps.supportedType;
72
+ }
73
+
74
+ /**
75
+ * Check if specific DRM type is supported
76
+ */
77
+ async isDRMTypeSupported(drmType: DRMType): Promise<boolean> {
78
+ const caps = await this.detectCapabilities();
79
+ switch (drmType) {
80
+ case DRMTypeEnum.WIDEVINE:
81
+ return caps.widevine;
82
+ case DRMTypeEnum.FAIRPLAY:
83
+ return caps.fairplay;
84
+ case DRMTypeEnum.PLAYREADY:
85
+ return caps.playready;
86
+ default:
87
+ return false;
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Check if browser is Safari
93
+ */
94
+ private isSafari(): boolean {
95
+ const ua = navigator.userAgent.toLowerCase();
96
+ return ua.includes('safari') && !ua.includes('chrome') && !ua.includes('chromium');
97
+ }
98
+
99
+ /**
100
+ * Check if browser is WebKit-based
101
+ */
102
+ private isWebKitBased(): boolean {
103
+ return 'WebKitMediaKeys' in window;
104
+ }
105
+
106
+ /**
107
+ * Check if browser is Edge
108
+ */
109
+ private isEdge(): boolean {
110
+ const ua = navigator.userAgent.toLowerCase();
111
+ return ua.includes('edg/');
112
+ }
113
+
114
+ /**
115
+ * Check FairPlay support
116
+ */
117
+ private async checkFairPlaySupport(): Promise<boolean> {
118
+ try {
119
+ // Check for WebKit-specific FairPlay API
120
+ if ('WebKitMediaKeys' in window) {
121
+ return true;
122
+ }
123
+
124
+ // Check via EME API
125
+ if (navigator.requestMediaKeySystemAccess) {
126
+ const config: MediaKeySystemConfiguration[] = [{
127
+ initDataTypes: ['sinf', 'skd'],
128
+ videoCapabilities: [{ contentType: 'application/vnd.apple.mpegurl' }],
129
+ }];
130
+
131
+ for (const keySystem of KEY_SYSTEMS[DRMTypeEnum.FAIRPLAY]) {
132
+ try {
133
+ await navigator.requestMediaKeySystemAccess(keySystem, config);
134
+ return true;
135
+ } catch (e) {
136
+ // Try next key system
137
+ continue;
138
+ }
139
+ }
140
+ }
141
+
142
+ return false;
143
+ } catch {
144
+ return false;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Check Widevine support
150
+ */
151
+ private async checkWidevineSupport(): Promise<boolean> {
152
+ try {
153
+ if (!navigator.requestMediaKeySystemAccess) {
154
+ return false;
155
+ }
156
+
157
+ const config: MediaKeySystemConfiguration[] = [{
158
+ initDataTypes: ['cenc'],
159
+ videoCapabilities: [{
160
+ contentType: 'video/mp4; codecs="avc1.42E01E"',
161
+ }],
162
+ }];
163
+
164
+ for (const keySystem of KEY_SYSTEMS[DRMTypeEnum.WIDEVINE]) {
165
+ try {
166
+ await navigator.requestMediaKeySystemAccess(keySystem, config);
167
+ return true;
168
+ } catch (e) {
169
+ // Try next key system
170
+ continue;
171
+ }
172
+ }
173
+
174
+ return false;
175
+ } catch {
176
+ return false;
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Check PlayReady support
182
+ */
183
+ private async checkPlayReadySupport(): Promise<boolean> {
184
+ try {
185
+ if (!navigator.requestMediaKeySystemAccess) {
186
+ return false;
187
+ }
188
+
189
+ const config: MediaKeySystemConfiguration[] = [{
190
+ initDataTypes: ['cenc'],
191
+ videoCapabilities: [{
192
+ contentType: 'video/mp4; codecs="avc1.42E01E"',
193
+ }],
194
+ }];
195
+
196
+ for (const keySystem of KEY_SYSTEMS[DRMTypeEnum.PLAYREADY]) {
197
+ try {
198
+ await navigator.requestMediaKeySystemAccess(keySystem, config);
199
+ return true;
200
+ } catch (e) {
201
+ // Try next key system
202
+ continue;
203
+ }
204
+ }
205
+
206
+ return false;
207
+ } catch {
208
+ return false;
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Get user-friendly browser name
214
+ */
215
+ getBrowserName(): string {
216
+ const ua = navigator.userAgent.toLowerCase();
217
+
218
+ if (ua.includes('edg/')) return 'Edge';
219
+ if (ua.includes('chrome') || ua.includes('chromium')) return 'Chrome';
220
+ if (ua.includes('firefox')) return 'Firefox';
221
+ if (ua.includes('safari')) return 'Safari';
222
+ if (ua.includes('opera') || ua.includes('opr/')) return 'Opera';
223
+
224
+ return 'Unknown';
225
+ }
226
+
227
+ /**
228
+ * Reset cached capabilities (useful for testing)
229
+ */
230
+ resetCapabilities(): void {
231
+ this.capabilities = null;
232
+ }
233
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Certificate Manager
3
+ * Manages FairPlay DRM certificates with in-memory caching
4
+ */
5
+
6
+ export class CertificateManager {
7
+ private static instance: CertificateManager;
8
+ private cache: Map<string, ArrayBuffer>;
9
+ private maxCacheSize: number = 10; // Max number of certificates to cache
10
+
11
+ private constructor() {
12
+ this.cache = new Map();
13
+ }
14
+
15
+ static getInstance(): CertificateManager {
16
+ if (!CertificateManager.instance) {
17
+ CertificateManager.instance = new CertificateManager();
18
+ }
19
+ return CertificateManager.instance;
20
+ }
21
+
22
+ /**
23
+ * Get certificate from cache
24
+ */
25
+ getCertificate(url: string): ArrayBuffer | null {
26
+ return this.cache.get(url) || null;
27
+ }
28
+
29
+ /**
30
+ * Store certificate in cache
31
+ */
32
+ setCertificate(url: string, certificate: ArrayBuffer): void {
33
+ // Implement LRU eviction if cache is full
34
+ if (this.cache.size >= this.maxCacheSize && !this.cache.has(url)) {
35
+ const firstKey = this.cache.keys().next().value;
36
+ if (firstKey) {
37
+ this.cache.delete(firstKey);
38
+ }
39
+ }
40
+
41
+ this.cache.set(url, certificate);
42
+ }
43
+
44
+ /**
45
+ * Check if certificate is cached
46
+ */
47
+ hasCertificate(url: string): boolean {
48
+ return this.cache.has(url);
49
+ }
50
+
51
+ /**
52
+ * Clear all cached certificates
53
+ */
54
+ clearCache(): void {
55
+ this.cache.clear();
56
+ }
57
+
58
+ /**
59
+ * Remove specific certificate from cache
60
+ */
61
+ removeCertificate(url: string): boolean {
62
+ return this.cache.delete(url);
63
+ }
64
+
65
+ /**
66
+ * Get cache size
67
+ */
68
+ getCacheSize(): number {
69
+ return this.cache.size;
70
+ }
71
+
72
+ /**
73
+ * Set max cache size
74
+ */
75
+ setMaxCacheSize(size: number): void {
76
+ this.maxCacheSize = size;
77
+
78
+ // Evict old entries if current size exceeds new max
79
+ while (this.cache.size > this.maxCacheSize) {
80
+ const firstKey = this.cache.keys().next().value;
81
+ if (firstKey) {
82
+ this.cache.delete(firstKey);
83
+ }
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * DRM Error Handler
3
+ * Converts DRM errors to user-friendly messages
4
+ */
5
+
6
+ import { DRMError, DRMErrorCode } from '../types/DRMTypes';
7
+
8
+ export class DRMErrorHandler {
9
+ /**
10
+ * Get user-friendly error message
11
+ */
12
+ static getUserFriendlyMessage(error: DRMError): string {
13
+ switch (error.code) {
14
+ case DRMErrorCode.UNSUPPORTED_BROWSER:
15
+ return 'DRM is not supported in this browser. Please use Chrome, Safari, Firefox, or Edge.';
16
+
17
+ case DRMErrorCode.CERTIFICATE_LOAD_FAILED:
18
+ return 'Failed to load DRM certificate. Please check your internet connection.';
19
+
20
+ case DRMErrorCode.LICENSE_REQUEST_FAILED:
21
+ return 'Failed to obtain content license. Please check your internet connection and try again.';
22
+
23
+ case DRMErrorCode.KEY_SYSTEM_ACCESS_DENIED:
24
+ return 'Access to DRM system was denied. Please ensure DRM is enabled in your browser settings.';
25
+
26
+ case DRMErrorCode.MEDIA_KEYS_CREATION_FAILED:
27
+ return 'Failed to initialize DRM protection. Please try refreshing the page.';
28
+
29
+ case DRMErrorCode.SESSION_CREATION_FAILED:
30
+ return 'Failed to create secure playback session. Please try again.';
31
+
32
+ case DRMErrorCode.LICENSE_INVALID:
33
+ return 'Invalid or expired content license. You may not have permission to view this content.';
34
+
35
+ case DRMErrorCode.CONFIGURATION_ERROR:
36
+ return 'DRM configuration error. Please contact support.';
37
+
38
+ case DRMErrorCode.NETWORK_ERROR:
39
+ return 'Network error while loading protected content. Please check your internet connection.';
40
+
41
+ case DRMErrorCode.TIMEOUT:
42
+ return 'DRM initialization timed out. Please try again.';
43
+
44
+ default:
45
+ return 'An error occurred while loading protected content. Please try again.';
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Get technical error message for developers
51
+ */
52
+ static getTechnicalMessage(error: DRMError): string {
53
+ let message = `[${error.code}] ${error.message}`;
54
+
55
+ if (error.details) {
56
+ message += `\nDetails: ${JSON.stringify(error.details, null, 2)}`;
57
+ }
58
+
59
+ if (error.systemError) {
60
+ message += `\nSystem Error: ${error.systemError}`;
61
+ }
62
+
63
+ return message;
64
+ }
65
+
66
+ /**
67
+ * Create standardized DRM error
68
+ */
69
+ static createError(
70
+ code: DRMErrorCode,
71
+ message: string,
72
+ fatal: boolean = true,
73
+ details?: any,
74
+ systemError?: any
75
+ ): DRMError {
76
+ return {
77
+ code,
78
+ message,
79
+ fatal,
80
+ details,
81
+ systemError,
82
+ };
83
+ }
84
+ }