expo-video 55.0.4 → 55.0.6
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/CHANGELOG.md +23 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/video/FullscreenPlayerActivity.kt +6 -3
- package/android/src/main/java/expo/modules/video/PlayerViewExtension.kt +51 -0
- package/android/src/main/java/expo/modules/video/VideoCache.kt +5 -1
- package/android/src/main/java/expo/modules/video/VideoModule.kt +8 -5
- package/android/src/main/java/expo/modules/video/VideoView.kt +26 -4
- package/android/src/main/java/expo/modules/video/managers/VideoManager.kt +5 -3
- package/android/src/main/java/expo/modules/video/player/FirstFrameEventGenerator.kt +5 -7
- package/android/src/main/java/expo/modules/video/player/VideoPlayer.kt +31 -9
- package/android/src/main/java/expo/modules/video/records/ButtonOptions.kt +15 -0
- package/android/src/main/java/expo/modules/video/records/PlayerBuilderOptions.kt +13 -0
- package/build/VideoPlayer.d.ts +6 -4
- package/build/VideoPlayer.d.ts.map +1 -1
- package/build/VideoPlayer.js +9 -6
- package/build/VideoPlayer.js.map +1 -1
- package/build/VideoPlayer.types.d.ts +20 -1
- package/build/VideoPlayer.types.d.ts.map +1 -1
- package/build/VideoPlayer.types.js.map +1 -1
- package/build/VideoView.types.d.ts +61 -0
- package/build/VideoView.types.d.ts.map +1 -1
- package/build/VideoView.types.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js.map +1 -1
- package/expo-module.config.json +1 -1
- package/ios/Cache/CachedResource.swift +74 -7
- package/ios/Cache/CachingHelpers.swift +24 -9
- package/ios/Cache/MediaFileHandle.swift +54 -9
- package/ios/Cache/MediaInfo.swift +65 -22
- package/ios/Cache/ResourceLoaderDelegate.swift +38 -6
- package/ios/Cache/VideoCacheManager.swift +1 -1
- package/ios/NowPlayingManager.swift +2 -2
- package/ios/VideoAsset.swift +7 -7
- package/ios/VideoManager.swift +2 -2
- package/ios/VideoModule.swift +1 -1
- package/ios/VideoPlayerItem.swift +2 -2
- package/local-maven-repo/host/exp/exponent/expo.modules.video/{55.0.4/expo.modules.video-55.0.4-sources.jar → 55.0.6/expo.modules.video-55.0.6-sources.jar} +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6-sources.jar.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6-sources.jar.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6-sources.jar.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6-sources.jar.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.aar +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.aar.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.aar.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.aar.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.aar.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/{55.0.4/expo.modules.video-55.0.4.module → 55.0.6/expo.modules.video-55.0.6.module} +22 -22
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.module.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.module.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.module.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.module.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/{55.0.4/expo.modules.video-55.0.4.pom → 55.0.6/expo.modules.video-55.0.6.pom} +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.pom.md5 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.pom.sha1 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.pom.sha256 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.6/expo.modules.video-55.0.6.pom.sha512 +1 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml +4 -4
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.md5 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha1 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha256 +1 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha512 +1 -1
- package/package.json +2 -2
- package/src/VideoPlayer.tsx +14 -7
- package/src/VideoPlayer.types.ts +26 -1
- package/src/VideoView.types.ts +63 -0
- package/src/index.ts +6 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4-sources.jar.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4-sources.jar.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4-sources.jar.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4-sources.jar.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.aar +0 -0
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.aar.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.aar.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.aar.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.aar.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.module.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.module.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.module.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.module.sha512 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.pom.md5 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.pom.sha1 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.pom.sha256 +0 -1
- package/local-maven-repo/host/exp/exponent/expo.modules.video/55.0.4/expo.modules.video-55.0.4.pom.sha512 +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,29 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 55.0.6 — 2026-02-16
|
|
14
|
+
|
|
15
|
+
### 🛠 Breaking changes
|
|
16
|
+
|
|
17
|
+
- [Android] The next and previous buttons are now hidden by default in the native `VideoView` controls. ([#42875](https://github.com/expo/expo/pull/42875) by [@behenate](https://github.com/behenate))
|
|
18
|
+
|
|
19
|
+
### 🎉 New features
|
|
20
|
+
|
|
21
|
+
- [Android] Add `buttonConfiguration` prop to `VideoView`. ([#42875](https://github.com/expo/expo/pull/42875) by [@behenate](https://github.com/behenate))
|
|
22
|
+
- [Android] Add `PlayerBuilderOptions` parameter to `useVideoPlayer` hook to configure seek backward/forward increments. ([#43043](https://github.com/expo/expo/pull/43043) by [@behenate](https://github.com/behenate))
|
|
23
|
+
|
|
24
|
+
### 🐛 Bug fixes
|
|
25
|
+
|
|
26
|
+
- [Android] Fix only one player getting released when reloading with multiple players present. ([#42780](https://github.com/expo/expo/pull/42780) by [@behenate](https://github.com/behenate))
|
|
27
|
+
- [iOS] Fix data getting corrupted when caching is enabled. ([#42621](https://github.com/expo/expo/pull/42621) by [@behenate](https://github.com/behenate))
|
|
28
|
+
|
|
29
|
+
## 55.0.5 — 2026-02-08
|
|
30
|
+
|
|
31
|
+
### 🐛 Bug fixes
|
|
32
|
+
|
|
33
|
+
- [iOS] Prevents blocking main thread when loading asset tracks for non-HSL tracks ([#42037](https://github.com/expo/expo/pull/42037) by [@santitopo](https://github.com/santitopo))
|
|
34
|
+
- [Android] Fix crash due to `SimpleCache` directory lock conflicts. ([#42723](https://github.com/expo/expo/pull/42723) by [@santitopo](https://github.com/santitopo))
|
|
35
|
+
|
|
13
36
|
## 55.0.4 — 2026-02-03
|
|
14
37
|
|
|
15
38
|
### 🐛 Bug fixes
|
package/android/build.gradle
CHANGED
|
@@ -94,13 +94,16 @@ class FullscreenPlayerActivity : Activity() {
|
|
|
94
94
|
super.onPostCreate(savedInstanceState)
|
|
95
95
|
hideStatusBar()
|
|
96
96
|
setupFullscreenButton()
|
|
97
|
-
|
|
97
|
+
val requiresLinearPlayback = videoPlayer?.requiresLinearPlayback ?: false
|
|
98
|
+
val buttonConfig = videoView.buttonOptions.copy(showBottomBar = true) // Always show bottom bar in fullscreen mode so user can exit
|
|
99
|
+
playerView.applyButtonOptions(buttonConfig, requiresLinearPlayback)
|
|
100
|
+
playerView.setTimeBarInteractive(requiresLinearPlayback)
|
|
98
101
|
playerView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
|
|
99
102
|
// On every re-layout ExoPlayer makes the timeBar interactive.
|
|
100
103
|
// We need to disable it to keep scrubbing off.
|
|
101
|
-
playerView.setTimeBarInteractive(
|
|
104
|
+
playerView.setTimeBarInteractive(requiresLinearPlayback)
|
|
102
105
|
}
|
|
103
|
-
playerView.setShowSubtitleButton(videoView.
|
|
106
|
+
playerView.setShowSubtitleButton(videoView.buttonOptions.showSubtitles ?: videoView.currentTrackHasSubtitles)
|
|
104
107
|
|
|
105
108
|
// Configure subtitle view to fix sizing issues with embedded styles (same as VideoView)
|
|
106
109
|
SubtitleUtils.configureSubtitleView(playerView, this)
|
|
@@ -34,3 +34,54 @@ internal fun PlayerView.setFullscreenButtonVisibility(visible: Boolean) {
|
|
|
34
34
|
android.view.View.GONE
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
|
39
|
+
internal fun PlayerView.setSettingsButtonVisibility(visible: Boolean) {
|
|
40
|
+
val settingsButton = findViewById<android.widget.ImageButton>(androidx.media3.ui.R.id.exo_settings)
|
|
41
|
+
settingsButton?.visibility = if (visible) {
|
|
42
|
+
android.view.View.VISIBLE
|
|
43
|
+
} else {
|
|
44
|
+
android.view.View.GONE
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
|
49
|
+
internal fun PlayerView.setPlayPauseButtonVisibility(visible: Boolean) {
|
|
50
|
+
val playPauseButton = findViewById<android.widget.ImageButton>(androidx.media3.ui.R.id.exo_play_pause)
|
|
51
|
+
playPauseButton?.visibility = if (visible) {
|
|
52
|
+
android.view.View.VISIBLE
|
|
53
|
+
} else {
|
|
54
|
+
android.view.View.GONE
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
|
59
|
+
internal fun PlayerView.setBottomBarVisibility(visible: Boolean) {
|
|
60
|
+
val bottomBar = findViewById<android.view.ViewGroup>(androidx.media3.ui.R.id.exo_bottom_bar)
|
|
61
|
+
bottomBar?.visibility = if (visible) {
|
|
62
|
+
android.view.View.VISIBLE
|
|
63
|
+
} else {
|
|
64
|
+
android.view.View.GONE
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
val progressBar = findViewById<DefaultTimeBar>(androidx.media3.ui.R.id.exo_progress)
|
|
68
|
+
progressBar?.visibility = if (visible) {
|
|
69
|
+
android.view.View.VISIBLE
|
|
70
|
+
} else {
|
|
71
|
+
android.view.View.GONE
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
|
|
76
|
+
internal fun PlayerView.applyButtonOptions(
|
|
77
|
+
config: expo.modules.video.records.ButtonOptions,
|
|
78
|
+
requiresLinearPlayback: Boolean = false
|
|
79
|
+
) {
|
|
80
|
+
setShowFastForwardButton(!requiresLinearPlayback && config.showSeekForward)
|
|
81
|
+
setShowRewindButton(!requiresLinearPlayback && config.showSeekBackward)
|
|
82
|
+
setShowPreviousButton(!requiresLinearPlayback && config.showPrevious)
|
|
83
|
+
setShowNextButton(!requiresLinearPlayback && config.showNext)
|
|
84
|
+
setSettingsButtonVisibility(config.showSettings)
|
|
85
|
+
setPlayPauseButtonVisibility(config.showPlayPause)
|
|
86
|
+
setBottomBarVisibility(config.showBottomBar)
|
|
87
|
+
}
|
|
@@ -38,6 +38,10 @@ class VideoCache(context: Context) {
|
|
|
38
38
|
return sharedPreferences.getLong(CACHE_SIZE_KEY, DEFAULT_CACHE_SIZE)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
fun release() {
|
|
42
|
+
instance.release()
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
fun setMaxCacheSize(size: Long) {
|
|
42
46
|
assertModificationReleaseConditions()
|
|
43
47
|
instance.release()
|
|
@@ -55,7 +59,7 @@ class VideoCache(context: Context) {
|
|
|
55
59
|
// Weird structure, because kotlin marks the result of `getString` as nullable
|
|
56
60
|
val videoCacheDirName = sharedPreferences.getString(VIDEO_CACHE_DIR_KEY, null) ?: run {
|
|
57
61
|
val newCacheDirName = generateCacheDirName()
|
|
58
|
-
sharedPreferences.edit().putString(VIDEO_CACHE_DIR_KEY, newCacheDirName).
|
|
62
|
+
sharedPreferences.edit().putString(VIDEO_CACHE_DIR_KEY, newCacheDirName).commit()
|
|
59
63
|
newCacheDirName
|
|
60
64
|
}
|
|
61
65
|
val cacheParentDir = File(context.cacheDir, VIDEO_CACHE_PARENT_DIR)
|
|
@@ -19,6 +19,8 @@ import expo.modules.video.enums.AudioMixingMode
|
|
|
19
19
|
import expo.modules.video.enums.ContentFit
|
|
20
20
|
import expo.modules.video.player.VideoPlayer
|
|
21
21
|
import expo.modules.video.records.BufferOptions
|
|
22
|
+
import expo.modules.video.records.PlayerBuilderOptions
|
|
23
|
+
import expo.modules.video.records.ButtonOptions
|
|
22
24
|
import expo.modules.video.records.FullscreenOptions
|
|
23
25
|
import expo.modules.video.records.SubtitleTrack
|
|
24
26
|
import expo.modules.video.records.AudioTrack
|
|
@@ -72,8 +74,8 @@ class VideoModule : Module() {
|
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
Class(VideoPlayer::class) {
|
|
75
|
-
Constructor { source: VideoSource? ->
|
|
76
|
-
val player = VideoPlayer(appContext.throwingActivity.applicationContext, appContext, source)
|
|
77
|
+
Constructor { source: VideoSource?, /* useSynchronousReplace - iOS-only */ _: Boolean?, playerBuilderOptions: PlayerBuilderOptions? ->
|
|
78
|
+
val player = VideoPlayer(appContext.throwingActivity.applicationContext, appContext, source, playerBuilderOptions)
|
|
77
79
|
appContext.mainQueue.launch {
|
|
78
80
|
player.prepare()
|
|
79
81
|
}
|
|
@@ -410,9 +412,10 @@ private inline fun <reified T : VideoView> ViewDefinitionBuilder<T>.VideoViewCom
|
|
|
410
412
|
}
|
|
411
413
|
}
|
|
412
414
|
Prop("requiresLinearPlayback") { view: T, requiresLinearPlayback: Boolean? ->
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
415
|
+
view.requiresLinearPlayback = requiresLinearPlayback ?: false
|
|
416
|
+
}
|
|
417
|
+
Prop("buttonOptions") { view: T, buttonOptions: ButtonOptions? ->
|
|
418
|
+
view.buttonOptions = buttonOptions ?: ButtonOptions()
|
|
416
419
|
}
|
|
417
420
|
Prop("useExoShutter") { view: T, useExoShutter: Boolean? ->
|
|
418
421
|
view.useExoShutter = useExoShutter
|
|
@@ -26,6 +26,7 @@ import expo.modules.video.player.VideoPlayer
|
|
|
26
26
|
import expo.modules.video.listeners.VideoPlayerListener
|
|
27
27
|
import expo.modules.video.listeners.VideoViewListener
|
|
28
28
|
import expo.modules.video.records.AudioTrack
|
|
29
|
+
import expo.modules.video.records.ButtonOptions
|
|
29
30
|
import expo.modules.video.records.SubtitleTrack
|
|
30
31
|
import expo.modules.video.records.VideoSource
|
|
31
32
|
import expo.modules.video.records.VideoTrack
|
|
@@ -57,11 +58,25 @@ open class VideoView(context: Context, appContext: AppContext, useTextureView: B
|
|
|
57
58
|
var wasAutoPaused: Boolean = false
|
|
58
59
|
var isInFullscreen: Boolean = false
|
|
59
60
|
private set
|
|
60
|
-
var
|
|
61
|
+
var currentTrackHasSubtitles = false
|
|
61
62
|
private set
|
|
62
63
|
var showsAudioTracksButton = false
|
|
63
64
|
private set
|
|
64
65
|
|
|
66
|
+
var requiresLinearPlayback: Boolean = false
|
|
67
|
+
set(value) {
|
|
68
|
+
field = value
|
|
69
|
+
videoPlayer?.requiresLinearPlayback = value
|
|
70
|
+
playerView.applyRequiresLinearPlayback(value)
|
|
71
|
+
applyButtonSettings()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
var buttonOptions: ButtonOptions = ButtonOptions()
|
|
75
|
+
set(value) {
|
|
76
|
+
field = value
|
|
77
|
+
applyButtonSettings()
|
|
78
|
+
}
|
|
79
|
+
|
|
65
80
|
private var listeners = mutableListOf<WeakReference<VideoViewListener>>()
|
|
66
81
|
private val currentActivity = appContext.throwingActivity
|
|
67
82
|
private val decorView = currentActivity.window.decorView
|
|
@@ -131,8 +146,9 @@ open class VideoView(context: Context, appContext: AppContext, useTextureView: B
|
|
|
131
146
|
|
|
132
147
|
var useNativeControls: Boolean = true
|
|
133
148
|
set(value) {
|
|
149
|
+
val shouldShowSubtitle = value && (buttonOptions.showSubtitles ?: currentTrackHasSubtitles)
|
|
134
150
|
playerView.useController = value
|
|
135
|
-
playerView.setShowSubtitleButton(
|
|
151
|
+
playerView.setShowSubtitleButton(shouldShowSubtitle)
|
|
136
152
|
field = value
|
|
137
153
|
}
|
|
138
154
|
|
|
@@ -291,9 +307,9 @@ open class VideoView(context: Context, appContext: AppContext, useTextureView: B
|
|
|
291
307
|
}
|
|
292
308
|
|
|
293
309
|
override fun onTracksChanged(player: VideoPlayer, tracks: Tracks) {
|
|
294
|
-
|
|
310
|
+
currentTrackHasSubtitles = player.subtitles.availableSubtitleTracks.isNotEmpty()
|
|
295
311
|
showsAudioTracksButton = player.audioTracks.availableAudioTracks.size > 1
|
|
296
|
-
playerView.setShowSubtitleButton(
|
|
312
|
+
playerView.setShowSubtitleButton(buttonOptions.showSubtitles ?: currentTrackHasSubtitles)
|
|
297
313
|
super.onTracksChanged(player, tracks)
|
|
298
314
|
}
|
|
299
315
|
|
|
@@ -407,6 +423,12 @@ open class VideoView(context: Context, appContext: AppContext, useTextureView: B
|
|
|
407
423
|
}
|
|
408
424
|
}
|
|
409
425
|
|
|
426
|
+
private fun applyButtonSettings() {
|
|
427
|
+
val shouldShowSubtitle = buttonOptions.showSubtitles ?: currentTrackHasSubtitles
|
|
428
|
+
playerView.applyButtonOptions(buttonOptions, requiresLinearPlayback)
|
|
429
|
+
playerView.setShowSubtitleButton(shouldShowSubtitle)
|
|
430
|
+
}
|
|
431
|
+
|
|
410
432
|
companion object {
|
|
411
433
|
fun isPictureInPictureSupported(currentActivity: Activity): Boolean {
|
|
412
434
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && currentActivity.packageManager.hasSystemFeature(
|
|
@@ -34,18 +34,20 @@ object VideoManager {
|
|
|
34
34
|
|
|
35
35
|
private var listeners = mutableListOf<WeakReference<VideoManagerListener>>()
|
|
36
36
|
|
|
37
|
-
fun onModuleCreated(appContext: AppContext) {
|
|
37
|
+
fun onModuleCreated(appContext: AppContext) = synchronized(this) {
|
|
38
38
|
val context = appContext.reactContext ?: throw Exceptions.ReactContextLost()
|
|
39
|
-
this.appContext = WeakReference(appContext)
|
|
40
39
|
|
|
41
40
|
this.pictureInPicture = PictureInPictureManager(appContext)
|
|
42
|
-
|
|
43
41
|
if (!this::audioFocusManager.isInitialized) {
|
|
44
42
|
audioFocusManager = AudioFocusManager(appContext)
|
|
45
43
|
}
|
|
46
44
|
if (!this::cache.isInitialized) {
|
|
47
45
|
cache = VideoCache(context)
|
|
46
|
+
} else if (this.appContext.get()?.reactContext != appContext.reactContext) {
|
|
47
|
+
cache.release()
|
|
48
|
+
cache = VideoCache(context)
|
|
48
49
|
}
|
|
50
|
+
this.appContext = WeakReference(appContext)
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
fun onModuleDestroyed(appContext: AppContext) {
|
|
@@ -28,10 +28,9 @@ internal class FirstFrameEventGenerator(
|
|
|
28
28
|
appContext: AppContext,
|
|
29
29
|
videoPlayer: VideoPlayer,
|
|
30
30
|
private val currentViewReference: MutableWeakReference<VideoView?>,
|
|
31
|
-
private
|
|
31
|
+
private var onFirstFrameRendered: (() -> Unit)?
|
|
32
32
|
) : Player.Listener, VideoPlayerListener {
|
|
33
33
|
private val videoPlayerReference = WeakReference(videoPlayer)
|
|
34
|
-
private val weakAppContext = WeakReference(appContext)
|
|
35
34
|
private var hasPendingOnFirstFrame = false
|
|
36
35
|
internal var hasSentFirstFrameForCurrentMediaItem = false
|
|
37
36
|
private set
|
|
@@ -45,12 +44,11 @@ internal class FirstFrameEventGenerator(
|
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
|
|
47
|
+
@MainThread
|
|
48
48
|
fun release() {
|
|
49
49
|
videoPlayerReference.get()?.removeListener(this)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
videoPlayerReference.get()?.player?.removeListener(this@FirstFrameEventGenerator)
|
|
53
|
-
}
|
|
50
|
+
videoPlayerReference.get()?.player?.removeListener(this)
|
|
51
|
+
onFirstFrameRendered = null
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
override fun onRenderedFirstFrame() {
|
|
@@ -80,7 +78,7 @@ internal class FirstFrameEventGenerator(
|
|
|
80
78
|
// We want to match the behavior across platforms, so we limit the number of event emissions.
|
|
81
79
|
private fun maybeCallOnFirstFrameRendered() {
|
|
82
80
|
if (!hasSentFirstFrameForCurrentMediaItem || !hasSentFirstFrameForCurrentVideoView) {
|
|
83
|
-
onFirstFrameRendered()
|
|
81
|
+
onFirstFrameRendered?.invoke()
|
|
84
82
|
}
|
|
85
83
|
hasPendingOnFirstFrame = false
|
|
86
84
|
hasSentFirstFrameForCurrentMediaItem = true
|
|
@@ -47,13 +47,17 @@ import expo.modules.video.records.VideoSource
|
|
|
47
47
|
import expo.modules.video.utils.MutableWeakReference
|
|
48
48
|
import expo.modules.video.records.VideoTrack
|
|
49
49
|
import expo.modules.video.utils.buildBasicMediaSession
|
|
50
|
+
import kotlinx.coroutines.DelicateCoroutinesApi
|
|
51
|
+
import kotlinx.coroutines.Dispatchers
|
|
52
|
+
import kotlinx.coroutines.GlobalScope
|
|
50
53
|
import kotlinx.coroutines.launch
|
|
51
54
|
import java.io.FileInputStream
|
|
52
55
|
import java.lang.ref.WeakReference
|
|
56
|
+
import kotlin.time.DurationUnit
|
|
53
57
|
|
|
54
58
|
// https://developer.android.com/guide/topics/media/media3/getting-started/migration-guide#improvements_in_media3
|
|
55
59
|
@UnstableApi
|
|
56
|
-
class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSource?) : AutoCloseable, SharedObject(appContext), IntervalUpdateEmitter {
|
|
60
|
+
class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSource?, playerBuilderOptions: expo.modules.video.records.PlayerBuilderOptions? = null) : AutoCloseable, SharedObject(appContext), IntervalUpdateEmitter {
|
|
57
61
|
// This improves the performance of playing DRM-protected content
|
|
58
62
|
private var renderersFactory = DefaultRenderersFactory(context)
|
|
59
63
|
.forceEnableMediaCodecAsynchronousQueueing()
|
|
@@ -70,9 +74,16 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
|
|
|
70
74
|
|
|
71
75
|
val player = ExoPlayer
|
|
72
76
|
.Builder(context, renderersFactory)
|
|
73
|
-
.
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
.apply {
|
|
78
|
+
setLooper(context.mainLooper)
|
|
79
|
+
setLoadControl(loadControl)
|
|
80
|
+
playerBuilderOptions?.seekBackwardIncrement?.let {
|
|
81
|
+
setSeekBackIncrementMs((it).toLong(DurationUnit.MILLISECONDS).coerceIn(1, 999_000))
|
|
82
|
+
}
|
|
83
|
+
playerBuilderOptions?.seekForwardIncrement?.let {
|
|
84
|
+
setSeekForwardIncrementMs((it).toLong(DurationUnit.MILLISECONDS).coerceIn(1, 999_000))
|
|
85
|
+
}
|
|
86
|
+
}.build()
|
|
76
87
|
|
|
77
88
|
internal val firstFrameEventGenerator: FirstFrameEventGenerator
|
|
78
89
|
val serviceConnection = PlaybackServiceConnection(WeakReference(this), appContext)
|
|
@@ -346,7 +357,17 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
|
|
|
346
357
|
}
|
|
347
358
|
}
|
|
348
359
|
|
|
360
|
+
@kotlin.OptIn(DelicateCoroutinesApi::class)
|
|
349
361
|
override fun close() {
|
|
362
|
+
// Releases the listeners from VideoPlayerKeepAwake
|
|
363
|
+
keepScreenOnWhilePlaying = false
|
|
364
|
+
|
|
365
|
+
intervalUpdateClock.interval = 0L
|
|
366
|
+
|
|
367
|
+
synchronized(listeners) {
|
|
368
|
+
listeners.clear()
|
|
369
|
+
}
|
|
370
|
+
|
|
350
371
|
if (serviceConnection.isConnected) {
|
|
351
372
|
appContext?.reactContext?.unbindService(serviceConnection)
|
|
352
373
|
}
|
|
@@ -355,19 +376,20 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
|
|
|
355
376
|
|
|
356
377
|
VideoManager.unregisterVideoPlayer(this@VideoPlayer)
|
|
357
378
|
|
|
358
|
-
appContext
|
|
379
|
+
// Run on global scope (not appContext.mainQueue) so that reloading doesn't cancel the release process
|
|
380
|
+
// https://github.com/expo/expo/blob/cdf592a7fea56fc01b0149e9b2e5dbd294bcdc4c/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/AppContext.kt#L277-L279
|
|
381
|
+
GlobalScope.launch(Dispatchers.Main) {
|
|
359
382
|
firstFrameEventGenerator.release()
|
|
360
383
|
player.removeListener(playerListener)
|
|
384
|
+
player.removeAnalyticsListener(analyticsListener)
|
|
361
385
|
player.release()
|
|
362
386
|
}
|
|
363
387
|
uncommittedSource = null
|
|
364
388
|
commitedSource = null
|
|
365
|
-
// Releases the listeners from VideoPlayerKeepAwake
|
|
366
|
-
keepScreenOnWhilePlaying = false
|
|
367
389
|
}
|
|
368
390
|
|
|
369
|
-
override fun
|
|
370
|
-
super.
|
|
391
|
+
override fun sharedObjectDidRelease() {
|
|
392
|
+
super.sharedObjectDidRelease()
|
|
371
393
|
close()
|
|
372
394
|
}
|
|
373
395
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package expo.modules.video.records
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.records.Field
|
|
4
|
+
import expo.modules.kotlin.records.Record
|
|
5
|
+
|
|
6
|
+
data class ButtonOptions(
|
|
7
|
+
@Field val showNext: Boolean = false,
|
|
8
|
+
@Field val showPrevious: Boolean = false,
|
|
9
|
+
@Field val showSeekForward: Boolean = true,
|
|
10
|
+
@Field val showSeekBackward: Boolean = true,
|
|
11
|
+
@Field val showSubtitles: Boolean? = null,
|
|
12
|
+
@Field val showSettings: Boolean = true,
|
|
13
|
+
@Field val showPlayPause: Boolean = true,
|
|
14
|
+
@Field val showBottomBar: Boolean = true
|
|
15
|
+
) : Record
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package expo.modules.video.records
|
|
2
|
+
|
|
3
|
+
import androidx.media3.common.util.UnstableApi
|
|
4
|
+
import expo.modules.kotlin.records.Field
|
|
5
|
+
import expo.modules.kotlin.records.Record
|
|
6
|
+
import java.io.Serializable
|
|
7
|
+
import kotlin.time.Duration
|
|
8
|
+
|
|
9
|
+
@UnstableApi
|
|
10
|
+
class PlayerBuilderOptions(
|
|
11
|
+
@Field var seekBackwardIncrement: Duration? = null,
|
|
12
|
+
@Field var seekForwardIncrement: Duration? = null
|
|
13
|
+
) : Record, Serializable
|
package/build/VideoPlayer.d.ts
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { VideoSource, VideoPlayer } from './VideoPlayer.types';
|
|
1
|
+
import { VideoSource, VideoPlayer, PlayerBuilderOptions } from './VideoPlayer.types';
|
|
2
2
|
/**
|
|
3
3
|
* Creates a direct instance of `VideoPlayer` that doesn't release automatically.
|
|
4
4
|
*
|
|
5
5
|
* > **info** For most use cases you should use the [`useVideoPlayer`](#usevideoplayer) hook instead. See the [Using the VideoPlayer Directly](#using-the-videoplayer-directly) section for more details.
|
|
6
|
-
* @param source
|
|
6
|
+
* @param source - A video source that is used to initialize the player.
|
|
7
|
+
* @param playerBuilderOptions - Options to apply to the Android player builder before the native constructor is invoked.
|
|
7
8
|
*/
|
|
8
|
-
export declare function createVideoPlayer(source: VideoSource): VideoPlayer;
|
|
9
|
+
export declare function createVideoPlayer(source: VideoSource, playerBuilderOptions?: PlayerBuilderOptions): VideoPlayer;
|
|
9
10
|
/**
|
|
10
11
|
* Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.
|
|
11
12
|
* @param source - A video source that is used to initialize the player.
|
|
12
13
|
* @param setup - A function that allows setting up the player. It will run after the player is created.
|
|
14
|
+
* @param playerBuilderOptions - Options to apply to the Android player builder before the native constructor is invoked.
|
|
13
15
|
*/
|
|
14
|
-
export declare function useVideoPlayer(source: VideoSource, setup?: (player: VideoPlayer) => void): VideoPlayer;
|
|
16
|
+
export declare function useVideoPlayer(source: VideoSource, setup?: (player: VideoPlayer) => void, playerBuilderOptions?: PlayerBuilderOptions): VideoPlayer;
|
|
15
17
|
//# sourceMappingURL=VideoPlayer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAsBrF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,oBAAoB,CAAC,EAAE,oBAAoB,GAC1C,WAAW,CAGb;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,EACrC,oBAAoB,CAAC,EAAE,oBAAoB,GAC1C,WAAW,CAQb"}
|
package/build/VideoPlayer.js
CHANGED
|
@@ -17,23 +17,26 @@ NativeVideoModule.VideoPlayer.prototype.replaceAsync = function (source) {
|
|
|
17
17
|
* Creates a direct instance of `VideoPlayer` that doesn't release automatically.
|
|
18
18
|
*
|
|
19
19
|
* > **info** For most use cases you should use the [`useVideoPlayer`](#usevideoplayer) hook instead. See the [Using the VideoPlayer Directly](#using-the-videoplayer-directly) section for more details.
|
|
20
|
-
* @param source
|
|
20
|
+
* @param source - A video source that is used to initialize the player.
|
|
21
|
+
* @param playerBuilderOptions - Options to apply to the Android player builder before the native constructor is invoked.
|
|
21
22
|
*/
|
|
22
|
-
export function createVideoPlayer(source) {
|
|
23
|
-
|
|
23
|
+
export function createVideoPlayer(source, playerBuilderOptions) {
|
|
24
|
+
const parsedSource = parseSource(source);
|
|
25
|
+
return new NativeVideoModule.VideoPlayer(parsedSource, false, playerBuilderOptions);
|
|
24
26
|
}
|
|
25
27
|
/**
|
|
26
28
|
* Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.
|
|
27
29
|
* @param source - A video source that is used to initialize the player.
|
|
28
30
|
* @param setup - A function that allows setting up the player. It will run after the player is created.
|
|
31
|
+
* @param playerBuilderOptions - Options to apply to the Android player builder before the native constructor is invoked.
|
|
29
32
|
*/
|
|
30
|
-
export function useVideoPlayer(source, setup) {
|
|
33
|
+
export function useVideoPlayer(source, setup, playerBuilderOptions) {
|
|
31
34
|
const parsedSource = parseSource(source);
|
|
32
35
|
return useReleasingSharedObject(() => {
|
|
33
|
-
const player = new NativeVideoModule.VideoPlayer(parsedSource);
|
|
36
|
+
const player = new NativeVideoModule.VideoPlayer(parsedSource, false, playerBuilderOptions);
|
|
34
37
|
setup?.(player);
|
|
35
38
|
return player;
|
|
36
|
-
}, [JSON.stringify(parsedSource)]);
|
|
39
|
+
}, [JSON.stringify(parsedSource), JSON.stringify(playerBuilderOptions)]);
|
|
37
40
|
}
|
|
38
41
|
function parseSource(source) {
|
|
39
42
|
if (typeof source === 'number') {
|
package/build/VideoPlayer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayer.js","sourceRoot":"","sources":["../src/VideoPlayer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AAEpD,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AAEtD,4HAA4H;AAC5H,MAAM,OAAO,GAAG,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC;AAChE,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,GAAG,UAChD,MAAmB,EACnB,iBAA0B,KAAK;IAE/B,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CACV,mNAAmN,CACpN,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,YAAY,CAAC;AAC1E,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,YAAY,GAAG,UAAU,MAAmB;IAClF,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACtD,CAAC,CAAC;AACF
|
|
1
|
+
{"version":3,"file":"VideoPlayer.js","sourceRoot":"","sources":["../src/VideoPlayer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AAEpD,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AAEtD,4HAA4H;AAC5H,MAAM,OAAO,GAAG,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC;AAChE,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,GAAG,UAChD,MAAmB,EACnB,iBAA0B,KAAK;IAE/B,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CACV,mNAAmN,CACpN,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,YAAY,CAAC;AAC1E,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC,YAAY,GAAG,UAAU,MAAmB;IAClF,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACtD,CAAC,CAAC;AACF;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAmB,EACnB,oBAA2C;IAE3C,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO,IAAI,iBAAiB,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC;AACtF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAmB,EACnB,KAAqC,EACrC,oBAA2C;IAE3C,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAEzC,OAAO,wBAAwB,CAAC,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,EAAE,oBAAoB,CAAC,CAAC;QAC5F,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC;QAChB,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,WAAW,CAAC,MAAmB;IACtC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,4EAA4E;QAC5E,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,MAAM,CAAE,CAAC,GAAG,EAAE,CAAC;IAClD,CAAC;SAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACzB,CAAC;IAED,IAAI,OAAO,MAAM,EAAE,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QACvD,4EAA4E;QAC5E,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAE,CAAC,GAAG,EAAE,CAAC;IACrE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { useReleasingSharedObject } from 'expo-modules-core';\n\nimport NativeVideoModule from './NativeVideoModule';\nimport { VideoSource, VideoPlayer, PlayerBuilderOptions } from './VideoPlayer.types';\nimport resolveAssetSource from './resolveAssetSource';\n\n// TODO: Temporary solution until we develop a way of overriding prototypes that won't break the lazy loading of the module.\nconst replace = NativeVideoModule.VideoPlayer.prototype.replace;\nNativeVideoModule.VideoPlayer.prototype.replace = function (\n source: VideoSource,\n disableWarning: boolean = false\n) {\n if (!disableWarning) {\n console.warn(\n 'On iOS `VideoPlayer.replace` loads the asset data synchronously on the main thread, which can lead to UI freezes and will be deprecated in a future release. Switch to `replaceAsync` for better user experience.'\n );\n }\n\n return replace.call(this, parseSource(source));\n};\n\nconst replaceAsync = NativeVideoModule.VideoPlayer.prototype.replaceAsync;\nNativeVideoModule.VideoPlayer.prototype.replaceAsync = function (source: VideoSource) {\n return replaceAsync.call(this, parseSource(source));\n};\n/**\n * Creates a direct instance of `VideoPlayer` that doesn't release automatically.\n *\n * > **info** For most use cases you should use the [`useVideoPlayer`](#usevideoplayer) hook instead. See the [Using the VideoPlayer Directly](#using-the-videoplayer-directly) section for more details.\n * @param source - A video source that is used to initialize the player.\n * @param playerBuilderOptions - Options to apply to the Android player builder before the native constructor is invoked.\n */\nexport function createVideoPlayer(\n source: VideoSource,\n playerBuilderOptions?: PlayerBuilderOptions\n): VideoPlayer {\n const parsedSource = parseSource(source);\n return new NativeVideoModule.VideoPlayer(parsedSource, false, playerBuilderOptions);\n}\n\n/**\n * Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.\n * @param source - A video source that is used to initialize the player.\n * @param setup - A function that allows setting up the player. It will run after the player is created.\n * @param playerBuilderOptions - Options to apply to the Android player builder before the native constructor is invoked.\n */\nexport function useVideoPlayer(\n source: VideoSource,\n setup?: (player: VideoPlayer) => void,\n playerBuilderOptions?: PlayerBuilderOptions\n): VideoPlayer {\n const parsedSource = parseSource(source);\n\n return useReleasingSharedObject(() => {\n const player = new NativeVideoModule.VideoPlayer(parsedSource, false, playerBuilderOptions);\n setup?.(player);\n return player;\n }, [JSON.stringify(parsedSource), JSON.stringify(playerBuilderOptions)]);\n}\n\nfunction parseSource(source: VideoSource): VideoSource {\n if (typeof source === 'number') {\n // TODO(@kitten): This seems to not handle the `null` case. Is this correct?\n return { uri: resolveAssetSource(source)!.uri };\n } else if (typeof source === 'string') {\n return { uri: source };\n }\n\n if (typeof source?.assetId === 'number' && !source.uri) {\n // TODO(@kitten): This seems to not handle the `null` case. Is this correct?\n return { ...source, uri: resolveAssetSource(source.assetId)!.uri };\n }\n return source;\n}\n"]}
|
|
@@ -223,9 +223,10 @@ export declare class VideoPlayer extends SharedObject<VideoPlayerEvents> {
|
|
|
223
223
|
*
|
|
224
224
|
* @param source The source of the video to be played.
|
|
225
225
|
* @param useSynchronousReplace Optional parameter, when `true` `source` from the first parameter will be loaded on the main thread.
|
|
226
|
+
* @param playerBuilderOptions Options to apply to the player builder before the native constructor is invoked.
|
|
226
227
|
* @hidden
|
|
227
228
|
*/
|
|
228
|
-
constructor(source: VideoSource, useSynchronousReplace?: boolean);
|
|
229
|
+
constructor(source: VideoSource, useSynchronousReplace?: boolean, playerBuilderOptions?: PlayerBuilderOptions);
|
|
229
230
|
/**
|
|
230
231
|
* Resumes the player.
|
|
231
232
|
*/
|
|
@@ -656,4 +657,22 @@ export type ScrubbingModeOptions = {
|
|
|
656
657
|
*/
|
|
657
658
|
allowSkippingMediaCodecFlush?: boolean;
|
|
658
659
|
};
|
|
660
|
+
/**
|
|
661
|
+
* Options to apply to the player builder before the native constructor is invoked
|
|
662
|
+
* @platform android
|
|
663
|
+
*/
|
|
664
|
+
export type PlayerBuilderOptions = {
|
|
665
|
+
/**
|
|
666
|
+
* Seek backward increment in seconds.
|
|
667
|
+
* Values will be clamped between 0.001 and 999 seconds.
|
|
668
|
+
* @platform android
|
|
669
|
+
*/
|
|
670
|
+
seekBackwardIncrement?: number;
|
|
671
|
+
/**
|
|
672
|
+
* Seek forward increment in seconds.
|
|
673
|
+
* Values will be clamped between 0.001 and 999 seconds.
|
|
674
|
+
* @platform android
|
|
675
|
+
*/
|
|
676
|
+
seekForwardIncrement?: number;
|
|
677
|
+
};
|
|
659
678
|
//# sourceMappingURL=VideoPlayer.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayer.types.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,YAAY,CAAC,iBAAiB,CAAC;IACtE;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd;;;;OAIG;IACH,sBAAsB,EAAE,OAAO,CAAC;IAEhC;;;;;;OAMG;IACH,eAAe,EAAE,eAAe,CAAC;IAEjC;;;;OAIG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;;;;;;;OAQG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;;;;OAMG;IACH,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7C;;;;;OAKG;IACH,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9C;;;OAGG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;IAExB;;;;;OAKG;IACH,uBAAuB,EAAE,MAAM,CAAC;IAEhC;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;;;;OAQG;IACH,wBAAwB,EAAE,OAAO,CAAC;IAElC;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEnC;;;;;;;;OAQG;IACH,0BAA0B,EAAE,OAAO,CAAC;IAEpC;;;;;;;;OAQG;IACH,uBAAuB,EAAE,OAAO,CAAC;IAEjC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC;;;;;;OAMG;IACH,aAAa,EAAE,aAAa,CAAC;IAE7B;;;;;;;;OAQG;IACH,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAEpC;;;;;;OAMG;IACH,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAE9B;;;;;OAKG;IACH,QAAQ,CAAC,oBAAoB,EAAE,UAAU,EAAE,CAAC;IAE5C;;;;;OAKG;IACH,QAAQ,CAAC,uBAAuB,EAAE,aAAa,EAAE,CAAC;IAElD;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAEvC;;;;;;;OAOG;IACH,QAAQ,CAAC,oBAAoB,EAAE,UAAU,EAAE,CAAC;IAE5C;;;;OAIG;IACH,QAAQ,CAAC,wBAAwB,EAAE,OAAO,CAAC;IAE3C;;;;;;;;OAQG;IACH,aAAa,EAAE,aAAa,CAAC;IAE7B;;;;;OAKG;IACH,oBAAoB,EAAE,oBAAoB,CAAC;IAE3C
|
|
1
|
+
{"version":3,"file":"VideoPlayer.types.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.types.ts"],"names":[],"mappings":"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"}
|