mirror of
https://github.com/zoriya/react-native-video.git
synced 2026-06-07 20:31:58 +00:00
feat(ios): add overridePlayerAsset to AVPlayerPlugin (#4522)
This commit is contained in:
@@ -209,29 +209,80 @@ class MyAVPlayerAnalyticsPlugin: RNVAVPlayerPlugin {
|
|||||||
override func onInstanceRemoved(id: String, player: AVPlayer) {
|
override func onInstanceRemoved(id: String, player: AVPlayer) {
|
||||||
// Handle AVPlayer removal with type-safe access
|
// Handle AVPlayer removal with type-safe access
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Optionally override the asset used by the player before playback starts
|
||||||
|
override func overridePlayerAsset(source: VideoSource, asset: AVAsset) async -> OverridePlayerAssetResult? {
|
||||||
|
// Return a modified asset or nil to use the default
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `RNVPlugin` class defines two methods:
|
The `RNVAVPlayerPlugin` class defines several extension points:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
/**
|
/**
|
||||||
* Function called when a new player is created
|
* Function called when a new AVPlayer instance is created
|
||||||
* @param id: a random string identifying the player
|
* @param id: a random string identifying the player
|
||||||
* @param player: the instantiated player reference
|
* @param player: the instantiated AVPlayer
|
||||||
*/
|
*/
|
||||||
open func onInstanceCreated(id: String, player: Any) { /* no-op */ }
|
open func onInstanceCreated(id: String, player: AVPlayer) { /* no-op */ }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called when a player should be destroyed
|
* Function called when an AVPlayer instance is being removed
|
||||||
* when this callback is called, the plugin shall free all
|
|
||||||
* resources and release all reference to Player object
|
|
||||||
* @param id: a random string identifying the player
|
* @param id: a random string identifying the player
|
||||||
* @param player: the player to release
|
* @param player: the AVPlayer to release
|
||||||
*/
|
*/
|
||||||
open func onInstanceRemoved(id: String, player: Any) { /* no-op */ }
|
open func onInstanceRemoved(id: String, player: AVPlayer) { /* no-op */ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optionally override the asset used by the player before playback starts.
|
||||||
|
* Allows you to modify or replace the AVAsset before it is used to create the AVPlayerItem.
|
||||||
|
* Return nil to use the default asset.
|
||||||
|
*
|
||||||
|
* @param source: The VideoSource describing the video (uri, type, headers, etc.)
|
||||||
|
* @param asset: The AVAsset prepared by the player
|
||||||
|
* @return: OverridePlayerAssetResult if you want to override, or nil to use the default
|
||||||
|
*/
|
||||||
|
open func overridePlayerAsset(source: VideoSource, asset: AVAsset) async -> OverridePlayerAssetResult? { nil }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### `OverridePlayerAssetResult` and `OverridePlayerAssetType`
|
||||||
|
|
||||||
|
To override the asset, return an `OverridePlayerAssetResult`:
|
||||||
|
|
||||||
|
```swift
|
||||||
|
public struct OverridePlayerAssetResult {
|
||||||
|
public let type: OverridePlayerAssetType
|
||||||
|
public let asset: AVAsset
|
||||||
|
|
||||||
|
public init(type: OverridePlayerAssetType, asset: AVAsset) {
|
||||||
|
self.type = type
|
||||||
|
self.asset = asset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OverridePlayerAssetType {
|
||||||
|
case partial // Return a partially modified asset; will go through the default prepare process
|
||||||
|
case full // Return a fully modified asset; will skip the default prepare process
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Use `.partial` if you want the asset to continue through the player's normal preparation (e.g., for text tracks or metadata injection).
|
||||||
|
- Use `.full` if you want to provide a fully prepared asset that will be used as-is for playback.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
```swift
|
||||||
|
override func overridePlayerAsset(source: VideoSource, asset: AVAsset) async -> OverridePlayerAssetResult? {
|
||||||
|
// Example: Replace the asset URL
|
||||||
|
let newAsset = AVAsset(url: URL(string: "https://example.com/override.mp4")!)
|
||||||
|
return Result(type: .full, asset: newAsset)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> Only one plugin can override the player asset at a time. If multiple plugins implement this, only the first will be used.
|
||||||
|
|
||||||
### 3. Register the Plugin
|
### 3. Register the Plugin
|
||||||
|
|
||||||
To register the plugin in `react-native-video`, call:
|
To register the plugin in `react-native-video`, call:
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- boost (1.84.0)
|
- boost (1.84.0)
|
||||||
- DoubleConversion (1.1.6)
|
- DoubleConversion (1.1.6)
|
||||||
- EXConstants (17.0.3):
|
- EXConstants (17.0.8):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- Expo (52.0.7):
|
- Expo (52.0.46):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoAsset (11.0.1):
|
- ExpoAsset (11.0.5):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoFileSystem (18.0.3):
|
- ExpoFileSystem (18.0.12):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoFont (13.0.1):
|
- ExpoFont (13.0.4):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoKeepAwake (14.0.1):
|
- ExpoKeepAwake (14.0.3):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoModulesCore (2.0.3):
|
- ExpoModulesCore (2.2.3):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
@@ -36,7 +36,7 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/bridging
|
- ReactCommon/turbomodule/bridging
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- Yoga
|
- Yoga
|
||||||
- ExpoSplashScreen (0.29.11):
|
- ExpoSplashScreen (0.29.24):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- FBLazyVector (0.76.2-0)
|
- FBLazyVector (0.76.2-0)
|
||||||
- fmt (9.1.0)
|
- fmt (9.1.0)
|
||||||
@@ -1278,7 +1278,7 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/bridging
|
- ReactCommon/turbomodule/bridging
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- Yoga
|
- Yoga
|
||||||
- react-native-video (6.10.0):
|
- react-native-video (6.12.0):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
@@ -1291,7 +1291,7 @@ PODS:
|
|||||||
- React-featureflags
|
- React-featureflags
|
||||||
- React-graphics
|
- React-graphics
|
||||||
- React-ImageManager
|
- React-ImageManager
|
||||||
- react-native-video/Video (= 6.10.0)
|
- react-native-video/Video (= 6.12.0)
|
||||||
- React-NativeModulesApple
|
- React-NativeModulesApple
|
||||||
- React-RCTFabric
|
- React-RCTFabric
|
||||||
- React-rendererdebug
|
- React-rendererdebug
|
||||||
@@ -1322,7 +1322,7 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/bridging
|
- ReactCommon/turbomodule/bridging
|
||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- Yoga
|
- Yoga
|
||||||
- react-native-video/Video (6.10.0):
|
- react-native-video/Video (6.12.0):
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- glog
|
- glog
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
@@ -1851,80 +1851,80 @@ EXTERNAL SOURCES:
|
|||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
boost: ad4d3a971e4f0b520a127c02c8c3f98b43394c15
|
boost: ad4d3a971e4f0b520a127c02c8c3f98b43394c15
|
||||||
DoubleConversion: 9a8708fb8299350a38a3425761aaea31263b7443
|
DoubleConversion: 9a8708fb8299350a38a3425761aaea31263b7443
|
||||||
EXConstants: dd2fe64c6cdb1383b694c309a63028a8e9f2be6d
|
EXConstants: fcfc75800824ac2d5c592b5bc74130bad17b146b
|
||||||
Expo: 46cbe74ce0d0f4a4d7b726e90693eb8dfcec6de0
|
Expo: a6ff273c618506b12129a0d06f2a08201bfbcf43
|
||||||
ExpoAsset: 8138f2a9ec55ae1ad7c3871448379f7d97692d15
|
ExpoAsset: 48386d40d53a8c1738929b3ed509bcad595b5516
|
||||||
ExpoFileSystem: cc31b7a48031ab565f9eb5c2b61aa08d774a271a
|
ExpoFileSystem: 42d363d3b96f9afab980dcef60d5657a4443c655
|
||||||
ExpoFont: 7522d869d84ee2ee8093ee997fef5b86f85d856b
|
ExpoFont: f354e926f8feae5e831ec8087f36652b44a0b188
|
||||||
ExpoKeepAwake: 783e68647b969b210a786047c3daa7b753dcac1f
|
ExpoKeepAwake: b0171a73665bfcefcfcc311742a72a956e6aa680
|
||||||
ExpoModulesCore: 2d1df04dc27f91d8b383c0ec7f1d121e3d9b7f68
|
ExpoModulesCore: 15f60d00e33ca0cea27147543877ca6e70c42ef5
|
||||||
ExpoSplashScreen: 26cee50e9e95572baf87cd3a8ccaf2ffc3856422
|
ExpoSplashScreen: 399ee9f85b6c8a61b965e13a1ecff8384db591c2
|
||||||
FBLazyVector: 6bbb8b88508d32cdf0ffb7ceddedf6aca79eff14
|
FBLazyVector: 6bbb8b88508d32cdf0ffb7ceddedf6aca79eff14
|
||||||
fmt: a150d37a5595336f19c91e6f1db7fcf17d5eb99f
|
fmt: a150d37a5595336f19c91e6f1db7fcf17d5eb99f
|
||||||
glog: 9ab333e271c177cecb6362fe27832c88667cb7e9
|
glog: 9ab333e271c177cecb6362fe27832c88667cb7e9
|
||||||
hermes-engine: 7bc33a9a81e6a58b3bc3426105ecd59981ac730e
|
hermes-engine: 7bc33a9a81e6a58b3bc3426105ecd59981ac730e
|
||||||
RCT-Folly: 2512380c804686400e7f60b9e8b60525df4a6191
|
RCT-Folly: 839d900d8e4d2b726f3277dd085d97c8904f9eac
|
||||||
RCTDeprecation: b90bc991c207fa777f3d4f0d7f36d7473e62319a
|
RCTDeprecation: b90bc991c207fa777f3d4f0d7f36d7473e62319a
|
||||||
RCTRequired: c8fda281396e4e5cf96e3ab216c05986fb37ca3e
|
RCTRequired: c8fda281396e4e5cf96e3ab216c05986fb37ca3e
|
||||||
RCTTypeSafety: 28a29fb79051f043943135d2e4403e77d3b7ec21
|
RCTTypeSafety: 28a29fb79051f043943135d2e4403e77d3b7ec21
|
||||||
React: dade949d9edcee964714fe90a2892beef3d3a54b
|
React: dade949d9edcee964714fe90a2892beef3d3a54b
|
||||||
React-callinvoker: a6517e487e1645d2bc627be8d86b1f8dd5278bb5
|
React-callinvoker: a6517e487e1645d2bc627be8d86b1f8dd5278bb5
|
||||||
React-Core: 7010fbd0ed122476aa2cf7aa9619ec9ffb73c551
|
React-Core: 3b252d6ed5c2b9e50ed245f95aa4de1f6b5849ab
|
||||||
React-CoreModules: 64eea3d14266e79f8362da71623a5157a7a6c41f
|
React-CoreModules: 5df4a1fa73a93ca46c33f22148b4f4693b64364e
|
||||||
React-cxxreact: 01f36b93aa3c923f7607c50a43cc2b5a06129f07
|
React-cxxreact: e8b2b06dfbb9d646d9b45a29c3fc67f230e76fa9
|
||||||
React-debug: 25139c51b9fda09bb1745952c81cea9f46225d6a
|
React-debug: 25139c51b9fda09bb1745952c81cea9f46225d6a
|
||||||
React-defaultsnativemodule: 3805189f0d7bce05b3650d364676cf9b49e75eab
|
React-defaultsnativemodule: 6a217b48ce4eb487e7f0a9697ba6513a274cdbdc
|
||||||
React-domnativemodule: abb803da2e62c1acbae61d277fd044fe77f6a9af
|
React-domnativemodule: 64d0ffb108dc00a1275338afdfb78766fbd799d0
|
||||||
React-Fabric: c8d1c4207248fbaf9c046d92d81bab67d4694122
|
React-Fabric: cb88e6fe3e97be05b425413dbba4fb6cab8e9b34
|
||||||
React-FabricComponents: 7147628a2fec488771369e0a0dead89ad9649e0e
|
React-FabricComponents: c5a6e9c81f9a64521ac8abf9ca2f2532e1398b86
|
||||||
React-FabricImage: f814221b18a7d560baaa5fb807895c4c345036be
|
React-FabricImage: 724ae12ceb53b5f01dfc03d0acd63e392487713f
|
||||||
React-featureflags: b684bbc804b9c85754fd009167a527a6eadbd9d5
|
React-featureflags: b684bbc804b9c85754fd009167a527a6eadbd9d5
|
||||||
React-featureflagsnativemodule: 8b29cc7a659d17d0072924a83de9cf9a62a4d147
|
React-featureflagsnativemodule: 46d989a753848048218ea29a30c081274c42e661
|
||||||
React-graphics: 4d7d1fa0ea456c398de7b1f40f708885bccec2e8
|
React-graphics: accc162849d86b3a8607ce80dd49afc129f35f66
|
||||||
React-hermes: 981bd8b0f89a50a8fd06079bbdc4b11003135021
|
React-hermes: 2702dda9e6550e7bfcd6d11ed2dd5ac79ee824a7
|
||||||
React-idlecallbacksnativemodule: 12e7223f085d9d0b82aa0a10b0691294b11c792e
|
React-idlecallbacksnativemodule: c271aad98748669cf8a045b0559a0d3fd67013d2
|
||||||
React-ImageManager: 4300a7a83ee603351659dade2e61e673ae3b88d2
|
React-ImageManager: 6eb6ea557f32850680896907964fc0a8515721db
|
||||||
React-jserrorhandler: 40984dfabb1ab0b2e21d9d21af66530d5309aad0
|
React-jserrorhandler: 6236637935a035413e9ada45c7a08a2a58fa7212
|
||||||
React-jsi: ecb93733e8efcd240957abf32b33624ce207d1f9
|
React-jsi: a18137983c0690f3e29882128aa7daf624d2fdac
|
||||||
React-jsiexecutor: 7ceddf35714b4c4a95ea1f590a16d96b1d577c49
|
React-jsiexecutor: 75909d0eeac14133f33a0446b776388591e1c7c7
|
||||||
React-jsinspector: fe8b01493fb3cb8c6b946cb24c3e83e5d774fb1e
|
React-jsinspector: db3334448e910b60b59cd1809dcf747970525077
|
||||||
React-jsitracing: 47a37e9a623aadd867574d8143fa314df57f1f49
|
React-jsitracing: 545fc999f9db67b157323f439ff964caccae2c48
|
||||||
React-logger: e928ead07d07fbe16f5bebc7ee004bfb7bf731d5
|
React-logger: c1804a09cb1c3486fcd9c2b4753ba7b5b9ae1c38
|
||||||
React-Mapbuffer: 08b067fc26d19868b0a1fea3586d92afff4e8e4f
|
React-Mapbuffer: 2c717de369c66af62d34cdf52202da3951feab59
|
||||||
React-microtasksnativemodule: 309d3c6653f4ffcb8a3956604e07ab19b006ef82
|
React-microtasksnativemodule: c285dc3fa70ea3099d8ee0887aab0fc53f3ef791
|
||||||
react-native-video: 25ecb15d6ac0f97e2d863cbe317c70bd6e8f1a6e
|
react-native-video: b18f2dda48b6424cb8d4d6168821223bbf9eb38a
|
||||||
react-native-video-plugin-sample: 1f6b1dda047cdf07f6cd7e730dc92c1349656b1a
|
react-native-video-plugin-sample: 79af31831cddfa916eb264d89b006fdcf227a8f5
|
||||||
React-nativeconfig: e90353e1c5ab46843222e25d529d342c174184f4
|
React-nativeconfig: e90353e1c5ab46843222e25d529d342c174184f4
|
||||||
React-NativeModulesApple: 5f46e9be9fbff00c706cb31a91753975e99f86a1
|
React-NativeModulesApple: de38a9d30fafd773bc72e8b078d57de2dfccae7f
|
||||||
React-perflogger: a629f2ce2eeab290cfc851a015c5d804a8b36f20
|
React-perflogger: 63dd38ee6f413be0aa176de9f6efc65819e289ca
|
||||||
React-performancetimeline: 09eaa1261ce7b3d51dcd8001f922c7b7f018957c
|
React-performancetimeline: 450a56eff8fbe3de667f26d1857f3bd150e037a7
|
||||||
React-RCTActionSheet: 0622ace751a55109844ff5d6239c83ae36f193d6
|
React-RCTActionSheet: 0622ace751a55109844ff5d6239c83ae36f193d6
|
||||||
React-RCTAnimation: 8651b17476b17d97d7f0fad16d9020f9b1724226
|
React-RCTAnimation: 90e804d3918a97910c94732f23f1c3d3ac43d1ff
|
||||||
React-RCTAppDelegate: 09147856b3e6c55f45afc32f485697b9c7097830
|
React-RCTAppDelegate: 7503e65922a7de2dcb04c7ad9dba8d18c0c1084b
|
||||||
React-RCTBlob: 4ce6e176c0b0999b6ae907537c665dec382095ca
|
React-RCTBlob: e0ac1d709fab205330a6a4ff3430b19358fe2aa4
|
||||||
React-RCTFabric: 6d6d776ec2bb746a599ca113da4c9e5e30519175
|
React-RCTFabric: a308ebf92877e49196d81568a0098bc5a54b0cc2
|
||||||
React-RCTImage: 1ba821a26daf160f596266f78b084df38bad43bf
|
React-RCTImage: 3ebf257e04f4e0d366e8d11e9ee0c9fb1d5318e4
|
||||||
React-RCTLinking: b913efa56e459a7c9bd8575ea35fffcd43d2b226
|
React-RCTLinking: 86a8f8fb5169e0499d8ff9f17b466103a9c7344f
|
||||||
React-RCTNetwork: ff7b971a79b35407aa7fc84d0d34d4bf87977832
|
React-RCTNetwork: 9d8dae79abf6281174aabdcd5cb952b125a19834
|
||||||
React-RCTSettings: a40d2c591ea4b3ebeb0d5fca84cef83bf3a808b8
|
React-RCTSettings: 26320c05739c8dc553e87f8195efb51fa1a4f4d1
|
||||||
React-RCTText: 54e4c01e54f2b323494950100b3f96a44c8d756a
|
React-RCTText: 1b3aafa95d0b8f5546ea8b11f218b97a6c50e6ac
|
||||||
React-RCTVibration: 415d77ace6572495a7fabc0013794eb232263f61
|
React-RCTVibration: b4b8c7ca82031b6a628d5197db32123786269f83
|
||||||
React-rendererconsistency: abd0c952e6447de1851995630d388adb756c5490
|
React-rendererconsistency: abd0c952e6447de1851995630d388adb756c5490
|
||||||
React-rendererdebug: 931afa3e69cad5617d70fc8d22a51b8f0b8962ab
|
React-rendererdebug: d2cee4431aae3b94a369922950314bdd11ed4e36
|
||||||
React-rncore: 4fa27b1f5758f1e43daecaca33828b6724ff975e
|
React-rncore: 4fa27b1f5758f1e43daecaca33828b6724ff975e
|
||||||
React-RuntimeApple: bc87436ff646bc38b3b40b5c1b64b3292083b5d6
|
React-RuntimeApple: 4400921398bc7f37dea96b38408f75fa79a4e087
|
||||||
React-RuntimeCore: 4588a5b4bf68324088d3aba640c7aecda1f8ccf7
|
React-RuntimeCore: f5d8891ca6c8fd0ea1ce97e1e742f674c6e3f3de
|
||||||
React-runtimeexecutor: 369f2c0dd457ecc25d8aca20717b8b7c655fea30
|
React-runtimeexecutor: 369f2c0dd457ecc25d8aca20717b8b7c655fea30
|
||||||
React-RuntimeHermes: fa0dbe3e215052f6f2a64961a81292a7d8a29cc1
|
React-RuntimeHermes: f36d89a2b787488c5c52b56f6e390ea6daad8177
|
||||||
React-runtimescheduler: 0c3791a76e2c851a6c0387549f6288cb9dd6e3d6
|
React-runtimescheduler: d767ba9dbcc56926ef8e33d9a79ffc73b1f21216
|
||||||
React-timing: d1b4d886b3ad54cb7d7902551d6f326de16b13d3
|
React-timing: d1b4d886b3ad54cb7d7902551d6f326de16b13d3
|
||||||
React-utils: 5b35e0df4b1e5414ccb7aad3295de9e422d19265
|
React-utils: b5263797499f58d23f8cdf84a43947fa935144a5
|
||||||
ReactCodegen: 64ba3fd7eb98692015dbd29ca0ca38ea2c5f92c6
|
ReactCodegen: be823df68a7af474545f249dab02cd94893917e8
|
||||||
ReactCommon: 8676c2ee5eb8c937ea33df7c91f42d4cd9e95e79
|
ReactCommon: ccfca2ddb61b208d3a9bfbbfc87233656d65a4d8
|
||||||
RNCPicker: f963e01f78e546a93b98aa201501713dbda14e94
|
RNCPicker: 0e683a85cae99a8a739e97a49f269a4630de0a01
|
||||||
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
||||||
Yoga: aaa386a35c44b356306dafca9e8afd81877fb7ed
|
Yoga: 748384d41d07db337d313e0f37eec81c8c0ae46f
|
||||||
|
|
||||||
PODFILE CHECKSUM: 90d803972b4acfc1d2bb6dbe7b0713677a2ff655
|
PODFILE CHECKSUM: 90d803972b4acfc1d2bb6dbe7b0713677a2ff655
|
||||||
|
|
||||||
COCOAPODS: 1.15.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
struct AdParams {
|
public struct AdParams {
|
||||||
let adTagUrl: String?
|
let adTagUrl: String?
|
||||||
let adLanguage: String?
|
let adLanguage: String?
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
struct CustomMetadata {
|
public struct CustomMetadata {
|
||||||
let title: String?
|
let title: String?
|
||||||
let subtitle: String?
|
let subtitle: String?
|
||||||
let artist: String?
|
let artist: String?
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import AVFoundation
|
||||||
|
|
||||||
|
// MARK: - OverridePlayerAssetType
|
||||||
|
|
||||||
|
public enum OverridePlayerAssetType {
|
||||||
|
// Return partially modified asset, that will go through the default prepare process
|
||||||
|
case partial
|
||||||
|
// Return fully modified asset, that will skip the default prepare process
|
||||||
|
case full
|
||||||
|
}
|
||||||
|
|
||||||
|
public typealias OverridePlayerAsset = (VideoSource, AVAsset) async -> OverridePlayerAssetResult
|
||||||
|
|
||||||
|
// MARK: - OverridePlayerAssetResult
|
||||||
|
|
||||||
|
public struct OverridePlayerAssetResult {
|
||||||
|
public let type: OverridePlayerAssetType
|
||||||
|
public let asset: AVAsset
|
||||||
|
|
||||||
|
public init(type: OverridePlayerAssetType, asset: AVAsset) {
|
||||||
|
self.type = type
|
||||||
|
self.asset = asset
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
struct TextTrack {
|
public struct TextTrack {
|
||||||
let type: String
|
let type: String
|
||||||
let language: String
|
let language: String
|
||||||
let title: String
|
let title: String
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
struct VideoSource {
|
public struct VideoSource {
|
||||||
let type: String?
|
let type: String?
|
||||||
let uri: String?
|
let uri: String?
|
||||||
let isNetwork: Bool
|
let isNetwork: Bool
|
||||||
|
|||||||
@@ -493,7 +493,19 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
])
|
])
|
||||||
|
|
||||||
if let uri = source.uri, uri.starts(with: "ph://") {
|
if let uri = source.uri, uri.starts(with: "ph://") {
|
||||||
let photoAsset = await RCTVideoUtils.preparePHAsset(uri: uri)
|
guard let photoAsset = await RCTVideoUtils.preparePHAsset(uri: uri) else {
|
||||||
|
DebugLog("Could not load asset '\(String(describing: _source))'")
|
||||||
|
throw NSError(domain: "", code: 0, userInfo: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let overridePlayerAsset = await ReactNativeVideoManager.shared.overridePlayerAsset(source: source, asset: photoAsset) {
|
||||||
|
if overridePlayerAsset.type == .full {
|
||||||
|
return AVPlayerItem(asset: overridePlayerAsset.asset)
|
||||||
|
}
|
||||||
|
|
||||||
|
return await playerItemPrepareText(source: source, asset: overridePlayerAsset.asset, assetOptions: nil, uri: source.uri ?? "")
|
||||||
|
}
|
||||||
|
|
||||||
return await playerItemPrepareText(source: source, asset: photoAsset, assetOptions: nil, uri: source.uri ?? "")
|
return await playerItemPrepareText(source: source, asset: photoAsset, assetOptions: nil, uri: source.uri ?? "")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,6 +542,14 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let overridePlayerAsset = await ReactNativeVideoManager.shared.overridePlayerAsset(source: source, asset: asset) {
|
||||||
|
if overridePlayerAsset.type == .full {
|
||||||
|
return AVPlayerItem(asset: overridePlayerAsset.asset)
|
||||||
|
}
|
||||||
|
|
||||||
|
return await playerItemPrepareText(source: source, asset: overridePlayerAsset.asset, assetOptions: assetOptions, uri: source.uri ?? "")
|
||||||
|
}
|
||||||
|
|
||||||
return await playerItemPrepareText(source: source, asset: asset, assetOptions: assetOptions, uri: source.uri ?? "")
|
return await playerItemPrepareText(source: source, asset: asset, assetOptions: assetOptions, uri: source.uri ?? "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ open class RNVAVPlayerPlugin: RNVPlugin {
|
|||||||
*/
|
*/
|
||||||
open func onInstanceRemoved(id _: String, player _: AVPlayer) { /* no-op */ }
|
open func onInstanceRemoved(id _: String, player _: AVPlayer) { /* no-op */ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called when creating a new AVPlayerItem
|
||||||
|
* @param source: The VideoSource describing the video (uri, type, headers, etc.)
|
||||||
|
* @param asset: The AVAsset prepared by the player
|
||||||
|
* @return: OverridePlayerAssetResult if you want to override, or nil if you don't
|
||||||
|
*/
|
||||||
|
open func overridePlayerAsset(source _: VideoSource, asset _: AVAsset) async -> OverridePlayerAssetResult? { nil }
|
||||||
|
|
||||||
// MARK: - RNVPlugin methods
|
// MARK: - RNVPlugin methods
|
||||||
|
|
||||||
override public func onInstanceCreated(id: String, player: Any) {
|
override public func onInstanceCreated(id: String, player: Any) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// react-native-video
|
// react-native-video
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import AVFoundation
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class ReactNativeVideoManager: RNVPlugin {
|
public class ReactNativeVideoManager: RNVPlugin {
|
||||||
@@ -67,6 +68,17 @@ public class ReactNativeVideoManager: RNVPlugin {
|
|||||||
return customDRMManager?.1 ?? DRMManager()
|
return customDRMManager?.1 ?? DRMManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func overridePlayerAsset(source: VideoSource, asset: AVAsset) async -> OverridePlayerAssetResult? {
|
||||||
|
for plugin in pluginList {
|
||||||
|
if let avpPlugin = plugin as? RNVAVPlayerPlugin,
|
||||||
|
let overridePlayerAsset = await avpPlugin.overridePlayerAsset(source: source, asset: asset) {
|
||||||
|
return overridePlayerAsset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Helper methods
|
// MARK: - Helper methods
|
||||||
|
|
||||||
func maybeRegisterAVPlayerPlugin(plugin: RNVPlugin) {
|
func maybeRegisterAVPlayerPlugin(plugin: RNVPlugin) {
|
||||||
|
|||||||
Reference in New Issue
Block a user