unified-video-framework 1.0.0
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/.github/workflows/ci.yml +253 -0
- package/ANDROID_TV_IMPLEMENTATION.md +313 -0
- package/COMPLETION_STATUS.md +165 -0
- package/CONTRIBUTING.md +376 -0
- package/FINAL_STATUS_REPORT.md +170 -0
- package/FRAMEWORK_REVIEW.md +247 -0
- package/IMPROVEMENTS_SUMMARY.md +168 -0
- package/LICENSE +21 -0
- package/NATIVE_APP_INTEGRATION_GUIDE.md +903 -0
- package/PAYWALL_RENTAL_FLOW.md +499 -0
- package/PLATFORM_SETUP_GUIDE.md +1636 -0
- package/README.md +315 -0
- package/RUN_LOCALLY.md +151 -0
- package/apps/demo/cast-sender-min.html +173 -0
- package/apps/demo/custom-player.html +883 -0
- package/apps/demo/demo.html +990 -0
- package/apps/demo/enhanced-player.html +3556 -0
- package/apps/demo/index.html +159 -0
- package/apps/rental-api/.env.example +24 -0
- package/apps/rental-api/README.md +23 -0
- package/apps/rental-api/migrations/001_init.sql +35 -0
- package/apps/rental-api/migrations/002_videos.sql +10 -0
- package/apps/rental-api/migrations/003_add_gateway_subref.sql +4 -0
- package/apps/rental-api/migrations/004_update_gateways.sql +4 -0
- package/apps/rental-api/migrations/005_seed_demo_video.sql +5 -0
- package/apps/rental-api/package-lock.json +2045 -0
- package/apps/rental-api/package.json +33 -0
- package/apps/rental-api/scripts/run-migration.js +42 -0
- package/apps/rental-api/scripts/update-video-currency.js +21 -0
- package/apps/rental-api/scripts/update-video-price.js +19 -0
- package/apps/rental-api/src/config.ts +14 -0
- package/apps/rental-api/src/db.ts +10 -0
- package/apps/rental-api/src/routes/cashfree.ts +167 -0
- package/apps/rental-api/src/routes/pesapal.ts +92 -0
- package/apps/rental-api/src/routes/rentals.ts +242 -0
- package/apps/rental-api/src/routes/webhooks.ts +73 -0
- package/apps/rental-api/src/server.ts +41 -0
- package/apps/rental-api/src/services/entitlements.ts +45 -0
- package/apps/rental-api/src/services/payments.ts +22 -0
- package/apps/rental-api/tsconfig.json +17 -0
- package/check-urls.ps1 +74 -0
- package/comparison-report.md +181 -0
- package/docs/PAYWALL.md +95 -0
- package/docs/PLAYER_UI_VISIBILITY.md +431 -0
- package/docs/README.md +7 -0
- package/docs/SYSTEM_ARCHITECTURE.md +612 -0
- package/docs/VDOCIPHER_CLONE_REQUIREMENTS.md +403 -0
- package/examples/android/JavaSampleApp/MainActivity.java +641 -0
- package/examples/android/JavaSampleApp/activity_main.xml +226 -0
- package/examples/android/SampleApp/MainActivity.kt +430 -0
- package/examples/ios/SampleApp/ViewController.swift +337 -0
- package/examples/ios/SwiftUISampleApp/ContentView.swift +304 -0
- package/iOS_IMPLEMENTATION_OPTIONS.md +470 -0
- package/ios/UnifiedVideoPlayer/UnifiedVideoPlayer.podspec +33 -0
- package/jest.config.js +33 -0
- package/jitpack.yml +5 -0
- package/lerna.json +35 -0
- package/package.json +69 -0
- package/packages/PLATFORM_STATUS.md +163 -0
- package/packages/android/build.gradle +135 -0
- package/packages/android/src/main/AndroidManifest.xml +36 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/PlayerConfiguration.java +221 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/UnifiedVideoPlayer.java +1037 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/UnifiedVideoPlayer.kt +707 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/analytics/AnalyticsProvider.java +9 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/cast/CastManager.java +141 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/cast/CastOptionsProvider.java +29 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/overlay/WatermarkOverlayView.java +88 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/pip/PipActionReceiver.java +33 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/services/PlaybackService.java +110 -0
- package/packages/android/src/main/java/com/unifiedvideo/player/services/PlayerHolder.java +19 -0
- package/packages/core/package.json +34 -0
- package/packages/core/src/BasePlayer.ts +250 -0
- package/packages/core/src/VideoPlayer.ts +237 -0
- package/packages/core/src/VideoPlayerFactory.ts +145 -0
- package/packages/core/src/index.ts +20 -0
- package/packages/core/src/interfaces/IVideoPlayer.ts +184 -0
- package/packages/core/src/interfaces.ts +240 -0
- package/packages/core/src/utils/EventEmitter.ts +66 -0
- package/packages/core/src/utils/PlatformDetector.ts +300 -0
- package/packages/core/tsconfig.json +20 -0
- package/packages/enact/package.json +51 -0
- package/packages/enact/src/VideoPlayer.js +365 -0
- package/packages/enact/src/adapters/TizenAdapter.js +354 -0
- package/packages/enact/src/index.js +82 -0
- package/packages/ios/BUILD_INSTRUCTIONS.md +108 -0
- package/packages/ios/FIX_EMBED_ISSUE.md +142 -0
- package/packages/ios/GETTING_STARTED.md +100 -0
- package/packages/ios/Package.swift +35 -0
- package/packages/ios/README.md +84 -0
- package/packages/ios/Sources/UnifiedVideoPlayer/Analytics/AnalyticsEmitter.swift +26 -0
- package/packages/ios/Sources/UnifiedVideoPlayer/DRM/FairPlayDRMManager.swift +102 -0
- package/packages/ios/Sources/UnifiedVideoPlayer/Info.plist +24 -0
- package/packages/ios/Sources/UnifiedVideoPlayer/Remote/RemoteCommandCenter.swift +109 -0
- package/packages/ios/Sources/UnifiedVideoPlayer/UnifiedVideoPlayer.swift +811 -0
- package/packages/ios/Sources/UnifiedVideoPlayer/UnifiedVideoPlayerView.swift +640 -0
- package/packages/ios/Sources/UnifiedVideoPlayer/Utilities/Color+Hex.swift +36 -0
- package/packages/ios/UnifiedVideoPlayer.podspec +27 -0
- package/packages/ios/UnifiedVideoPlayer.xcodeproj/project.pbxproj +385 -0
- package/packages/ios/build_framework.sh +55 -0
- package/packages/react-native/android/src/main/java/com/unifiedvideo/UnifiedVideoPlayerModule.kt +482 -0
- package/packages/react-native/ios/UnifiedVideoPlayer.swift +436 -0
- package/packages/react-native/package.json +51 -0
- package/packages/react-native/src/ReactNativePlayer.tsx +423 -0
- package/packages/react-native/src/VideoPlayer.tsx +224 -0
- package/packages/react-native/src/index.ts +28 -0
- package/packages/react-native/src/utils/EventEmitter.ts +66 -0
- package/packages/react-native/tsconfig.json +31 -0
- package/packages/roku/components/UnifiedVideoPlayer.brs +400 -0
- package/packages/roku/package.json +44 -0
- package/packages/roku/source/VideoPlayer.brs +231 -0
- package/packages/roku/source/main.brs +28 -0
- package/packages/web/GETTING_STARTED.md +292 -0
- package/packages/web/jest.config.js +28 -0
- package/packages/web/jest.setup.ts +110 -0
- package/packages/web/package.json +50 -0
- package/packages/web/src/SecureVideoPlayer.ts +1164 -0
- package/packages/web/src/WebPlayer.ts +3110 -0
- package/packages/web/src/__tests__/WebPlayer.test.ts +314 -0
- package/packages/web/src/index.ts +14 -0
- package/packages/web/src/paywall/PaywallController.ts +215 -0
- package/packages/web/src/react/WebPlayerView.tsx +177 -0
- package/packages/web/tsconfig.json +23 -0
- package/packages/web/webpack.config.js +45 -0
- package/server.js +131 -0
- package/server.py +84 -0
- package/test-urls.ps1 +97 -0
- package/test-video-urls.ps1 +87 -0
- package/tsconfig.json +39 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
9
|
+
<key>CFBundleIdentifier</key>
|
|
10
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
11
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
12
|
+
<string>6.0</string>
|
|
13
|
+
<key>CFBundleName</key>
|
|
14
|
+
<string>$(PRODUCT_NAME)</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
|
17
|
+
<key>CFBundleShortVersionString</key>
|
|
18
|
+
<string>1.0</string>
|
|
19
|
+
<key>CFBundleVersion</key>
|
|
20
|
+
<string>$(CURRENT_PROJECT_VERSION)</string>
|
|
21
|
+
<key>NSPrincipalClass</key>
|
|
22
|
+
<string></string>
|
|
23
|
+
</dict>
|
|
24
|
+
</plist>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import MediaPlayer
|
|
3
|
+
import AVFoundation
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
final class RemoteCommandCenter {
|
|
7
|
+
private weak var player: AVPlayer?
|
|
8
|
+
private var nowPlaying: [String: Any] = [:]
|
|
9
|
+
|
|
10
|
+
func enable(for player: AVPlayer, title: String?, duration: Double?, artworkURL: URL?) {
|
|
11
|
+
self.player = player
|
|
12
|
+
configureAudioSession()
|
|
13
|
+
setupRemoteCommands()
|
|
14
|
+
updateNowPlaying(title: title, duration: duration, elapsed: currentTime(), isPlaying: player.timeControlStatus == .playing, artworkURL: artworkURL)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
func disable() {
|
|
18
|
+
let center = MPRemoteCommandCenter.shared()
|
|
19
|
+
center.playCommand.isEnabled = false
|
|
20
|
+
center.pauseCommand.isEnabled = false
|
|
21
|
+
center.togglePlayPauseCommand.isEnabled = false
|
|
22
|
+
center.changePlaybackPositionCommand.isEnabled = false
|
|
23
|
+
MPNowPlayingInfoCenter.default().nowPlayingInfo = nil
|
|
24
|
+
nowPlaying = [:]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func updateProgress(elapsed: Double, duration: Double?, isPlaying: Bool) {
|
|
28
|
+
updateNowPlaying(title: nowPlaying[MPMediaItemPropertyTitle] as? String, duration: duration, elapsed: elapsed, isPlaying: isPlaying, artworkURL: nil)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private func configureAudioSession() {
|
|
32
|
+
do {
|
|
33
|
+
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .moviePlayback, options: [])
|
|
34
|
+
try AVAudioSession.sharedInstance().setActive(true)
|
|
35
|
+
} catch {
|
|
36
|
+
// Swallow; caller may be setting this too
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private func setupRemoteCommands() {
|
|
41
|
+
let center = MPRemoteCommandCenter.shared()
|
|
42
|
+
|
|
43
|
+
center.playCommand.isEnabled = true
|
|
44
|
+
center.playCommand.addTarget { [weak self] _ in
|
|
45
|
+
self?.player?.play()
|
|
46
|
+
self?.syncState()
|
|
47
|
+
return .success
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
center.pauseCommand.isEnabled = true
|
|
51
|
+
center.pauseCommand.addTarget { [weak self] _ in
|
|
52
|
+
self?.player?.pause()
|
|
53
|
+
self?.syncState()
|
|
54
|
+
return .success
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
center.togglePlayPauseCommand.isEnabled = true
|
|
58
|
+
center.togglePlayPauseCommand.addTarget { [weak self] _ in
|
|
59
|
+
guard let p = self?.player else { return .commandFailed }
|
|
60
|
+
p.timeControlStatus == .playing ? p.pause() : p.play()
|
|
61
|
+
self?.syncState()
|
|
62
|
+
return .success
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
center.changePlaybackPositionCommand.isEnabled = true
|
|
66
|
+
center.changePlaybackPositionCommand.addTarget { [weak self] e in
|
|
67
|
+
guard let evt = e as? MPChangePlaybackPositionCommandEvent else { return .commandFailed }
|
|
68
|
+
let t = CMTime(seconds: evt.positionTime, preferredTimescale: 600)
|
|
69
|
+
self?.player?.seek(to: t)
|
|
70
|
+
self?.syncState()
|
|
71
|
+
return .success
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private func updateNowPlaying(title: String?, duration: Double?, elapsed: Double, isPlaying: Bool, artworkURL: URL?) {
|
|
76
|
+
var info: [String: Any] = nowPlaying
|
|
77
|
+
if let title = title { info[MPMediaItemPropertyTitle] = title }
|
|
78
|
+
if let duration = duration { info[MPMediaItemPropertyPlaybackDuration] = duration }
|
|
79
|
+
info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = elapsed
|
|
80
|
+
info[MPNowPlayingInfoPropertyPlaybackRate] = isPlaying ? 1.0 : 0.0
|
|
81
|
+
|
|
82
|
+
if let artworkURL = artworkURL {
|
|
83
|
+
URLSession.shared.dataTask(with: artworkURL) { data, _, _ in
|
|
84
|
+
var edited = info
|
|
85
|
+
if let d = data, let img = UIImage(data: d) {
|
|
86
|
+
let art = MPMediaItemArtwork(boundsSize: img.size) { _ in img }
|
|
87
|
+
edited[MPMediaItemPropertyArtwork] = art
|
|
88
|
+
}
|
|
89
|
+
DispatchQueue.main.async { MPNowPlayingInfoCenter.default().nowPlayingInfo = edited }
|
|
90
|
+
}.resume()
|
|
91
|
+
} else {
|
|
92
|
+
MPNowPlayingInfoCenter.default().nowPlayingInfo = info
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
nowPlaying = MPNowPlayingInfoCenter.default().nowPlayingInfo ?? info
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private func syncState() {
|
|
99
|
+
guard let p = player else { return }
|
|
100
|
+
updateNowPlaying(title: nowPlaying[MPMediaItemPropertyTitle] as? String,
|
|
101
|
+
duration: nowPlaying[MPMediaItemPropertyPlaybackDuration] as? Double,
|
|
102
|
+
elapsed: currentTime(),
|
|
103
|
+
isPlaying: p.timeControlStatus == .playing,
|
|
104
|
+
artworkURL: nil)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private func currentTime() -> Double { player?.currentTime().seconds ?? 0 }
|
|
108
|
+
}
|
|
109
|
+
|