expo-video 57.0.1 → 57.0.2

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 (43) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/android/build.gradle +2 -2
  3. package/expo-module.config.json +1 -1
  4. package/ios/Utils/RunOnMainThread.swift +11 -0
  5. package/ios/VideoPlayer.swift +45 -13
  6. package/ios/VideoPlayerObserver.swift +18 -13
  7. package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1.module → 57.0.2/expo.modules.video-57.0.2.module} +7 -7
  8. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.2/expo.modules.video-57.0.2.module.md5 +1 -0
  9. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.2/expo.modules.video-57.0.2.module.sha1 +1 -0
  10. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.2/expo.modules.video-57.0.2.module.sha256 +1 -0
  11. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.2/expo.modules.video-57.0.2.module.sha512 +1 -0
  12. package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1.pom → 57.0.2/expo.modules.video-57.0.2.pom} +1 -1
  13. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.2/expo.modules.video-57.0.2.pom.md5 +1 -0
  14. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.2/expo.modules.video-57.0.2.pom.sha1 +1 -0
  15. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.2/expo.modules.video-57.0.2.pom.sha256 +1 -0
  16. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.2/expo.modules.video-57.0.2.pom.sha512 +1 -0
  17. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml +4 -4
  18. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.md5 +1 -1
  19. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha1 +1 -1
  20. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha256 +1 -1
  21. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha512 +1 -1
  22. package/package.json +3 -3
  23. package/plugin/tsconfig.tsbuildinfo +1 -1
  24. package/prebuilds/output/debug/xcframeworks/ExpoVideo.tar.gz +0 -0
  25. package/prebuilds/output/release/xcframeworks/ExpoVideo.tar.gz +0 -0
  26. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.1/expo.modules.video-57.0.1.module.md5 +0 -1
  27. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.1/expo.modules.video-57.0.1.module.sha1 +0 -1
  28. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.1/expo.modules.video-57.0.1.module.sha256 +0 -1
  29. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.1/expo.modules.video-57.0.1.module.sha512 +0 -1
  30. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.1/expo.modules.video-57.0.1.pom.md5 +0 -1
  31. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.1/expo.modules.video-57.0.1.pom.sha1 +0 -1
  32. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.1/expo.modules.video-57.0.1.pom.sha256 +0 -1
  33. package/local-maven-repo/host/exp/exponent/expo.modules.video/57.0.1/expo.modules.video-57.0.1.pom.sha512 +0 -1
  34. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1-sources.jar → 57.0.2/expo.modules.video-57.0.2-sources.jar} +0 -0
  35. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1-sources.jar.md5 → 57.0.2/expo.modules.video-57.0.2-sources.jar.md5} +0 -0
  36. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1-sources.jar.sha1 → 57.0.2/expo.modules.video-57.0.2-sources.jar.sha1} +0 -0
  37. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1-sources.jar.sha256 → 57.0.2/expo.modules.video-57.0.2-sources.jar.sha256} +0 -0
  38. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1-sources.jar.sha512 → 57.0.2/expo.modules.video-57.0.2-sources.jar.sha512} +0 -0
  39. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1.aar → 57.0.2/expo.modules.video-57.0.2.aar} +0 -0
  40. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1.aar.md5 → 57.0.2/expo.modules.video-57.0.2.aar.md5} +0 -0
  41. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1.aar.sha1 → 57.0.2/expo.modules.video-57.0.2.aar.sha1} +0 -0
  42. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1.aar.sha256 → 57.0.2/expo.modules.video-57.0.2.aar.sha256} +0 -0
  43. /package/local-maven-repo/host/exp/exponent/expo.modules.video/{57.0.1/expo.modules.video-57.0.1.aar.sha512 → 57.0.2/expo.modules.video-57.0.2.aar.sha512} +0 -0
package/CHANGELOG.md CHANGED
@@ -10,6 +10,13 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 57.0.2 — 2026-07-22
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - [iOS] Fix a race when registering video player observer delegates. ([#47976](https://github.com/expo/expo/pull/47976) by [@behenate](https://github.com/behenate))
18
+ - [iOS] Update the way the VideoPlayer releases to comply with the modified SharedObject lifecycle. ([#47828](https://github.com/expo/expo/pull/47828) by [@behenate](https://github.com/behenate))
19
+
13
20
  ## 57.0.1 — 2026-07-15
14
21
 
15
22
  _This version does not introduce any user-facing changes._
@@ -4,13 +4,13 @@ plugins {
4
4
  }
5
5
 
6
6
  group = 'host.exp.exponent'
7
- version = '57.0.1'
7
+ version = '57.0.2'
8
8
 
9
9
  android {
10
10
  namespace "expo.modules.video"
11
11
  defaultConfig {
12
12
  versionCode 1
13
- versionName '57.0.1'
13
+ versionName '57.0.2'
14
14
  }
15
15
  }
16
16
 
@@ -8,7 +8,7 @@
8
8
  "publication": {
9
9
  "groupId": "host.exp.exponent",
10
10
  "artifactId": "expo.modules.video",
11
- "version": "57.0.1",
11
+ "version": "57.0.2",
12
12
  "repository": "local-maven-repo"
13
13
  }
14
14
  }
@@ -0,0 +1,11 @@
1
+ // Copyright 2026-present 650 Industries. All rights reserved.
2
+
3
+ import Foundation
4
+
5
+ internal func runOnMainThread(_ operation: @escaping () -> Void) {
6
+ if Thread.isMainThread {
7
+ operation()
8
+ } else {
9
+ DispatchQueue.main.async(execute: operation)
10
+ }
11
+ }
@@ -13,6 +13,7 @@ internal final class VideoPlayer: SharedRef<AVPlayer>, Hashable, VideoPlayerObse
13
13
  lazy var audioTracks: VideoPlayerAudioTracks = VideoPlayerAudioTracks(owner: self)
14
14
  lazy var seeker: VideoPlayerSeeker = VideoPlayerSeeker(player: self)
15
15
  private var tracksLoadingTask: Task<(), Never>?
16
+ private let didRelease = Mutex(false)
16
17
 
17
18
  var loop = false
18
19
  var audioMixingMode: AudioMixingMode = .doNotMix {
@@ -181,18 +182,14 @@ internal final class VideoPlayer: SharedRef<AVPlayer>, Hashable, VideoPlayerObse
181
182
  }
182
183
 
183
184
  deinit {
184
- observer?.cleanup()
185
- NowPlayingManager.shared.unregisterPlayer(self)
186
- VideoManager.shared.unregister(videoPlayer: self)
187
-
188
- videoSourceLoader.cancelCurrentTask()
189
- tracksLoadingTask?.cancel()
185
+ releasePlayer()
186
+ }
190
187
 
191
- // We have to replace from the main thread because of KVOs (see comment in VideoSourceLoader).
192
- // Moreover, in this case we have to keep a strong reference to AVPlayer and remove its item
193
- // If we don't do this AVPlayer doesn't get deallocated
194
- DispatchQueue.main.async { [ref] in
195
- ref.replaceCurrentItem(with: nil)
188
+ override func sharedObjectWillRelease() {
189
+ // Strong self capture is intentional: it keeps the player alive until the teardown
190
+ // has run on the main thread, so `deinit` can never race with it.
191
+ runOnMainThread {
192
+ self.releasePlayer()
196
193
  }
197
194
  }
198
195
 
@@ -224,7 +221,7 @@ internal final class VideoPlayer: SharedRef<AVPlayer>, Hashable, VideoPlayerObse
224
221
  // sometimes the KVOs will try to deliver updates after the item has been changed or player deallocated,
225
222
  // which causes crashes.
226
223
  DispatchQueue.main.async { [weak self] in
227
- guard let self else {
224
+ guard let self, !self.hasBeenReleased else {
228
225
  return
229
226
  }
230
227
  self.ref.replaceCurrentItem(with: playerItem)
@@ -261,7 +258,7 @@ internal final class VideoPlayer: SharedRef<AVPlayer>, Hashable, VideoPlayerObse
261
258
  // sometimes the KVOs will try to deliver updates after the item has been changed or player deallocated,
262
259
  // which causes crashes.
263
260
  DispatchQueue.main.async { [weak self] in
264
- guard let self else {
261
+ guard let self, !self.hasBeenReleased else {
265
262
  return
266
263
  }
267
264
  self.ref.replaceCurrentItem(with: playerItem)
@@ -322,6 +319,38 @@ internal final class VideoPlayer: SharedRef<AVPlayer>, Hashable, VideoPlayerObse
322
319
  return
323
320
  }
324
321
 
322
+ private func releasePlayer() {
323
+ let alreadyReleased = didRelease.withLock { didRelease in
324
+ defer {
325
+ didRelease = true
326
+ }
327
+ return didRelease
328
+ }
329
+ guard !alreadyReleased else {
330
+ return
331
+ }
332
+
333
+ observer?.cleanup()
334
+ observer = nil
335
+ NowPlayingManager.shared.unregisterPlayer(self)
336
+ VideoManager.shared.unregister(videoPlayer: self)
337
+
338
+ videoSourceLoader.cancelCurrentTask()
339
+ tracksLoadingTask?.cancel()
340
+
341
+ // We have to replace from the main thread because of KVOs (see comment in VideoSourceLoader).
342
+ // Moreover, in this case we have to keep a strong reference to AVPlayer and remove its item
343
+ // If we don't do this AVPlayer doesn't get deallocated
344
+ runOnMainThread { [ref] in
345
+ ref.pause()
346
+ ref.replaceCurrentItem(with: nil)
347
+ }
348
+ }
349
+
350
+ private var hasBeenReleased: Bool {
351
+ return didRelease.withLock { $0 }
352
+ }
353
+
325
354
  private func getBufferedPosition() -> Double {
326
355
  guard let currentItem = ref.currentItem else {
327
356
  return -1
@@ -398,6 +427,9 @@ internal final class VideoPlayer: SharedRef<AVPlayer>, Hashable, VideoPlayerObse
398
427
  }
399
428
 
400
429
  func onLoadedPlayerItem(player: AVPlayer, playerItem: AVPlayerItem?) {
430
+ guard !hasBeenReleased else {
431
+ return
432
+ }
401
433
  // Loading tracks requires doing some long tasks, this callback can be called from the main thread
402
434
  // Which could cause hangs
403
435
  tracksLoadingTask?.cancel()
@@ -80,25 +80,22 @@ extension VideoPlayerObserverDelegate {
80
80
  func onIsExternalPlaybackActiveChanged(player: AVPlayer, oldIsExternalPlaybackActive: Bool?, newIsExternalPlaybackActive: Bool) {}
81
81
  }
82
82
 
83
- // Wrapper used to store WeakReferences to the observer delegate
83
+ // Wrapper used to store WeakReferences to the observer delegate.
84
84
  final class WeakPlayerObserverDelegate: Hashable {
85
85
  private(set) weak var value: VideoPlayerObserverDelegate?
86
+ private let id: ObjectIdentifier
86
87
 
87
- init(value: VideoPlayerObserverDelegate? = nil) {
88
+ init(value: VideoPlayerObserverDelegate) {
88
89
  self.value = value
90
+ self.id = ObjectIdentifier(value)
89
91
  }
90
92
 
91
93
  static func == (lhs: WeakPlayerObserverDelegate, rhs: WeakPlayerObserverDelegate) -> Bool {
92
- guard let lhsValue = lhs.value, let rhsValue = rhs.value else {
93
- return lhs.value == nil && rhs.value == nil
94
- }
95
- return ObjectIdentifier(lhsValue) == ObjectIdentifier(rhsValue)
94
+ return lhs.id == rhs.id
96
95
  }
97
96
 
98
97
  func hash(into hasher: inout Hasher) {
99
- if let value {
100
- hasher.combine(ObjectIdentifier(value))
101
- }
98
+ hasher.combine(id)
102
99
  }
103
100
  }
104
101
 
@@ -110,7 +107,10 @@ class VideoPlayerObserver: VideoSourceLoaderListener {
110
107
  var player: AVPlayer? {
111
108
  owner?.ref
112
109
  }
113
- var delegates = Set<WeakPlayerObserverDelegate>()
110
+ private let delegatesStore = Mutex(Set<WeakPlayerObserverDelegate>())
111
+ var delegates: Set<WeakPlayerObserverDelegate> {
112
+ delegatesStore.withLock { $0 }
113
+ }
114
114
  private var currentItem: VideoPlayerItem?
115
115
  private var isLoadingAsynchronously = false
116
116
  private var loadedCurrentItem = false
@@ -203,16 +203,21 @@ class VideoPlayerObserver: VideoSourceLoaderListener {
203
203
 
204
204
  func registerDelegate(delegate: VideoPlayerObserverDelegate) {
205
205
  let weakDelegate = WeakPlayerObserverDelegate(value: delegate)
206
- delegates.insert(weakDelegate)
206
+ delegatesStore.withLock { delegates in
207
+ delegates = delegates.filter { $0.value != nil }
208
+ delegates.insert(weakDelegate)
209
+ }
207
210
  }
208
211
 
209
212
  func unregisterDelegate(delegate: VideoPlayerObserverDelegate) {
210
- delegates.remove(WeakPlayerObserverDelegate(value: delegate))
213
+ delegatesStore.withLock { delegates in
214
+ delegates.remove(WeakPlayerObserverDelegate(value: delegate))
215
+ }
211
216
  }
212
217
 
213
218
  func cleanup() {
214
219
  self.videoSourceLoader?.unregisterListener(listener: self)
215
- delegates.removeAll()
220
+ delegatesStore.withLock { $0.removeAll() }
216
221
  invalidatePlayerObservers()
217
222
  invalidateCurrentPlayerItemObservers()
218
223
  stopTimeUpdates()
@@ -3,7 +3,7 @@
3
3
  "component": {
4
4
  "group": "host.exp.exponent",
5
5
  "module": "expo.modules.video",
6
- "version": "57.0.1",
6
+ "version": "57.0.2",
7
7
  "attributes": {
8
8
  "org.gradle.status": "release"
9
9
  }
@@ -24,8 +24,8 @@
24
24
  },
25
25
  "files": [
26
26
  {
27
- "name": "expo.modules.video-57.0.1.aar",
28
- "url": "expo.modules.video-57.0.1.aar",
27
+ "name": "expo.modules.video-57.0.2.aar",
28
+ "url": "expo.modules.video-57.0.2.aar",
29
29
  "size": 618935,
30
30
  "sha512": "414333cf491f54d00eb9354836fb034f8d4884373ecf52fc552b9be5a4f1b0df376e52117b687f1fb653c4f985d4a227e1dbadac482abac881b0b65ebc633f2a",
31
31
  "sha256": "fa52e334dfab3a78de313226342de9f7aa80fe3b067f6a153b14f80b15399d3a",
@@ -127,8 +127,8 @@
127
127
  ],
128
128
  "files": [
129
129
  {
130
- "name": "expo.modules.video-57.0.1.aar",
131
- "url": "expo.modules.video-57.0.1.aar",
130
+ "name": "expo.modules.video-57.0.2.aar",
131
+ "url": "expo.modules.video-57.0.2.aar",
132
132
  "size": 618935,
133
133
  "sha512": "414333cf491f54d00eb9354836fb034f8d4884373ecf52fc552b9be5a4f1b0df376e52117b687f1fb653c4f985d4a227e1dbadac482abac881b0b65ebc633f2a",
134
134
  "sha256": "fa52e334dfab3a78de313226342de9f7aa80fe3b067f6a153b14f80b15399d3a",
@@ -147,8 +147,8 @@
147
147
  },
148
148
  "files": [
149
149
  {
150
- "name": "expo.modules.video-57.0.1-sources.jar",
151
- "url": "expo.modules.video-57.0.1-sources.jar",
150
+ "name": "expo.modules.video-57.0.2-sources.jar",
151
+ "url": "expo.modules.video-57.0.2-sources.jar",
152
152
  "size": 74869,
153
153
  "sha512": "2bbbb172455223c7c185bdbe9931bb6e7012443a2836fef262c86b8279d6ec1cc04fa159cef9e5d29f76971cbd32c3dba2e52d16f83b6ff5f3aec5bc5c3a4715",
154
154
  "sha256": "71ed9d27197bfcd8f718d4d9d49c1cfb14bc23d9abb69db8b58a573d4771a424",
@@ -0,0 +1 @@
1
+ 8c50fdd26a7fb0791676846b1585d81efe00028859aee92fa6bbf6c350de839f
@@ -0,0 +1 @@
1
+ 55b07f580463cad4b7b9501b26d2fe5bc5037437090bc05b48ffda3ebe2192f6a06acbc41ccf1960ab7dc3f3d0439f1f659538cd24a3a3b82488c0605fa65717
@@ -9,7 +9,7 @@
9
9
  <modelVersion>4.0.0</modelVersion>
10
10
  <groupId>host.exp.exponent</groupId>
11
11
  <artifactId>expo.modules.video</artifactId>
12
- <version>57.0.1</version>
12
+ <version>57.0.2</version>
13
13
  <packaging>aar</packaging>
14
14
  <name>expo.modules.video</name>
15
15
  <url>https://github.com/expo/expo</url>
@@ -0,0 +1 @@
1
+ 93e41a7be8f1414c3584501af5806681d7b041a6
@@ -0,0 +1 @@
1
+ 3d8cf55fd289529794e8010b4b30619621d2b75c4e7ff3323b6206873dd0cd92
@@ -0,0 +1 @@
1
+ c7a28d881bd4f0dcfa61134878a7fb6dfb809a95f377438a7b4147f4f25e59b381c2838505d493e8eeb6504feab77e8d2ce015b07a2e250c5c49dea6225fa279
@@ -3,11 +3,11 @@
3
3
  <groupId>host.exp.exponent</groupId>
4
4
  <artifactId>expo.modules.video</artifactId>
5
5
  <versioning>
6
- <latest>57.0.1</latest>
7
- <release>57.0.1</release>
6
+ <latest>57.0.2</latest>
7
+ <release>57.0.2</release>
8
8
  <versions>
9
- <version>57.0.1</version>
9
+ <version>57.0.2</version>
10
10
  </versions>
11
- <lastUpdated>20260715094902</lastUpdated>
11
+ <lastUpdated>20260722161447</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- 2e010c94832f3dbebbae55b2c03ea4c5
1
+ d3e3f170ab6217e1d60c5b48286768f0
@@ -1 +1 @@
1
- 779873f409a23c2757701faf13ca43cd848428c6
1
+ 5addbae4c84daa38b9e11cee4d5d57fad20e63f2
@@ -1 +1 @@
1
- 7dc9f70996598bc24ece1ec5f9ca71ec5297daf2cec75ec6bb3e02abbbb3d351
1
+ e4b8851c55e07994d432258e793e997e19be92cfef2a323dcc4914815c65668d
@@ -1 +1 @@
1
- 054f780a78b9fd92ba0a7179cb0383ca91fee4b387a80e90039c9e8cec13c741ce84860068cf6410479aedafee7c79a8ffc39b9dad0cd236502f152966c31ead
1
+ 8f0e9bfc0063f0dc5ad2fcd4876ca4cc56cec08763618f5fc38ee1a9defde7d56d0fc75eaf735a4834360cf6c22ba6acbdb654d260939dbdc3b30109a2a16180
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "expo-video",
3
3
  "title": "Expo Video",
4
- "version": "57.0.1",
4
+ "version": "57.0.2",
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",
@@ -24,7 +24,7 @@
24
24
  "devDependencies": {
25
25
  "@types/node": "^22.14.0",
26
26
  "@types/react": "~19.2.0",
27
- "expo": "57.0.6",
27
+ "expo": "57.0.8",
28
28
  "expo-module-scripts": "56.0.3"
29
29
  },
30
30
  "peerDependencies": {
@@ -32,7 +32,7 @@
32
32
  "react": "*",
33
33
  "react-native": "*"
34
34
  },
35
- "gitHead": "b9503d06b8e130abfca1bc16f671dbefb41ad709",
35
+ "gitHead": "a4789f1e53353f4929b0baddcfe5a7c622b99c71",
36
36
  "scripts": {
37
37
  "build": "expo-module build",
38
38
  "clean": "expo-module clean",
@@ -1 +1 @@
1
- {"root":["./src/index.ts","./src/withexpovideo.ts"],"version":"6.0.3"}
1
+ {"root":["./src/withexpovideo.ts"],"version":"5.9.2"}
@@ -1 +0,0 @@
1
- 1ff39b2c4e899b1445cd8d4581f61072cc805673
@@ -1 +0,0 @@
1
- 94343df0375f9f72efff232973f76fb7e9cb26cb77983432bf3e56f056284818
@@ -1 +0,0 @@
1
- 38fe83e1eb1bf7539254484785310451a737b952a107fd0d4a298fe34bfcb4cc3969a9932ba78247889163eba4e875f732e97a774024bffa8a3efe463d42ed8f
@@ -1 +0,0 @@
1
- 3b48874e79e4ca7baf2b8c126cebdea45cf6b493
@@ -1 +0,0 @@
1
- d145b227acbf604c6e9db92c6ea35e1ee3716d427b258a3b65b5ceac6c1b1819
@@ -1 +0,0 @@
1
- e4e1ae68b3d8fdc2be3a18b8b4cd408c3ea8fbb030c692635f9adb78948cc8a4054a3afe17b25fbf6bf1a1bfaf054126ee9b57716041b83edc2feaa36ced114a