expo-video 2.1.9 → 2.2.1

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 (67) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/video/VideoModule.kt +21 -1
  4. package/android/src/main/java/expo/modules/video/VideoView.kt +7 -4
  5. package/android/src/main/java/expo/modules/video/player/FirstFrameEventGenerator.kt +3 -2
  6. package/android/src/main/java/expo/modules/video/player/PlayerEvent.kt +20 -2
  7. package/android/src/main/java/expo/modules/video/player/VideoPlayer.kt +16 -1
  8. package/android/src/main/java/expo/modules/video/player/VideoPlayerAudioTracks.kt +125 -0
  9. package/android/src/main/java/expo/modules/video/records/Tracks.kt +21 -0
  10. package/android/src/main/java/expo/modules/video/records/VideoEventPayloads.kt +12 -1
  11. package/build/VideoPlayer.types.d.ts +30 -0
  12. package/build/VideoPlayer.types.d.ts.map +1 -1
  13. package/build/VideoPlayer.types.js.map +1 -1
  14. package/build/VideoPlayer.web.d.ts +3 -1
  15. package/build/VideoPlayer.web.d.ts.map +1 -1
  16. package/build/VideoPlayer.web.js +2 -0
  17. package/build/VideoPlayer.web.js.map +1 -1
  18. package/build/VideoPlayerEvents.types.d.ts +34 -1
  19. package/build/VideoPlayerEvents.types.d.ts.map +1 -1
  20. package/build/VideoPlayerEvents.types.js.map +1 -1
  21. package/build/VideoView.types.d.ts +1 -1
  22. package/build/VideoView.types.d.ts.map +1 -1
  23. package/build/VideoView.types.js.map +1 -1
  24. package/build/index.d.ts +1 -1
  25. package/build/index.d.ts.map +1 -1
  26. package/build/index.js.map +1 -1
  27. package/expo-module.config.json +7 -1
  28. package/ios/Records/Tracks.swift +13 -0
  29. package/ios/Records/VideoEventPayloads.swift +11 -0
  30. package/ios/VideoModule.swift +11 -0
  31. package/ios/VideoPlayer.swift +21 -2
  32. package/ios/VideoPlayerAudioTracks.swift +72 -0
  33. package/ios/VideoPlayerItem.swift +3 -1
  34. package/ios/VideoPlayerObserver.swift +89 -22
  35. package/ios/VideoSourceLoader.swift +44 -8
  36. package/ios/VideoSourceLoaderListener.swift +34 -0
  37. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar +0 -0
  38. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar.md5 +1 -0
  39. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar.sha1 +1 -0
  40. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar.sha256 +1 -0
  41. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar.sha512 +1 -0
  42. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar +0 -0
  43. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar.md5 +1 -0
  44. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar.sha1 +1 -0
  45. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar.sha256 +1 -0
  46. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar.sha512 +1 -0
  47. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module +147 -0
  48. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module.md5 +1 -0
  49. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module.sha1 +1 -0
  50. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module.sha256 +1 -0
  51. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module.sha512 +1 -0
  52. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom +88 -0
  53. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom.md5 +1 -0
  54. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom.sha1 +1 -0
  55. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom.sha256 +1 -0
  56. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom.sha512 +1 -0
  57. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml +13 -0
  58. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.md5 +1 -0
  59. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha1 +1 -0
  60. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha256 +1 -0
  61. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha512 +1 -0
  62. package/package.json +2 -2
  63. package/src/VideoPlayer.types.ts +35 -0
  64. package/src/VideoPlayer.web.tsx +3 -0
  65. package/src/VideoPlayerEvents.types.ts +40 -0
  66. package/src/VideoView.types.ts +2 -1
  67. package/src/index.ts +1 -0
@@ -24,6 +24,7 @@ protocol VideoPlayerObserverDelegate: AnyObject {
24
24
  func onTimeUpdate(player: AVPlayer, timeUpdate: TimeUpdate)
25
25
  func onAudioMixingModeChanged(player: AVPlayer, oldAudioMixingMode: AudioMixingMode, newAudioMixingMode: AudioMixingMode)
26
26
  func onSubtitleSelectionChanged(player: AVPlayer, playerItem: AVPlayerItem?, subtitleTrack: SubtitleTrack?)
27
+ func onAudioTrackSelectionChanged(player: AVPlayer, playerItem: AVPlayerItem?, audioTrack: AudioTrack?)
27
28
  func onLoadedPlayerItem(player: AVPlayer, playerItem: AVPlayerItem?)
28
29
  func onVideoTrackChanged(player: AVPlayer, oldVideoTrack: VideoTrack?, newVideoTrack: VideoTrack?)
29
30
  }
@@ -41,6 +42,7 @@ extension VideoPlayerObserverDelegate {
41
42
  func onTimeUpdate(player: AVPlayer, timeUpdate: TimeUpdate) {}
42
43
  func onAudioMixingModeChanged(player: AVPlayer, oldAudioMixingMode: AudioMixingMode, newAudioMixingMode: AudioMixingMode) {}
43
44
  func onSubtitleSelectionChanged(player: AVPlayer, playerItem: AVPlayerItem?, subtitleTrack: SubtitleTrack?) {}
45
+ func onAudioTrackSelectionChanged(player: AVPlayer, playerItem: AVPlayerItem?, audioTrack: AudioTrack?) {}
44
46
  func onLoadedPlayerItem(player: AVPlayer, playerItem: AVPlayerItem?) {}
45
47
  func onVideoTrackChanged(player: AVPlayer, oldVideoTrack: VideoTrack?, newVideoTrack: VideoTrack?) {}
46
48
  }
@@ -67,13 +69,15 @@ final class WeakPlayerObserverDelegate: Hashable {
67
69
  }
68
70
  }
69
71
 
70
- class VideoPlayerObserver {
72
+ class VideoPlayerObserver: VideoSourceLoaderListener {
71
73
  private weak var owner: VideoPlayer?
74
+ private weak var videoSourceLoader: VideoSourceLoader?
72
75
  var player: AVPlayer? {
73
76
  owner?.ref
74
77
  }
75
78
  var delegates = Set<WeakPlayerObserverDelegate>()
76
79
  private var currentItem: VideoPlayerItem?
80
+ private var isLoadingAsynchronously = false
77
81
  private var loadedCurrentItem = false
78
82
  private var periodicTimeObserver: Any?
79
83
  private var currentVideoTrack: VideoTrack? {
@@ -96,11 +100,21 @@ class VideoPlayerObserver {
96
100
  }
97
101
  }
98
102
  private var error: Exception?
99
- private var status: PlayerStatus = .idle {
100
- didSet {
101
- if let player, oldValue != status {
103
+ private var _status: PlayerStatus = .idle
104
+ private var status: PlayerStatus {
105
+ get {
106
+ return _status
107
+ }
108
+ set {
109
+ if newValue != .loading && isLoadingAsynchronously {
110
+ return
111
+ }
112
+
113
+ if let player, newValue != status {
114
+ let oldStatus = self._status
115
+ _status = newValue
102
116
  delegates.forEach { delegate in
103
- delegate.value?.onStatusChanged(player: player, oldStatus: oldValue, newStatus: status, error: error)
117
+ delegate.value?.onStatusChanged(player: player, oldStatus: oldStatus, newStatus: status, error: error)
104
118
  }
105
119
  }
106
120
  }
@@ -123,10 +137,13 @@ class VideoPlayerObserver {
123
137
  private var playerItemStatusObserver: NSKeyValueObservation?
124
138
  private var playbackLikelyToKeepUpObserver: NSKeyValueObservation?
125
139
  private var currentSubtitlesObserver: NSObjectProtocol?
140
+ private var currentAudioTracksObserver: NSObjectProtocol?
126
141
 
127
- init(owner: VideoPlayer) {
142
+ init(owner: VideoPlayer, videoSourceLoader: VideoSourceLoader) {
128
143
  self.owner = owner
144
+ self.videoSourceLoader = videoSourceLoader
129
145
  initializePlayerObservers()
146
+ self.videoSourceLoader?.registerListener(listener: self)
130
147
  }
131
148
 
132
149
  deinit {
@@ -143,6 +160,7 @@ class VideoPlayerObserver {
143
160
  }
144
161
 
145
162
  func cleanup() {
163
+ self.videoSourceLoader?.unregisterListener(listener: self)
146
164
  delegates.removeAll()
147
165
  invalidatePlayerObservers()
148
166
  invalidateCurrentPlayerItemObservers()
@@ -241,6 +259,17 @@ class VideoPlayerObserver {
241
259
  delegate.value?.onSubtitleSelectionChanged(player: player, playerItem: playerItem, subtitleTrack: subtitleTrack)
242
260
  }
243
261
  }
262
+
263
+ currentAudioTracksObserver = NotificationCenter.default.addObserver(
264
+ forName: AVPlayerItem.mediaSelectionDidChangeNotification,
265
+ object: playerItem,
266
+ queue: nil
267
+ ) { [weak self] _ in
268
+ self?.delegates.forEach { delegate in
269
+ let audioTrack = VideoPlayerAudioTracks.findCurrentAudioTrack(for: playerItem)
270
+ delegate.value?.onAudioTrackSelectionChanged(player: player, playerItem: playerItem, audioTrack: audioTrack)
271
+ }
272
+ }
244
273
  }
245
274
 
246
275
  private func invalidateCurrentPlayerItemObservers() {
@@ -250,6 +279,7 @@ class VideoPlayerObserver {
250
279
  tracksObserver?.invalidate()
251
280
  NotificationCenter.default.removeObserver(playerItemObserver as Any)
252
281
  NotificationCenter.default.removeObserver(currentSubtitlesObserver as Any)
282
+ NotificationCenter.default.removeObserver(currentAudioTracksObserver as Any)
253
283
  }
254
284
 
255
285
  func startOrUpdateTimeUpdates(forInterval interval: Double) {
@@ -332,24 +362,18 @@ class VideoPlayerObserver {
332
362
  if player?.status != .failed {
333
363
  error = nil
334
364
  }
335
-
336
- switch playerItem.status {
337
- case .unknown:
365
+ if owner?.videoSourceLoader.isLoading == true {
338
366
  status = .loading
339
- case .failed:
340
- // The AVPlayerItem.error can't be modified, so we have a custom field for caching errors
341
- let playerItemError = (playerItem as? VideoPlayerItem)?.urlAsset.cachingError ?? error
367
+ return
368
+ }
369
+
370
+ let newStatus = playerItem.status.toVideoPlayerStatus(isPlaybackBufferEmpty: playerItem.isPlaybackBufferEmpty)
371
+
372
+ // The AVPlayerItem.error can't be modified, so we have a custom field for caching errors
373
+ if newStatus == .error {
374
+ let playerItemError = (playerItem as? VideoPlayerItem)?.urlAsset.cachingError ?? playerItem.error ?? error
342
375
  error = PlayerItemLoadException(playerItemError?.localizedDescription)
343
376
  status = .error
344
- case .readyToPlay:
345
- if playerItem.isPlaybackBufferEmpty {
346
- status = .loading
347
- } else {
348
- status = .readyToPlay
349
- }
350
- @unknown default:
351
- log.error("Unhandled `AVPlayerItem.Status` value: \(playerItem.status), returning `.loading` as fallback. Add the missing case as soon as possible.")
352
- status = .loading
353
377
  }
354
378
 
355
379
  if let player, !loadedCurrentItem && (status == .readyToPlay || status == .error) {
@@ -385,7 +409,16 @@ class VideoPlayerObserver {
385
409
  if player.timeControlStatus != .waitingToPlayAtSpecifiedRate && player.status == .readyToPlay && currentItem?.isPlaybackBufferEmpty != true {
386
410
  status = .readyToPlay
387
411
  } else if player.timeControlStatus == .waitingToPlayAtSpecifiedRate {
388
- status = .loading
412
+ switch player.reasonForWaitingToPlay {
413
+ case .noItemToPlay:
414
+ status = .idle
415
+ case .evaluatingBufferingRate:
416
+ // Every time the player is unpaused timeControlStatus goes into .waitingToPlayAtSpecifiedRate while evaluating buffering rate.
417
+ // This takes less than a frame and we can ignore this change to avoid unnecessary status changes.
418
+ break
419
+ default:
420
+ status = .loading
421
+ }
389
422
  }
390
423
 
391
424
  if isPlaying != (player.timeControlStatus == .playing) {
@@ -430,6 +463,21 @@ class VideoPlayerObserver {
430
463
  }
431
464
  }
432
465
  }
466
+
467
+ // MARK: - VideoSourceLoaderListener
468
+ func onLoadingStarted(loader: VideoSourceLoader, videoSource: VideoSource?) {
469
+ isLoadingAsynchronously = true
470
+ status = .loading
471
+ }
472
+
473
+ func onLoadingCancelled(loader: VideoSourceLoader, videoSource: VideoSource?) {
474
+ isLoadingAsynchronously = false
475
+ status = .idle
476
+ }
477
+
478
+ func onLoadingFinished(loader: VideoSourceLoader, videoSource: VideoSource?, result: VideoPlayerItem?) {
479
+ isLoadingAsynchronously = false
480
+ }
433
481
  }
434
482
 
435
483
  private extension AVPlayerItemAccessLogEvent {
@@ -454,3 +502,22 @@ private extension AVPlayerItemAccessLogEvent {
454
502
  return videoTracks.first { $0.id == id }
455
503
  }
456
504
  }
505
+
506
+ fileprivate extension AVPlayerItem.Status {
507
+ func toVideoPlayerStatus(isPlaybackBufferEmpty: Bool) -> PlayerStatus {
508
+ switch self {
509
+ case .unknown:
510
+ return .loading
511
+ case .failed:
512
+ return .error
513
+ case .readyToPlay:
514
+ if isPlaybackBufferEmpty {
515
+ return .loading
516
+ }
517
+ return .readyToPlay
518
+ @unknown default:
519
+ log.error("Unhandled `AVPlayerItem.Status` value: \(self), returning `.loading` as fallback. Add the missing case as soon as possible.")
520
+ return .loading
521
+ }
522
+ }
523
+ }
@@ -2,7 +2,19 @@ import AVKit
2
2
 
3
3
  internal class VideoSourceLoader {
4
4
  private(set) var isLoading: Bool = true
5
- private var currentTask: Task<VideoPlayerItem?, Error>?
5
+ private var currentSource: VideoSource?
6
+ private var currentTask: Task<LoadingResult, Error>?
7
+
8
+ private var listeners = Set<WeakVideoSourceLoaderListener>()
9
+
10
+ func registerListener(listener: VideoSourceLoaderListener) {
11
+ let weakListener = WeakVideoSourceLoaderListener(value: listener)
12
+ listeners.insert(weakListener)
13
+ }
14
+
15
+ func unregisterListener(listener: VideoSourceLoaderListener) {
16
+ listeners.remove(WeakVideoSourceLoaderListener(value: listener))
17
+ }
6
18
 
7
19
  /**
8
20
  Asynchronously loads a video item from the provided `videoSource`. If another loading operation is in progress, it will be cancelled.
@@ -12,16 +24,31 @@ internal class VideoSourceLoader {
12
24
  */
13
25
  func load(videoSource: VideoSource) async throws -> VideoPlayerItem? {
14
26
  isLoading = true
15
- currentTask?.cancel()
27
+ if let currentTask {
28
+ currentTask.cancel()
29
+ listeners.forEach { listener in
30
+ listener.value?.onLoadingCancelled(loader: self, videoSource: currentSource)
31
+ }
32
+ }
16
33
 
17
34
  let newTask = Task {
18
35
  return try await loadImpl(videoSource: videoSource)
19
36
  }
20
37
 
21
38
  self.currentTask = newTask
22
- let result = try await newTask.value
39
+ self.currentSource = videoSource
40
+ let loadingResult = try await newTask.value
41
+
42
+ if !loadingResult.isCancelled {
43
+ listeners.forEach { listener in
44
+ listener.value?.onLoadingFinished(loader: self, videoSource: videoSource, result: loadingResult.value)
45
+ }
46
+ }
47
+
23
48
  isLoading = false
24
- return result
49
+ self.currentSource = nil
50
+ self.currentTask = nil
51
+ return loadingResult.value
25
52
  }
26
53
 
27
54
  func cancelCurrentTask() {
@@ -34,20 +61,29 @@ internal class VideoSourceLoader {
34
61
  cancelCurrentTask()
35
62
  }
36
63
 
37
- private func loadImpl(videoSource: VideoSource) async throws -> VideoPlayerItem? {
64
+ private func loadImpl(videoSource: VideoSource) async throws -> LoadingResult {
65
+ listeners.forEach { listener in
66
+ listener.value?.onLoadingStarted(loader: self, videoSource: videoSource)
67
+ }
68
+
38
69
  guard
39
70
  let url = videoSource.uri
40
71
  else {
41
- return nil
72
+ return LoadingResult(value: nil, isCancelled: false)
42
73
  }
43
74
 
44
75
  let playerItem = try await VideoPlayerItem(videoSource: videoSource)
45
76
 
46
77
  if Task.isCancelled {
47
78
  print("The loading task has been cancelled")
48
- return nil
79
+ return LoadingResult(value: nil, isCancelled: true)
49
80
  }
50
81
 
51
- return playerItem
82
+ return LoadingResult(value: playerItem, isCancelled: false)
52
83
  }
53
84
  }
85
+
86
+ private struct LoadingResult {
87
+ let value: VideoPlayerItem?
88
+ let isCancelled: Bool
89
+ }
@@ -0,0 +1,34 @@
1
+ import Foundation
2
+
3
+ protocol VideoSourceLoaderListener: AnyObject {
4
+ func onLoadingStarted(loader: VideoSourceLoader, videoSource: VideoSource?)
5
+ func onLoadingFinished(loader: VideoSourceLoader, videoSource: VideoSource?, result: VideoPlayerItem?)
6
+ func onLoadingCancelled(loader: VideoSourceLoader, videoSource: VideoSource?)
7
+ }
8
+
9
+ extension VideoSourceLoaderListener {
10
+ func onLoadingStarted(loader: VideoSourceLoader, videoSource: VideoSource?) {}
11
+ func onLoadingFinished(loader: VideoSourceLoader, videoSource: VideoSource?, result: VideoPlayerItem?) {}
12
+ func onLoadingCancelled(loader: VideoSourceLoader, videoSource: VideoSource?) {}
13
+ }
14
+
15
+ final class WeakVideoSourceLoaderListener: Hashable {
16
+ private(set) weak var value: VideoSourceLoaderListener?
17
+
18
+ init(value: VideoSourceLoaderListener? = nil) {
19
+ self.value = value
20
+ }
21
+
22
+ static func == (lhs: WeakVideoSourceLoaderListener, rhs: WeakVideoSourceLoaderListener) -> Bool {
23
+ guard let lhsValue = lhs.value, let rhsValue = rhs.value else {
24
+ return lhs.value == nil && rhs.value == nil
25
+ }
26
+ return ObjectIdentifier(lhsValue) == ObjectIdentifier(rhsValue)
27
+ }
28
+
29
+ func hash(into hasher: inout Hasher) {
30
+ if let value {
31
+ hasher.combine(ObjectIdentifier(value))
32
+ }
33
+ }
34
+ }
@@ -0,0 +1 @@
1
+ ff54e2221752092ebdece914b77e4504b2864fc94504c8a1887ea67a2afa5ea0
@@ -0,0 +1 @@
1
+ c7c374ab88183e831ed5a80a5e7a6f9ef2d29d4157c7b9496e30a9f87b14c4952b1e867b29f8feedbab21badccdf1b751f3a20367d1970a5e814311d96618f0e
@@ -0,0 +1 @@
1
+ 06203802abf1c39df7bef9bddb6cf7dda03e6300
@@ -0,0 +1 @@
1
+ 0022fab08b59c4346e67a4bf573af546f4f0e7eb322aee1115335e035318fa2c
@@ -0,0 +1 @@
1
+ a1501f7e947680eba85a049cf0520518bca4feca64832fbdc41383cb2c483f6253ecf8d429ad936966fcce1b0494175035399894dbce9c50f4765bd099edebf1
@@ -0,0 +1,147 @@
1
+ {
2
+ "formatVersion": "1.1",
3
+ "component": {
4
+ "group": "host.exp.exponent",
5
+ "module": "expo.modules.video",
6
+ "version": "2.2.1",
7
+ "attributes": {
8
+ "org.gradle.status": "release"
9
+ }
10
+ },
11
+ "createdBy": {
12
+ "gradle": {
13
+ "version": "8.13"
14
+ }
15
+ },
16
+ "variants": [
17
+ {
18
+ "name": "releaseVariantReleaseApiPublication",
19
+ "attributes": {
20
+ "org.gradle.category": "library",
21
+ "org.gradle.dependency.bundling": "external",
22
+ "org.gradle.libraryelements": "aar",
23
+ "org.gradle.usage": "java-api"
24
+ },
25
+ "files": [
26
+ {
27
+ "name": "expo.modules.video-2.2.1.aar",
28
+ "url": "expo.modules.video-2.2.1.aar",
29
+ "size": 444322,
30
+ "sha512": "a1501f7e947680eba85a049cf0520518bca4feca64832fbdc41383cb2c483f6253ecf8d429ad936966fcce1b0494175035399894dbce9c50f4765bd099edebf1",
31
+ "sha256": "0022fab08b59c4346e67a4bf573af546f4f0e7eb322aee1115335e035318fa2c",
32
+ "sha1": "06203802abf1c39df7bef9bddb6cf7dda03e6300",
33
+ "md5": "b87e04623a8bc68b39b0d628a278460d"
34
+ }
35
+ ]
36
+ },
37
+ {
38
+ "name": "releaseVariantReleaseRuntimePublication",
39
+ "attributes": {
40
+ "org.gradle.category": "library",
41
+ "org.gradle.dependency.bundling": "external",
42
+ "org.gradle.libraryelements": "aar",
43
+ "org.gradle.usage": "java-runtime"
44
+ },
45
+ "dependencies": [
46
+ {
47
+ "group": "org.jetbrains.kotlin",
48
+ "module": "kotlin-stdlib-jdk7",
49
+ "version": {
50
+ "requires": "2.0.21"
51
+ }
52
+ },
53
+ {
54
+ "group": "com.facebook.react",
55
+ "module": "react-android"
56
+ },
57
+ {
58
+ "group": "androidx.media3",
59
+ "module": "media3-session",
60
+ "version": {
61
+ "requires": "1.4.0"
62
+ }
63
+ },
64
+ {
65
+ "group": "androidx.media3",
66
+ "module": "media3-exoplayer",
67
+ "version": {
68
+ "requires": "1.4.0"
69
+ }
70
+ },
71
+ {
72
+ "group": "androidx.media3",
73
+ "module": "media3-exoplayer-dash",
74
+ "version": {
75
+ "requires": "1.4.0"
76
+ }
77
+ },
78
+ {
79
+ "group": "androidx.media3",
80
+ "module": "media3-exoplayer-hls",
81
+ "version": {
82
+ "requires": "1.4.0"
83
+ }
84
+ },
85
+ {
86
+ "group": "androidx.media3",
87
+ "module": "media3-ui",
88
+ "version": {
89
+ "requires": "1.4.0"
90
+ }
91
+ },
92
+ {
93
+ "group": "androidx.media3",
94
+ "module": "media3-datasource-okhttp",
95
+ "version": {
96
+ "requires": "1.4.0"
97
+ }
98
+ },
99
+ {
100
+ "group": "androidx.fragment",
101
+ "module": "fragment",
102
+ "version": {
103
+ "requires": "1.6.2"
104
+ }
105
+ },
106
+ {
107
+ "group": "androidx.fragment",
108
+ "module": "fragment-ktx",
109
+ "version": {
110
+ "requires": "1.6.2"
111
+ }
112
+ }
113
+ ],
114
+ "files": [
115
+ {
116
+ "name": "expo.modules.video-2.2.1.aar",
117
+ "url": "expo.modules.video-2.2.1.aar",
118
+ "size": 444322,
119
+ "sha512": "a1501f7e947680eba85a049cf0520518bca4feca64832fbdc41383cb2c483f6253ecf8d429ad936966fcce1b0494175035399894dbce9c50f4765bd099edebf1",
120
+ "sha256": "0022fab08b59c4346e67a4bf573af546f4f0e7eb322aee1115335e035318fa2c",
121
+ "sha1": "06203802abf1c39df7bef9bddb6cf7dda03e6300",
122
+ "md5": "b87e04623a8bc68b39b0d628a278460d"
123
+ }
124
+ ]
125
+ },
126
+ {
127
+ "name": "releaseVariantReleaseSourcePublication",
128
+ "attributes": {
129
+ "org.gradle.category": "documentation",
130
+ "org.gradle.dependency.bundling": "external",
131
+ "org.gradle.docstype": "sources",
132
+ "org.gradle.usage": "java-runtime"
133
+ },
134
+ "files": [
135
+ {
136
+ "name": "expo.modules.video-2.2.1-sources.jar",
137
+ "url": "expo.modules.video-2.2.1-sources.jar",
138
+ "size": 52499,
139
+ "sha512": "c7c374ab88183e831ed5a80a5e7a6f9ef2d29d4157c7b9496e30a9f87b14c4952b1e867b29f8feedbab21badccdf1b751f3a20367d1970a5e814311d96618f0e",
140
+ "sha256": "ff54e2221752092ebdece914b77e4504b2864fc94504c8a1887ea67a2afa5ea0",
141
+ "sha1": "f26b20423aa775f88468456856f576c24bc8149b",
142
+ "md5": "6e1f79fc8674bec45f35f95a4f8933f3"
143
+ }
144
+ ]
145
+ }
146
+ ]
147
+ }
@@ -0,0 +1 @@
1
+ 53814f15e51286b6229b601265835761f6c64266002c3216fb933fda817efbb2
@@ -0,0 +1 @@
1
+ 0954a801c43e9242b4db377ad2b306f55d0f85dea74e8cb11aa206ed7ff680d00ea98ed496496987c4ed87af271f01f16bfff9909ed713aec68321b9abb4704e
@@ -0,0 +1,88 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
3
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4
+ <!-- This module was also published with a richer model, Gradle metadata, -->
5
+ <!-- which should be used instead. Do not delete the following line which -->
6
+ <!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
7
+ <!-- that they should prefer consuming it instead. -->
8
+ <!-- do_not_remove: published-with-gradle-metadata -->
9
+ <modelVersion>4.0.0</modelVersion>
10
+ <groupId>host.exp.exponent</groupId>
11
+ <artifactId>expo.modules.video</artifactId>
12
+ <version>2.2.1</version>
13
+ <packaging>aar</packaging>
14
+ <name>expo.modules.video</name>
15
+ <url>https://github.com/expo/expo</url>
16
+ <licenses>
17
+ <license>
18
+ <name>MIT License</name>
19
+ <url>https://github.com/expo/expo/blob/main/LICENSE</url>
20
+ </license>
21
+ </licenses>
22
+ <scm>
23
+ <connection>https://github.com/expo/expo.git</connection>
24
+ <developerConnection>https://github.com/expo/expo.git</developerConnection>
25
+ <url>https://github.com/expo/expo</url>
26
+ </scm>
27
+ <dependencies>
28
+ <dependency>
29
+ <groupId>org.jetbrains.kotlin</groupId>
30
+ <artifactId>kotlin-stdlib-jdk7</artifactId>
31
+ <version>2.0.21</version>
32
+ <scope>runtime</scope>
33
+ </dependency>
34
+ <dependency>
35
+ <groupId>com.facebook.react</groupId>
36
+ <artifactId>react-android</artifactId>
37
+ <scope>runtime</scope>
38
+ </dependency>
39
+ <dependency>
40
+ <groupId>androidx.media3</groupId>
41
+ <artifactId>media3-session</artifactId>
42
+ <version>1.4.0</version>
43
+ <scope>runtime</scope>
44
+ </dependency>
45
+ <dependency>
46
+ <groupId>androidx.media3</groupId>
47
+ <artifactId>media3-exoplayer</artifactId>
48
+ <version>1.4.0</version>
49
+ <scope>runtime</scope>
50
+ </dependency>
51
+ <dependency>
52
+ <groupId>androidx.media3</groupId>
53
+ <artifactId>media3-exoplayer-dash</artifactId>
54
+ <version>1.4.0</version>
55
+ <scope>runtime</scope>
56
+ </dependency>
57
+ <dependency>
58
+ <groupId>androidx.media3</groupId>
59
+ <artifactId>media3-exoplayer-hls</artifactId>
60
+ <version>1.4.0</version>
61
+ <scope>runtime</scope>
62
+ </dependency>
63
+ <dependency>
64
+ <groupId>androidx.media3</groupId>
65
+ <artifactId>media3-ui</artifactId>
66
+ <version>1.4.0</version>
67
+ <scope>runtime</scope>
68
+ </dependency>
69
+ <dependency>
70
+ <groupId>androidx.media3</groupId>
71
+ <artifactId>media3-datasource-okhttp</artifactId>
72
+ <version>1.4.0</version>
73
+ <scope>runtime</scope>
74
+ </dependency>
75
+ <dependency>
76
+ <groupId>androidx.fragment</groupId>
77
+ <artifactId>fragment</artifactId>
78
+ <version>1.6.2</version>
79
+ <scope>runtime</scope>
80
+ </dependency>
81
+ <dependency>
82
+ <groupId>androidx.fragment</groupId>
83
+ <artifactId>fragment-ktx</artifactId>
84
+ <version>1.6.2</version>
85
+ <scope>runtime</scope>
86
+ </dependency>
87
+ </dependencies>
88
+ </project>
@@ -0,0 +1 @@
1
+ 0e372e48b5871a6a0626cd97273f6c85e835f4a9
@@ -0,0 +1 @@
1
+ b3296cfce3d47bb8a61f69e5faea5ce137f18fece4687b2e24310c974d0d97b5
@@ -0,0 +1 @@
1
+ bbd813cc4afc824a0160cbc648f16b3261b5f223cc78cd29135188337d54c7928cd90c7ec13e87991b7de47c4a4fab6b96e8db1775bcc503ade8fbf3ac036570
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <metadata>
3
+ <groupId>host.exp.exponent</groupId>
4
+ <artifactId>expo.modules.video</artifactId>
5
+ <versioning>
6
+ <latest>2.2.1</latest>
7
+ <release>2.2.1</release>
8
+ <versions>
9
+ <version>2.2.1</version>
10
+ </versions>
11
+ <lastUpdated>20250610113903</lastUpdated>
12
+ </versioning>
13
+ </metadata>
@@ -0,0 +1 @@
1
+ d175f56e996dbf7ca76d75bfe82c4d41
@@ -0,0 +1 @@
1
+ 1776813ac995e4f770f3461f9f4f7d125c03b710
@@ -0,0 +1 @@
1
+ 56169c737354e30bd868954cb30731441d9fceba388fcf1274f0ee5462378bb3
@@ -0,0 +1 @@
1
+ abde90e836a99c9272468d5749616b4e8cc162fb1d56fc7d4e7cc62e6233feaffb9e3cbd00c2d7f1af598756ace51c63b55e7b388552a93c5aaf8bed81786bf3
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "expo-video",
3
3
  "title": "Expo Video",
4
- "version": "2.1.9",
4
+ "version": "2.2.1",
5
5
  "description": "A cross-platform, performant video component for React Native and Expo with Web support",
6
6
  "main": "build/index.js",
7
7
  "types": "build/index.d.ts",
@@ -38,5 +38,5 @@
38
38
  "react": "*",
39
39
  "react-native": "*"
40
40
  },
41
- "gitHead": "49c9d53cf0a9fc8179d1c8f5268beadd141f70ca"
41
+ "gitHead": "d0b4f7c27a356e8c53bfe45db39fff9e96906a2e"
42
42
  }