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
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Base DRM System
3
+ * Abstract base class for all DRM system implementations
4
+ */
5
+
6
+ import { ExtendedDRMConfig, LicenseRequest, LicenseResponse } from '../types/DRMTypes';
7
+ import { LicenseRequestHandler } from '../utils/LicenseRequestHandler';
8
+
9
+ export abstract class BaseDRM {
10
+ protected videoElement: HTMLVideoElement;
11
+ protected config: ExtendedDRMConfig;
12
+ protected debug: boolean;
13
+ protected licenseHandler: LicenseRequestHandler;
14
+ protected mediaKeys: MediaKeys | null = null;
15
+ protected keySession: MediaKeySession | null = null;
16
+
17
+ constructor(videoElement: HTMLVideoElement, config: ExtendedDRMConfig, debug: boolean = false) {
18
+ this.videoElement = videoElement;
19
+ this.config = config;
20
+ this.debug = debug;
21
+ this.licenseHandler = new LicenseRequestHandler(config, debug);
22
+ }
23
+
24
+ /**
25
+ * Initialize DRM system
26
+ */
27
+ abstract initialize(): Promise<void>;
28
+
29
+ /**
30
+ * Get key system identifier
31
+ */
32
+ abstract getKeySystem(): string;
33
+
34
+ /**
35
+ * Get HLS.js configuration
36
+ */
37
+ abstract getHLSConfig(): any;
38
+
39
+ /**
40
+ * Get dash.js protection data
41
+ */
42
+ abstract getDashProtectionData(): any;
43
+
44
+ /**
45
+ * Cleanup resources
46
+ */
47
+ async destroy(): Promise<void> {
48
+ if (this.keySession) {
49
+ try {
50
+ await this.keySession.close();
51
+ } catch (error) {
52
+ this.log('Error closing key session:', error);
53
+ }
54
+ this.keySession = null;
55
+ }
56
+
57
+ this.mediaKeys = null;
58
+ }
59
+
60
+ /**
61
+ * Debug logging
62
+ */
63
+ protected log(...args: any[]): void {
64
+ if (this.debug) {
65
+ console.log(`[${this.constructor.name}]`, ...args);
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,306 @@
1
+ /**
2
+ * FairPlay DRM Implementation
3
+ * Implements FairPlay DRM for Safari/iOS using WebKit EME APIs
4
+ */
5
+
6
+ import { BaseDRM } from './BaseDRM';
7
+ import { KEY_SYSTEMS, DRMErrorCode } from '../types/DRMTypes';
8
+ import type { DRMType } from '@unified-video/core';
9
+ import { CertificateManager } from '../utils/CertificateManager';
10
+ import { DRMErrorHandler } from '../utils/DRMErrorHandler';
11
+ import { DRMType as DRMTypeEnum } from '@unified-video/core';
12
+
13
+ // WebKit-specific types
14
+ declare global {
15
+ interface HTMLVideoElement {
16
+ webkitSetMediaKeys?: (mediaKeys: any) => void;
17
+ webkitKeys?: any;
18
+ }
19
+
20
+ interface Window {
21
+ WebKitMediaKeys?: any;
22
+ }
23
+ }
24
+
25
+ export class FairPlayDRM extends BaseDRM {
26
+ private certificateManager: CertificateManager;
27
+ private serverCertificate: ArrayBuffer | null = null;
28
+ private encryptedEventHandler: ((event: any) => Promise<void>) | null = null;
29
+ private needKeyEventHandler: ((event: any) => Promise<void>) | null = null;
30
+
31
+ constructor(videoElement: HTMLVideoElement, config: any, debug: boolean = false) {
32
+ super(videoElement, config, debug);
33
+ this.certificateManager = CertificateManager.getInstance();
34
+ }
35
+
36
+ async initialize(): Promise<void> {
37
+ this.log('Initializing FairPlay DRM...');
38
+
39
+ // Load server certificate
40
+ await this.loadCertificate();
41
+
42
+ // Set up encrypted event listeners
43
+ this.setupEncryptedEventListeners();
44
+
45
+ this.log('FairPlay DRM initialized');
46
+ }
47
+
48
+ getKeySystem(): string {
49
+ return KEY_SYSTEMS[DRMTypeEnum.FAIRPLAY][0];
50
+ }
51
+
52
+ getHLSConfig(): any {
53
+ this.log('Generating HLS.js config for FairPlay');
54
+
55
+ const certificateUrl = this.config.certificateUrl || this.config.fairplayOptions?.certificateUrl;
56
+ const licenseUrl = this.config.licenseUrl || this.config.fairplayOptions?.licenseUrl;
57
+
58
+ return {
59
+ emeEnabled: true,
60
+ drmSystems: {
61
+ [this.getKeySystem()]: {
62
+ licenseUrl: licenseUrl,
63
+ serverCertificateUrl: certificateUrl,
64
+ serverCertificate: this.serverCertificate,
65
+ },
66
+ },
67
+ requestMediaKeySystemAccessFunc: this.createMediaKeySystemAccess.bind(this),
68
+ };
69
+ }
70
+
71
+ getDashProtectionData(): any {
72
+ this.log('Generating dash.js protection data for FairPlay');
73
+
74
+ const licenseUrl = this.config.licenseUrl || this.config.fairplayOptions?.licenseUrl;
75
+
76
+ return {
77
+ [this.getKeySystem()]: {
78
+ serverURL: licenseUrl,
79
+ serverCertificate: this.serverCertificate,
80
+ },
81
+ };
82
+ }
83
+
84
+ async destroy(): Promise<void> {
85
+ // Remove event listeners
86
+ if (this.encryptedEventHandler) {
87
+ this.videoElement.removeEventListener('encrypted', this.encryptedEventHandler as any);
88
+ this.encryptedEventHandler = null;
89
+ }
90
+
91
+ if (this.needKeyEventHandler) {
92
+ this.videoElement.removeEventListener('webkitneedkey', this.needKeyEventHandler as any);
93
+ this.needKeyEventHandler = null;
94
+ }
95
+
96
+ await super.destroy();
97
+ }
98
+
99
+ private async loadCertificate(): Promise<void> {
100
+ const certificateUrl = this.config.certificateUrl || this.config.fairplayOptions?.certificateUrl;
101
+
102
+ if (!certificateUrl) {
103
+ throw DRMErrorHandler.createError(
104
+ DRMErrorCode.CONFIGURATION_ERROR,
105
+ 'FairPlay certificate URL not provided',
106
+ true
107
+ );
108
+ }
109
+
110
+ this.log('Loading FairPlay certificate from:', certificateUrl);
111
+
112
+ // Check cache first
113
+ const cached = this.certificateManager.getCertificate(certificateUrl);
114
+ if (cached) {
115
+ this.log('Using cached certificate');
116
+ this.serverCertificate = cached;
117
+ return;
118
+ }
119
+
120
+ // Fetch certificate
121
+ try {
122
+ const response = await fetch(certificateUrl);
123
+ if (!response.ok) {
124
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
125
+ }
126
+
127
+ this.serverCertificate = await response.arrayBuffer();
128
+
129
+ // Cache for future use
130
+ this.certificateManager.setCertificate(certificateUrl, this.serverCertificate);
131
+
132
+ this.log('FairPlay certificate loaded, size:', this.serverCertificate.byteLength, 'bytes');
133
+ } catch (error: any) {
134
+ throw DRMErrorHandler.createError(
135
+ DRMErrorCode.CERTIFICATE_LOAD_FAILED,
136
+ `Failed to load FairPlay certificate: ${error.message}`,
137
+ true,
138
+ error
139
+ );
140
+ }
141
+ }
142
+
143
+ private setupEncryptedEventListeners(): void {
144
+ // Modern EME encrypted event
145
+ this.encryptedEventHandler = this.onEncrypted.bind(this);
146
+ this.videoElement.addEventListener('encrypted', this.encryptedEventHandler as any);
147
+
148
+ // Legacy WebKit needkey event
149
+ this.needKeyEventHandler = this.onWebKitNeedKey.bind(this);
150
+ this.videoElement.addEventListener('webkitneedkey', this.needKeyEventHandler as any);
151
+
152
+ this.log('FairPlay encrypted event listeners set up');
153
+ }
154
+
155
+ private async onEncrypted(event: any): Promise<void> {
156
+ this.log('Encrypted event received:', event);
157
+
158
+ try {
159
+ const initData = event.initData;
160
+ const initDataType = event.initDataType;
161
+
162
+ await this.createSession(initData, initDataType);
163
+ } catch (error) {
164
+ this.log('Error handling encrypted event:', error);
165
+ throw error;
166
+ }
167
+ }
168
+
169
+ private async onWebKitNeedKey(event: any): Promise<void> {
170
+ this.log('WebKit needkey event received');
171
+
172
+ try {
173
+ const initData = event.initData;
174
+ await this.createSession(initData, 'skd');
175
+ } catch (error) {
176
+ this.log('Error handling webkitneedkey event:', error);
177
+ throw error;
178
+ }
179
+ }
180
+
181
+ private async createSession(initData: ArrayBuffer, initDataType: string): Promise<void> {
182
+ // Create media keys if not already created
183
+ if (!this.mediaKeys) {
184
+ try {
185
+ const keySystemAccess = await navigator.requestMediaKeySystemAccess(
186
+ this.getKeySystem(),
187
+ this.getKeySystemConfiguration()
188
+ );
189
+ this.mediaKeys = await keySystemAccess.createMediaKeys();
190
+ await this.videoElement.setMediaKeys(this.mediaKeys);
191
+
192
+ this.log('FairPlay MediaKeys created and set');
193
+ } catch (error: any) {
194
+ throw DRMErrorHandler.createError(
195
+ DRMErrorCode.MEDIA_KEYS_CREATION_FAILED,
196
+ `Failed to create FairPlay MediaKeys: ${error.message}`,
197
+ true,
198
+ error
199
+ );
200
+ }
201
+ }
202
+
203
+ // Create session
204
+ try {
205
+ this.keySession = this.mediaKeys.createSession();
206
+ this.log('FairPlay session created');
207
+
208
+ // Handle license request
209
+ this.keySession.addEventListener('message', async (event: any) => {
210
+ await this.onMessage(event);
211
+ });
212
+
213
+ // Generate license request
214
+ await this.keySession.generateRequest(initDataType, initData);
215
+ } catch (error: any) {
216
+ throw DRMErrorHandler.createError(
217
+ DRMErrorCode.SESSION_CREATION_FAILED,
218
+ `Failed to create FairPlay session: ${error.message}`,
219
+ true,
220
+ error
221
+ );
222
+ }
223
+ }
224
+
225
+ private async onMessage(event: any): Promise<void> {
226
+ this.log('FairPlay message event:', event.messageType);
227
+
228
+ try {
229
+ const message = event.message;
230
+
231
+ // Convert message to base64 for FairPlay license request
232
+ const messageBase64 = this.arrayBufferToBase64(message);
233
+
234
+ const licenseUrl = this.config.licenseUrl || this.config.fairplayOptions?.licenseUrl;
235
+ if (!licenseUrl) {
236
+ throw DRMErrorHandler.createError(
237
+ DRMErrorCode.CONFIGURATION_ERROR,
238
+ 'FairPlay license URL not provided',
239
+ true
240
+ );
241
+ }
242
+
243
+ // Request license from server
244
+ const license = await this.licenseHandler.requestLicense({
245
+ url: licenseUrl,
246
+ method: 'POST',
247
+ headers: {
248
+ 'Content-Type': 'application/octet-stream',
249
+ ...this.config.headers,
250
+ },
251
+ body: message,
252
+ responseType: 'arraybuffer',
253
+ });
254
+
255
+ // Update session with license (CKC - Content Key Context)
256
+ await this.keySession!.update(license.license);
257
+
258
+ this.log('FairPlay license applied successfully');
259
+ } catch (error: any) {
260
+ throw DRMErrorHandler.createError(
261
+ DRMErrorCode.LICENSE_REQUEST_FAILED,
262
+ `Failed to process FairPlay license: ${error.message}`,
263
+ true,
264
+ error
265
+ );
266
+ }
267
+ }
268
+
269
+ private getKeySystemConfiguration(): MediaKeySystemConfiguration[] {
270
+ return [{
271
+ initDataTypes: ['sinf', 'skd'],
272
+ audioCapabilities: [{
273
+ contentType: 'audio/mp4; codecs="mp4a.40.2"',
274
+ }],
275
+ videoCapabilities: [
276
+ {
277
+ contentType: 'application/vnd.apple.mpegurl',
278
+ robustness: 'SW_SECURE_CRYPTO',
279
+ },
280
+ {
281
+ contentType: 'video/mp4; codecs="avc1.42E01E"',
282
+ robustness: 'SW_SECURE_CRYPTO',
283
+ },
284
+ ],
285
+ distinctiveIdentifier: 'not-allowed',
286
+ persistentState: 'not-allowed',
287
+ sessionTypes: ['temporary'],
288
+ }];
289
+ }
290
+
291
+ private async createMediaKeySystemAccess(): Promise<MediaKeySystemAccess> {
292
+ return navigator.requestMediaKeySystemAccess(
293
+ this.getKeySystem(),
294
+ this.getKeySystemConfiguration()
295
+ );
296
+ }
297
+
298
+ private arrayBufferToBase64(buffer: ArrayBuffer): string {
299
+ const bytes = new Uint8Array(buffer);
300
+ let binary = '';
301
+ for (let i = 0; i < bytes.byteLength; i++) {
302
+ binary += String.fromCharCode(bytes[i]);
303
+ }
304
+ return btoa(binary);
305
+ }
306
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * PlayReady DRM Implementation
3
+ * Implements PlayReady DRM for Edge and IE
4
+ */
5
+
6
+ import { BaseDRM } from './BaseDRM';
7
+ import { KEY_SYSTEMS, DRMErrorCode } from '../types/DRMTypes';
8
+ import type { DRMType } from '@unified-video/core';
9
+ import { DRMErrorHandler } from '../utils/DRMErrorHandler';
10
+ import { DRMType as DRMTypeEnum } from '@unified-video/core';
11
+
12
+ export class PlayReadyDRM extends BaseDRM {
13
+ async initialize(): Promise<void> {
14
+ this.log('Initializing PlayReady DRM...');
15
+
16
+ // PlayReady is primarily configured through HLS.js and dash.js
17
+ // Basic EME setup for validation
18
+ try {
19
+ const keySystemAccess = await navigator.requestMediaKeySystemAccess(
20
+ this.getKeySystem(),
21
+ this.getKeySystemConfiguration()
22
+ );
23
+
24
+ this.log('PlayReady key system access granted');
25
+ this.mediaKeys = await keySystemAccess.createMediaKeys();
26
+
27
+ // For HLS.js and dash.js, they handle the actual EME setup
28
+ // We just validate that the system is available
29
+
30
+ } catch (error: any) {
31
+ // Try fallback key system
32
+ try {
33
+ const fallbackKeySystem = KEY_SYSTEMS[DRMTypeEnum.PLAYREADY][1];
34
+ const keySystemAccess = await navigator.requestMediaKeySystemAccess(
35
+ fallbackKeySystem,
36
+ this.getKeySystemConfiguration()
37
+ );
38
+
39
+ this.log('PlayReady fallback key system access granted');
40
+ this.mediaKeys = await keySystemAccess.createMediaKeys();
41
+ } catch (fallbackError: any) {
42
+ this.log('PlayReady initialization failed:', fallbackError);
43
+ throw DRMErrorHandler.createError(
44
+ DRMErrorCode.KEY_SYSTEM_ACCESS_DENIED,
45
+ 'Failed to access PlayReady DRM system',
46
+ true,
47
+ fallbackError
48
+ );
49
+ }
50
+ }
51
+
52
+ this.log('PlayReady DRM initialized');
53
+ }
54
+
55
+ getKeySystem(): string {
56
+ return KEY_SYSTEMS[DRMTypeEnum.PLAYREADY][0];
57
+ }
58
+
59
+ getHLSConfig(): any {
60
+ this.log('Generating HLS.js config for PlayReady');
61
+
62
+ return {
63
+ emeEnabled: true,
64
+ drmSystems: {
65
+ [this.getKeySystem()]: {
66
+ licenseUrl: this.config.licenseUrl || this.config.playreadyOptions?.licenseUrl,
67
+ customData: this.config.customData || this.config.playreadyOptions?.customData,
68
+ },
69
+ // Add fallback key system
70
+ [KEY_SYSTEMS[DRMTypeEnum.PLAYREADY][1]]: {
71
+ licenseUrl: this.config.licenseUrl || this.config.playreadyOptions?.licenseUrl,
72
+ customData: this.config.customData || this.config.playreadyOptions?.customData,
73
+ },
74
+ },
75
+ requestMediaKeySystemAccessFunc: navigator.requestMediaKeySystemAccess.bind(navigator),
76
+ };
77
+ }
78
+
79
+ getDashProtectionData(): any {
80
+ this.log('Generating dash.js protection data for PlayReady');
81
+
82
+ const licenseUrl = this.config.licenseUrl || this.config.playreadyOptions?.licenseUrl;
83
+
84
+ const protectionData: any = {
85
+ [this.getKeySystem()]: {
86
+ serverURL: licenseUrl,
87
+ },
88
+ // Add fallback key system
89
+ [KEY_SYSTEMS[DRMTypeEnum.PLAYREADY][1]]: {
90
+ serverURL: licenseUrl,
91
+ },
92
+ };
93
+
94
+ // Add custom headers if provided
95
+ if (this.config.headers && Object.keys(this.config.headers).length > 0) {
96
+ protectionData[this.getKeySystem()].httpRequestHeaders = this.config.headers;
97
+ protectionData[KEY_SYSTEMS[DRMTypeEnum.PLAYREADY][1]].httpRequestHeaders = this.config.headers;
98
+ }
99
+
100
+ // Add custom data if provided
101
+ const customData = this.config.customData || this.config.playreadyOptions?.customData;
102
+ if (customData) {
103
+ protectionData[this.getKeySystem()].customData = customData;
104
+ protectionData[KEY_SYSTEMS[DRMTypeEnum.PLAYREADY][1]].customData = customData;
105
+ }
106
+
107
+ return protectionData;
108
+ }
109
+
110
+ private getKeySystemConfiguration(): MediaKeySystemConfiguration[] {
111
+ return [{
112
+ initDataTypes: ['cenc'],
113
+ audioCapabilities: [{
114
+ contentType: 'audio/mp4; codecs="mp4a.40.2"',
115
+ robustness: 'SW_SECURE_CRYPTO',
116
+ }],
117
+ videoCapabilities: [
118
+ {
119
+ contentType: 'video/mp4; codecs="avc1.42E01E"',
120
+ robustness: 'SW_SECURE_CRYPTO',
121
+ },
122
+ {
123
+ contentType: 'video/mp4; codecs="avc1.4d401f"',
124
+ robustness: 'SW_SECURE_CRYPTO',
125
+ },
126
+ ],
127
+ distinctiveIdentifier: 'not-allowed',
128
+ persistentState: 'not-allowed',
129
+ sessionTypes: ['temporary'],
130
+ }];
131
+ }
132
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Widevine DRM Implementation
3
+ * Implements Widevine DRM for Chrome, Firefox, Edge, Android
4
+ */
5
+
6
+ import { BaseDRM } from './BaseDRM';
7
+ import { KEY_SYSTEMS, DRMErrorCode } from '../types/DRMTypes';
8
+ import type { DRMType } from '@unified-video/core';
9
+ import { DRMErrorHandler } from '../utils/DRMErrorHandler';
10
+ import { DRMType as DRMTypeEnum } from '@unified-video/core';
11
+
12
+ export class WidevineDRM extends BaseDRM {
13
+ async initialize(): Promise<void> {
14
+ this.log('Initializing Widevine DRM...');
15
+
16
+ // Widevine is primarily configured through HLS.js and dash.js
17
+ // Basic EME setup for validation
18
+ try {
19
+ const keySystemAccess = await navigator.requestMediaKeySystemAccess(
20
+ this.getKeySystem(),
21
+ this.getKeySystemConfiguration()
22
+ );
23
+
24
+ this.log('Widevine key system access granted');
25
+ this.mediaKeys = await keySystemAccess.createMediaKeys();
26
+
27
+ // For HLS.js and dash.js, they handle the actual EME setup
28
+ // We just validate that the system is available
29
+
30
+ } catch (error: any) {
31
+ this.log('Widevine initialization failed:', error);
32
+ throw DRMErrorHandler.createError(
33
+ DRMErrorCode.KEY_SYSTEM_ACCESS_DENIED,
34
+ 'Failed to access Widevine DRM system',
35
+ true,
36
+ error
37
+ );
38
+ }
39
+
40
+ this.log('Widevine DRM initialized');
41
+ }
42
+
43
+ getKeySystem(): string {
44
+ return KEY_SYSTEMS[DRMTypeEnum.WIDEVINE][0];
45
+ }
46
+
47
+ getHLSConfig(): any {
48
+ this.log('Generating HLS.js config for Widevine');
49
+
50
+ return {
51
+ emeEnabled: true,
52
+ drmSystems: {
53
+ [this.getKeySystem()]: {
54
+ licenseUrl: this.config.licenseUrl || this.config.widevineOptions?.licenseUrl,
55
+ serverCertificate: this.config.widevineOptions?.serverCertificate,
56
+ },
57
+ },
58
+ requestMediaKeySystemAccessFunc: navigator.requestMediaKeySystemAccess.bind(navigator),
59
+ };
60
+ }
61
+
62
+ getDashProtectionData(): any {
63
+ this.log('Generating dash.js protection data for Widevine');
64
+
65
+ const protectionData: any = {
66
+ [this.getKeySystem()]: {
67
+ serverURL: this.config.licenseUrl || this.config.widevineOptions?.licenseUrl,
68
+ },
69
+ };
70
+
71
+ // Add custom headers if provided
72
+ if (this.config.headers && Object.keys(this.config.headers).length > 0) {
73
+ protectionData[this.getKeySystem()].httpRequestHeaders = this.config.headers;
74
+ }
75
+
76
+ // Add server certificate if provided
77
+ if (this.config.widevineOptions?.serverCertificate) {
78
+ protectionData[this.getKeySystem()].serverCertificate = this.config.widevineOptions.serverCertificate;
79
+ }
80
+
81
+ return protectionData;
82
+ }
83
+
84
+ private getKeySystemConfiguration(): MediaKeySystemConfiguration[] {
85
+ return [{
86
+ initDataTypes: ['cenc'],
87
+ audioCapabilities: [{
88
+ contentType: 'audio/mp4; codecs="mp4a.40.2"',
89
+ robustness: 'SW_SECURE_CRYPTO',
90
+ }],
91
+ videoCapabilities: [
92
+ {
93
+ contentType: 'video/mp4; codecs="avc1.42E01E"',
94
+ robustness: 'SW_SECURE_CRYPTO',
95
+ },
96
+ {
97
+ contentType: 'video/mp4; codecs="avc1.4d401f"',
98
+ robustness: 'SW_SECURE_CRYPTO',
99
+ },
100
+ ],
101
+ distinctiveIdentifier: 'not-allowed',
102
+ persistentState: 'not-allowed',
103
+ sessionTypes: ['temporary'],
104
+ }];
105
+ }
106
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Bunny.net DRM Type Definitions
3
+ * Type definitions specific to Bunny.net MediaCage DRM integration
4
+ */
5
+
6
+ import type { DRMType } from '@unified-video/core';
7
+
8
+ export interface BunnyNetConfig {
9
+ libraryId: string;
10
+ videoId: string;
11
+ drmType?: DRMType;
12
+ }
13
+
14
+ export interface BunnyNetEndpoints {
15
+ widevine: string;
16
+ fairplayCert: string;
17
+ fairplayLicense: string;
18
+ playready: string;
19
+ }
20
+
21
+ export const BUNNY_NET_BASE_URL = 'https://video.bunnycdn.com';
22
+
23
+ export const BUNNY_NET_ENDPOINTS = {
24
+ WIDEVINE_LICENSE: (libraryId: string, videoId: string) =>
25
+ `${BUNNY_NET_BASE_URL}/WidevineLicense/${libraryId}/${videoId}`,
26
+
27
+ FAIRPLAY_CERTIFICATE: (libraryId: string) =>
28
+ `${BUNNY_NET_BASE_URL}/FairPlay/${libraryId}/certificate`,
29
+
30
+ FAIRPLAY_LICENSE: (libraryId: string, videoId: string) =>
31
+ `${BUNNY_NET_BASE_URL}/FairPlay/${libraryId}/license/?videoId=${videoId}`,
32
+
33
+ PLAYREADY_LICENSE: (libraryId: string, videoId: string) =>
34
+ `${BUNNY_NET_BASE_URL}/PlayReadyLicense/${libraryId}/${videoId}`,
35
+ };