unified-video-framework 1.4.381 → 1.4.383

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 (32) hide show
  1. package/package.json +1 -1
  2. package/packages/core/dist/interfaces.d.ts +9 -2
  3. package/packages/core/dist/interfaces.d.ts.map +1 -1
  4. package/packages/core/dist/interfaces.js +0 -1
  5. package/packages/core/dist/interfaces.js.map +1 -1
  6. package/packages/core/src/interfaces.ts +14 -3
  7. package/packages/react-native/dist/drm/AndroidDRMProtection.js +1 -1
  8. package/packages/react-native/dist/drm/iOSDRMProtection.js +1 -1
  9. package/packages/web/dist/WebPlayer.d.ts +2 -0
  10. package/packages/web/dist/WebPlayer.d.ts.map +1 -1
  11. package/packages/web/dist/WebPlayer.js +9709 -9644
  12. package/packages/web/dist/WebPlayer.js.map +1 -1
  13. package/packages/web/dist/index.d.ts +0 -1
  14. package/packages/web/dist/index.d.ts.map +1 -1
  15. package/packages/web/dist/index.js +6 -7
  16. package/packages/web/dist/index.js.map +1 -1
  17. package/packages/web/dist/react/WebPlayerView.d.ts +3 -0
  18. package/packages/web/dist/react/WebPlayerView.d.ts.map +1 -1
  19. package/packages/web/dist/react/WebPlayerView.js.map +1 -1
  20. package/packages/web/dist/security/ScreenProtectionController.d.ts +31 -0
  21. package/packages/web/dist/security/ScreenProtectionController.d.ts.map +1 -0
  22. package/packages/web/dist/security/ScreenProtectionController.js +193 -0
  23. package/packages/web/dist/security/ScreenProtectionController.js.map +1 -0
  24. package/packages/web/src/WebPlayer.ts +87 -2
  25. package/packages/web/src/index.ts +0 -3
  26. package/packages/web/src/react/WebPlayerView.tsx +5 -0
  27. package/packages/web/src/security/ScreenProtectionController.ts +276 -0
  28. package/scripts/fix-imports.js +22 -12
  29. package/packages/core/src/interfaces/IDRMProtection.ts +0 -285
  30. package/packages/react-native/src/drm/AndroidDRMProtection.ts +0 -419
  31. package/packages/react-native/src/drm/iOSDRMProtection.ts +0 -415
  32. package/packages/web/src/drm/WebDRMProtection.ts +0 -596
@@ -1,415 +0,0 @@
1
- /**
2
- * iOS DRM Protection Implementation
3
- *
4
- * Implements Netflix-like content protection for iOS using:
5
- * - FairPlay Streaming DRM
6
- * - Screen capture detection via UIScreen.isCaptured
7
- * - AirPlay support (DRM playback, not mirroring)
8
- * - External display detection
9
- */
10
-
11
- import { NativeModules, NativeEventEmitter } from 'react-native';
12
- import {
13
- IDRMProtection,
14
- IDRMProtectionConfig,
15
- IDRMProtectionStatus,
16
- CastDevice,
17
- DRMErrorCode,
18
- } from '@unified-video/core';
19
-
20
- const { DRMProtectionModule } = NativeModules;
21
- const drmEventEmitter = new NativeEventEmitter(DRMProtectionModule);
22
-
23
- /**
24
- * iOS DRM Protection
25
- */
26
- export class iOSDRMProtection implements IDRMProtection {
27
- private config: IDRMProtectionConfig;
28
- private status: IDRMProtectionStatus;
29
- private listeners: any[] = [];
30
-
31
- constructor() {
32
- this.config = { enabled: false };
33
- this.status = {
34
- isProtected: false,
35
- drmSystem: 'none',
36
- isScreenRecordingBlocked: false,
37
- isAudioCaptureBlocked: false,
38
- isScreenshotBlocked: false,
39
- isCasting: false,
40
- screenRecordingDetected: false,
41
- mirroringDetected: false,
42
- };
43
- }
44
-
45
- /**
46
- * Initialize DRM protection
47
- */
48
- async initialize(config: IDRMProtectionConfig): Promise<void> {
49
- this.config = {
50
- blockScreenRecording: true,
51
- blockAudioCapture: true,
52
- blockScreenshots: true,
53
- allowCasting: true,
54
- blockMirroring: true,
55
- ...config,
56
- };
57
-
58
- if (!this.config.enabled) {
59
- console.log('[DRM-iOS] Protection disabled');
60
- return;
61
- }
62
-
63
- console.log('[DRM-iOS] Initializing...', this.config);
64
-
65
- try {
66
- // Initialize FairPlay DRM
67
- if (this.config.licenseServerUrl && this.config.certificateUrl) {
68
- await this.initializeFairPlay();
69
- }
70
-
71
- // Start screen capture detection
72
- if (this.config.blockScreenRecording) {
73
- await this.startScreenCaptureDetection();
74
- }
75
-
76
- // Initialize AirPlay
77
- if (this.config.allowCasting) {
78
- await this.initializeAirPlay();
79
- }
80
-
81
- // Setup event listeners
82
- this.setupEventListeners();
83
-
84
- this.status.isProtected = true;
85
- console.log('[DRM-iOS] Protection initialized');
86
- } catch (error) {
87
- console.error('[DRM-iOS] Initialization failed:', error);
88
- throw error;
89
- }
90
- }
91
-
92
- /**
93
- * Initialize FairPlay Streaming
94
- */
95
- private async initializeFairPlay(): Promise<void> {
96
- console.log('[DRM-iOS] Initializing FairPlay...');
97
-
98
- const fairPlayConfig = {
99
- licenseServerUrl: this.config.licenseServerUrl,
100
- certificateUrl: this.config.certificateUrl,
101
- licenseHeaders: this.config.licenseHeaders,
102
- };
103
-
104
- const result = await DRMProtectionModule.initializeFairPlay(fairPlayConfig);
105
-
106
- if (result.success) {
107
- this.status.drmSystem = 'fairplay';
108
- console.log('[DRM-iOS] FairPlay initialized successfully');
109
- } else {
110
- throw {
111
- code: DRMErrorCode.FAIRPLAY_NOT_AVAILABLE,
112
- message: 'FairPlay initialization failed',
113
- platform: 'ios',
114
- recoverable: false,
115
- };
116
- }
117
- }
118
-
119
- /**
120
- * Start screen capture detection using UIScreen.isCaptured
121
- */
122
- private async startScreenCaptureDetection(): Promise<void> {
123
- console.log('[DRM-iOS] Starting screen capture detection...');
124
-
125
- await DRMProtectionModule.startScreenCaptureDetection();
126
- this.status.isScreenRecordingBlocked = true;
127
- }
128
-
129
- /**
130
- * Initialize AirPlay
131
- */
132
- private async initializeAirPlay(): Promise<void> {
133
- console.log('[DRM-iOS] Initializing AirPlay...');
134
-
135
- await DRMProtectionModule.initializeAirPlay({
136
- allowMirroring: false, // Only allow native AirPlay, not screen mirroring
137
- });
138
- }
139
-
140
- /**
141
- * Setup event listeners
142
- */
143
- private setupEventListeners(): void {
144
- // Screen capture detected
145
- this.listeners.push(
146
- drmEventEmitter.addListener('onScreenCaptureDetected', () => {
147
- console.warn('[DRM-iOS] ⚠️ Screen capture detected!');
148
- this.status.screenRecordingDetected = true;
149
- this.config.onScreenRecordingDetected?.();
150
- })
151
- );
152
-
153
- // External display detected (mirroring)
154
- this.listeners.push(
155
- drmEventEmitter.addListener('onExternalDisplayDetected', (event: any) => {
156
- console.warn('[DRM-iOS] ⚠️ External display detected:', event);
157
- this.status.mirroringDetected = true;
158
- this.config.onMirroringDetected?.();
159
- })
160
- );
161
-
162
- // AirPlay started
163
- this.listeners.push(
164
- drmEventEmitter.addListener('onAirPlayStarted', (event: any) => {
165
- console.log('[DRM-iOS] AirPlay started:', event.deviceName);
166
- this.status.isCasting = true;
167
- this.status.castDevice = {
168
- name: event.deviceName,
169
- type: 'airplay',
170
- };
171
- this.config.onCastingStarted?.(event.deviceName, 'airplay');
172
- })
173
- );
174
-
175
- // AirPlay ended
176
- this.listeners.push(
177
- drmEventEmitter.addListener('onAirPlayEnded', () => {
178
- console.log('[DRM-iOS] AirPlay ended');
179
- this.status.isCasting = false;
180
- this.status.castDevice = undefined;
181
- this.config.onCastingEnded?.();
182
- })
183
- );
184
-
185
- // FairPlay license acquired
186
- this.listeners.push(
187
- drmEventEmitter.addListener('onLicenseAcquired', () => {
188
- console.log('[DRM-iOS] FairPlay license acquired');
189
- this.config.onLicenseAcquired?.();
190
- })
191
- );
192
-
193
- // DRM error
194
- this.listeners.push(
195
- drmEventEmitter.addListener('onDRMError', (error: any) => {
196
- console.error('[DRM-iOS] DRM Error:', error);
197
- this.config.onDRMError?.(error);
198
- })
199
- );
200
- }
201
-
202
- /**
203
- * Get current status
204
- */
205
- getStatus(): IDRMProtectionStatus {
206
- return { ...this.status };
207
- }
208
-
209
- /**
210
- * Enable/disable protection
211
- */
212
- setEnabled(enabled: boolean): void {
213
- this.config.enabled = enabled;
214
- DRMProtectionModule.setEnabled(enabled);
215
- }
216
-
217
- /**
218
- * Set specific feature
219
- */
220
- setFeature(feature: keyof IDRMProtectionConfig, enabled: boolean): void {
221
- (this.config as any)[feature] = enabled;
222
-
223
- switch (feature) {
224
- case 'blockScreenRecording':
225
- if (enabled) {
226
- this.startScreenCaptureDetection();
227
- }
228
- break;
229
- }
230
- }
231
-
232
- /**
233
- * Start casting (AirPlay)
234
- */
235
- async startCasting(deviceId: string): Promise<void> {
236
- await DRMProtectionModule.startAirPlay(deviceId);
237
- }
238
-
239
- /**
240
- * Stop casting
241
- */
242
- async stopCasting(): Promise<void> {
243
- await DRMProtectionModule.stopAirPlay();
244
- }
245
-
246
- /**
247
- * Get available cast devices
248
- */
249
- async getAvailableCastDevices(): Promise<CastDevice[]> {
250
- const devices = await DRMProtectionModule.getAvailableAirPlayDevices();
251
- return devices.map((device: any) => ({
252
- id: device.id,
253
- name: device.name,
254
- type: 'airplay',
255
- isAvailable: device.isAvailable,
256
- capabilities: {
257
- supportsVideo: true,
258
- supportsAudio: true,
259
- supportsDRM: device.supportsFairPlay,
260
- maxResolution: device.maxResolution,
261
- },
262
- }));
263
- }
264
-
265
- /**
266
- * Renew license
267
- */
268
- async renewLicense(): Promise<void> {
269
- await DRMProtectionModule.renewFairPlayLicense();
270
- }
271
-
272
- /**
273
- * Cleanup
274
- */
275
- dispose(): void {
276
- this.listeners.forEach((listener) => listener.remove());
277
- this.listeners = [];
278
- DRMProtectionModule.dispose();
279
- this.status.isProtected = false;
280
- }
281
- }
282
-
283
- /**
284
- * NATIVE iOS MODULE (Swift)
285
- *
286
- * File: ios/YourApp/DRMProtectionModule.swift
287
- *
288
- * ```swift
289
- * import Foundation
290
- * import AVFoundation
291
- * import React
292
- *
293
- * @objc(DRMProtectionModule)
294
- * class DRMProtectionModule: RCTEventEmitter {
295
- *
296
- * private var screenCaptureObserver: NSObjectProtocol?
297
- * private var externalDisplayObserver: NSObjectProtocol?
298
- * private var fairPlayResourceLoader: FairPlayResourceLoader?
299
- *
300
- * override static func requiresMainQueueSetup() -> Bool {
301
- * return true
302
- * }
303
- *
304
- * override func supportedEvents() -> [String]! {
305
- * return [
306
- * "onScreenCaptureDetected",
307
- * "onExternalDisplayDetected",
308
- * "onAirPlayStarted",
309
- * "onAirPlayEnded",
310
- * "onLicenseAcquired",
311
- * "onDRMError"
312
- * ]
313
- * }
314
- *
315
- * @objc
316
- * func initializeFairPlay(_ config: NSDictionary, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
317
- * guard let licenseServerUrl = config["licenseServerUrl"] as? String,
318
- * let certificateUrl = config["certificateUrl"] as? String else {
319
- * rejecter("FAIRPLAY_ERROR", "Invalid configuration", nil)
320
- * return
321
- * }
322
- *
323
- * fairPlayResourceLoader = FairPlayResourceLoader(
324
- * licenseServerUrl: licenseServerUrl,
325
- * certificateUrl: certificateUrl
326
- * )
327
- *
328
- * resolver(["success": true])
329
- * }
330
- *
331
- * @objc
332
- * func startScreenCaptureDetection(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
333
- * if #available(iOS 11.0, *) {
334
- * // Monitor UIScreen.isCaptured
335
- * screenCaptureObserver = NotificationCenter.default.addObserver(
336
- * forName: UIScreen.capturedDidChangeNotification,
337
- * object: nil,
338
- * queue: .main
339
- * ) { [weak self] _ in
340
- * if UIScreen.main.isCaptured {
341
- * print("[DRM] Screen capture detected!")
342
- * self?.sendEvent(withName: "onScreenCaptureDetected", body: ["isCaptured": true])
343
- * }
344
- * }
345
- *
346
- * // Monitor external displays
347
- * externalDisplayObserver = NotificationCenter.default.addObserver(
348
- * forName: UIScreen.didConnectNotification,
349
- * object: nil,
350
- * queue: .main
351
- * ) { [weak self] notification in
352
- * if let screen = notification.object as? UIScreen {
353
- * print("[DRM] External display connected")
354
- * self?.sendEvent(withName: "onExternalDisplayDetected", body: [
355
- * "screenName": screen.debugDescription
356
- * ])
357
- * }
358
- * }
359
- *
360
- * resolve(true)
361
- * } else {
362
- * reject("NOT_SUPPORTED", "Screen capture detection requires iOS 11+", nil)
363
- * }
364
- * }
365
- *
366
- * @objc
367
- * func initializeAirPlay(_ config: NSDictionary, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
368
- * // Configure AirPlay
369
- * let allowMirroring = config["allowMirroring"] as? Bool ?? false
370
- * resolver(true)
371
- * }
372
- *
373
- * deinit {
374
- * if let observer = screenCaptureObserver {
375
- * NotificationCenter.default.removeObserver(observer)
376
- * }
377
- * if let observer = externalDisplayObserver {
378
- * NotificationCenter.default.removeObserver(observer)
379
- * }
380
- * }
381
- * }
382
- *
383
- * // FairPlay Resource Loader
384
- * class FairPlayResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
385
- * let licenseServerUrl: String
386
- * let certificateUrl: String
387
- *
388
- * init(licenseServerUrl: String, certificateUrl: String) {
389
- * self.licenseServerUrl = licenseServerUrl
390
- * self.certificateUrl = certificateUrl
391
- * }
392
- *
393
- * func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
394
- * guard let url = loadingRequest.request.url else {
395
- * return false
396
- * }
397
- *
398
- * // Handle FairPlay license request
399
- * // 1. Get certificate from certificateUrl
400
- * // 2. Create SPC (Server Playback Context)
401
- * // 3. Send to license server
402
- * // 4. Get CKC (Content Key Context)
403
- * // 5. Provide to AVPlayer
404
- *
405
- * return true
406
- * }
407
- * }
408
- * ```
409
- *
410
- * Info.plist requirements:
411
- * ```xml
412
- * <key>NSMicrophoneUsageDescription</key>
413
- * <string>Required for content protection</string>
414
- * ```
415
- */