expo-video 2.0.0-preview.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/video/VideoModule.kt +16 -0
- package/android/src/main/java/expo/modules/video/VideoView.kt +9 -21
- package/android/src/main/java/expo/modules/video/player/PlayerEvent.kt +25 -0
- package/android/src/main/java/expo/modules/video/player/VideoPlayer.kt +31 -0
- package/android/src/main/java/expo/modules/video/player/VideoPlayerListener.kt +2 -0
- package/android/src/main/java/expo/modules/video/player/VideoPlayerSubtitles.kt +125 -0
- package/android/src/main/java/expo/modules/video/records/SubtitleTrack.kt +28 -0
- package/android/src/main/java/expo/modules/video/records/VideoEventPayloads.kt +10 -0
- package/build/VideoPlayer.d.ts +8 -3
- package/build/VideoPlayer.d.ts.map +1 -1
- package/build/VideoPlayer.js +9 -1
- package/build/VideoPlayer.js.map +1 -1
- package/build/VideoPlayer.types.d.ts +33 -0
- package/build/VideoPlayer.types.d.ts.map +1 -1
- package/build/VideoPlayer.types.js.map +1 -1
- package/build/VideoPlayer.web.d.ts +4 -1
- package/build/VideoPlayer.web.d.ts.map +1 -1
- package/build/VideoPlayer.web.js +6 -0
- package/build/VideoPlayer.web.js.map +1 -1
- package/build/VideoPlayerEvents.types.d.ts +30 -1
- package/build/VideoPlayerEvents.types.d.ts.map +1 -1
- package/build/VideoPlayerEvents.types.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/ios/Records/SubtitleTrack.swift +21 -0
- package/ios/Records/VideoEventPayloads.swift +10 -0
- package/ios/VideoModule.swift +11 -0
- package/ios/VideoPlayer.swift +23 -0
- package/ios/VideoPlayerObserver.swift +35 -0
- package/ios/VideoPlayerSubtitles.swift +71 -0
- package/package.json +2 -2
- package/src/VideoPlayer.tsx +11 -3
- package/src/VideoPlayer.types.ts +38 -0
- package/src/VideoPlayer.web.tsx +9 -0
- package/src/VideoPlayerEvents.types.ts +35 -1
- package/src/index.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,11 +10,24 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 2.0.0 — 2024-11-11
|
|
14
|
+
|
|
15
|
+
### 💡 Others
|
|
16
|
+
|
|
17
|
+
- [Android] Modify aspect ratio coverage of Android PiP to be more specific ([#32551](https://github.com/expo/expo/pull/32551) by [@YangJonghun](https://github.com/YangJonghun))
|
|
18
|
+
|
|
19
|
+
## 2.0.0-preview.2 — 2024-11-07
|
|
20
|
+
|
|
21
|
+
### 🎉 New features
|
|
22
|
+
|
|
23
|
+
- [Android][iOS] Add support for listing and selecting closed captions. ([#32582](https://github.com/expo/expo/pull/32582) by [@behenate](https://github.com/behenate))
|
|
24
|
+
|
|
13
25
|
## 2.0.0-preview.1 — 2024-11-05
|
|
14
26
|
|
|
15
27
|
### 🎉 New features
|
|
16
28
|
|
|
17
29
|
- [Android][iOS] Add `audioMixingMode` property to control how the player interacts with other audio in the system. ([#32428](https://github.com/expo/expo/pull/32428) by [@behenate](https://github.com/behenate))
|
|
30
|
+
- Add support for creating a direct instance of `VideoPlayer`. ([#32228](https://github.com/expo/expo/pull/32228) by [@behenate](https://github.com/behenate))
|
|
18
31
|
|
|
19
32
|
### 🐛 Bug fixes
|
|
20
33
|
|
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'host.exp.exponent'
|
|
4
|
-
version = '2.0.0
|
|
4
|
+
version = '2.0.0'
|
|
5
5
|
|
|
6
6
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
7
|
apply from: expoModulesCorePlugin
|
|
@@ -14,7 +14,7 @@ android {
|
|
|
14
14
|
namespace "expo.modules.video"
|
|
15
15
|
defaultConfig {
|
|
16
16
|
versionCode 1
|
|
17
|
-
versionName '2.0.0
|
|
17
|
+
versionName '2.0.0'
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -20,6 +20,7 @@ import expo.modules.video.enums.AudioMixingMode
|
|
|
20
20
|
import expo.modules.video.enums.ContentFit
|
|
21
21
|
import expo.modules.video.player.VideoPlayer
|
|
22
22
|
import expo.modules.video.records.BufferOptions
|
|
23
|
+
import expo.modules.video.records.SubtitleTrack
|
|
23
24
|
import expo.modules.video.records.VideoSource
|
|
24
25
|
import expo.modules.video.utils.ifYogaDefinedUse
|
|
25
26
|
import expo.modules.video.utils.makeYogaUndefinedIfNegative
|
|
@@ -208,6 +209,21 @@ class VideoModule : Module() {
|
|
|
208
209
|
}
|
|
209
210
|
}
|
|
210
211
|
|
|
212
|
+
Property("availableSubtitleTracks")
|
|
213
|
+
.get { ref: VideoPlayer ->
|
|
214
|
+
ref.subtitles.availableSubtitleTracks
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
Property("subtitleTrack")
|
|
218
|
+
.get { ref: VideoPlayer ->
|
|
219
|
+
ref.subtitles.currentSubtitleTrack
|
|
220
|
+
}
|
|
221
|
+
.set { ref: VideoPlayer, subtitleTrack: SubtitleTrack? ->
|
|
222
|
+
appContext.mainQueue.launch {
|
|
223
|
+
ref.subtitles.currentSubtitleTrack = subtitleTrack
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
211
227
|
Property("currentOffsetFromLive")
|
|
212
228
|
.get { ref: VideoPlayer ->
|
|
213
229
|
runBlocking(appContext.mainQueue.coroutineContext) {
|
|
@@ -12,8 +12,6 @@ import android.view.ViewGroup
|
|
|
12
12
|
import android.widget.FrameLayout
|
|
13
13
|
import android.widget.ImageButton
|
|
14
14
|
import androidx.fragment.app.FragmentActivity
|
|
15
|
-
import androidx.media3.common.Format
|
|
16
|
-
import androidx.media3.common.MimeTypes
|
|
17
15
|
import androidx.media3.common.Tracks
|
|
18
16
|
import androidx.media3.ui.PlayerView
|
|
19
17
|
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
@@ -203,11 +201,14 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
|
|
|
203
201
|
} else {
|
|
204
202
|
Rational(width, height)
|
|
205
203
|
}
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
204
|
+
// AspectRatio for the activity in picture-in-picture, must be between 2.39:1 and 1:2.39 (inclusive).
|
|
205
|
+
// https://developer.android.com/reference/android/app/PictureInPictureParams.Builder#setAspectRatio(android.util.Rational)
|
|
206
|
+
val maximumRatio = Rational(239, 100)
|
|
207
|
+
val minimumRatio = Rational(100, 239)
|
|
208
|
+
if (aspectRatio.toFloat() > maximumRatio.toFloat()) {
|
|
209
|
+
aspectRatio = maximumRatio
|
|
210
|
+
} else if (aspectRatio.toFloat() < minimumRatio.toFloat()) {
|
|
211
|
+
aspectRatio = minimumRatio
|
|
211
212
|
}
|
|
212
213
|
|
|
213
214
|
currentActivity.setPictureInPictureParams(
|
|
@@ -254,24 +255,11 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
|
|
|
254
255
|
}
|
|
255
256
|
|
|
256
257
|
override fun onTracksChanged(player: VideoPlayer, tracks: Tracks) {
|
|
257
|
-
showsSubtitlesButton =
|
|
258
|
+
showsSubtitlesButton = player.subtitles.availableSubtitleTracks.isNotEmpty()
|
|
258
259
|
playerView.setShowSubtitleButton(showsSubtitlesButton)
|
|
259
260
|
super.onTracksChanged(player, tracks)
|
|
260
261
|
}
|
|
261
262
|
|
|
262
|
-
private fun hasSubtitles(tracks: Tracks): Boolean {
|
|
263
|
-
for (group in tracks.groups) {
|
|
264
|
-
for (i in 0..<group.length) {
|
|
265
|
-
val format: Format = group.getTrackFormat(i)
|
|
266
|
-
|
|
267
|
-
if (MimeTypes.isText(format.sampleMimeType)) {
|
|
268
|
-
return true
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return false
|
|
273
|
-
}
|
|
274
|
-
|
|
275
263
|
override fun requestLayout() {
|
|
276
264
|
super.requestLayout()
|
|
277
265
|
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
package expo.modules.video.player
|
|
2
2
|
|
|
3
3
|
import androidx.annotation.OptIn
|
|
4
|
+
import androidx.media3.common.TrackSelectionParameters
|
|
4
5
|
import androidx.media3.common.Tracks
|
|
5
6
|
import androidx.media3.common.util.UnstableApi
|
|
6
7
|
import expo.modules.video.enums.AudioMixingMode
|
|
7
8
|
import expo.modules.video.enums.PlayerStatus
|
|
9
|
+
import expo.modules.video.records.AvailableSubtitleTracksChangedEventPayload
|
|
8
10
|
import expo.modules.video.records.IsPlayingEventPayload
|
|
9
11
|
import expo.modules.video.records.MutedChangedEventPayload
|
|
10
12
|
import expo.modules.video.records.PlaybackError
|
|
11
13
|
import expo.modules.video.records.PlaybackRateChangedEventPayload
|
|
12
14
|
import expo.modules.video.records.SourceChangedEventPayload
|
|
13
15
|
import expo.modules.video.records.StatusChangedEventPayload
|
|
16
|
+
import expo.modules.video.records.SubtitleTrack
|
|
17
|
+
import expo.modules.video.records.SubtitleTrackChangedEventPayload
|
|
14
18
|
import expo.modules.video.records.TimeUpdate
|
|
15
19
|
import expo.modules.video.records.VideoEventPayload
|
|
16
20
|
import expo.modules.video.records.VideoSource
|
|
@@ -57,6 +61,24 @@ sealed class PlayerEvent {
|
|
|
57
61
|
override val emitToJS = false
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
data class TrackSelectionParametersChanged(val trackSelectionParameters: TrackSelectionParameters) : PlayerEvent() {
|
|
65
|
+
override val name = "trackSelectionParametersChange"
|
|
66
|
+
override val emitToJS = false
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
data class SubtitleTrackChanged(val subtitleTrack: SubtitleTrack?, val oldSubtitleTrack: SubtitleTrack?) : PlayerEvent() {
|
|
70
|
+
override val name = "subtitleTrackChange"
|
|
71
|
+
override val jsEventPayload = SubtitleTrackChangedEventPayload(subtitleTrack, oldSubtitleTrack)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
data class AvailableSubtitleTracksChanged(
|
|
75
|
+
val availableSubtitleTracks: List<SubtitleTrack>,
|
|
76
|
+
val oldAvailableSubtitleTracks: List<SubtitleTrack>
|
|
77
|
+
) : PlayerEvent() {
|
|
78
|
+
override val name = "availableSubtitleTracksChange"
|
|
79
|
+
override val jsEventPayload = AvailableSubtitleTracksChangedEventPayload(availableSubtitleTracks, oldAvailableSubtitleTracks)
|
|
80
|
+
}
|
|
81
|
+
|
|
60
82
|
data class TimeUpdated(val timeUpdate: TimeUpdate) : PlayerEvent() {
|
|
61
83
|
override val name = "timeUpdate"
|
|
62
84
|
override val jsEventPayload = timeUpdate
|
|
@@ -79,10 +101,13 @@ sealed class PlayerEvent {
|
|
|
79
101
|
is SourceChanged -> listeners.forEach { it.onSourceChanged(player, source, oldSource) }
|
|
80
102
|
is PlaybackRateChanged -> listeners.forEach { it.onPlaybackRateChanged(player, rate, oldRate) }
|
|
81
103
|
is TracksChanged -> listeners.forEach { it.onTracksChanged(player, tracks) }
|
|
104
|
+
is TrackSelectionParametersChanged -> listeners.forEach { it.onTrackSelectionParametersChanged(player, trackSelectionParameters) }
|
|
82
105
|
is TimeUpdated -> listeners.forEach { it.onTimeUpdate(player, timeUpdate) }
|
|
83
106
|
is PlayedToEnd -> listeners.forEach { it.onPlayedToEnd(player) }
|
|
84
107
|
is MutedChanged -> listeners.forEach { it.onMutedChanged(player, muted, oldMuted) }
|
|
85
108
|
is AudioMixingModeChanged -> listeners.forEach { it.onAudioMixingModeChanged(player, audioMixingMode, oldAudioMixingMode) }
|
|
109
|
+
// JS-only events
|
|
110
|
+
else -> Unit
|
|
86
111
|
}
|
|
87
112
|
}
|
|
88
113
|
}
|
|
@@ -11,10 +11,12 @@ import androidx.media3.common.PlaybackParameters
|
|
|
11
11
|
import androidx.media3.common.Player
|
|
12
12
|
import androidx.media3.common.Player.STATE_BUFFERING
|
|
13
13
|
import androidx.media3.common.Timeline
|
|
14
|
+
import androidx.media3.common.TrackSelectionParameters
|
|
14
15
|
import androidx.media3.common.Tracks
|
|
15
16
|
import androidx.media3.common.util.UnstableApi
|
|
16
17
|
import androidx.media3.exoplayer.DefaultRenderersFactory
|
|
17
18
|
import androidx.media3.exoplayer.ExoPlayer
|
|
19
|
+
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
|
|
18
20
|
import androidx.media3.ui.PlayerView
|
|
19
21
|
import expo.modules.kotlin.AppContext
|
|
20
22
|
import expo.modules.kotlin.sharedobjects.SharedObject
|
|
@@ -44,6 +46,8 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
|
|
|
44
46
|
.setEnableDecoderFallback(true)
|
|
45
47
|
private var listeners: MutableList<WeakReference<VideoPlayerListener>> = mutableListOf()
|
|
46
48
|
val loadControl: VideoPlayerLoadControl = VideoPlayerLoadControl.Builder().build()
|
|
49
|
+
val subtitles: VideoPlayerSubtitles = VideoPlayerSubtitles(this)
|
|
50
|
+
val trackSelector = DefaultTrackSelector(context)
|
|
47
51
|
|
|
48
52
|
val player = ExoPlayer
|
|
49
53
|
.Builder(context, renderersFactory)
|
|
@@ -154,16 +158,38 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
|
|
|
154
158
|
}
|
|
155
159
|
|
|
156
160
|
override fun onTracksChanged(tracks: Tracks) {
|
|
161
|
+
val oldSubtitleTracks = ArrayList(subtitles.availableSubtitleTracks)
|
|
162
|
+
val oldCurrentTrack = subtitles.currentSubtitleTrack
|
|
157
163
|
sendEvent(PlayerEvent.TracksChanged(tracks))
|
|
164
|
+
|
|
165
|
+
val newSubtitleTracks = subtitles.availableSubtitleTracks
|
|
166
|
+
val newCurrentSubtitleTrack = subtitles.currentSubtitleTrack
|
|
167
|
+
|
|
168
|
+
if (!oldSubtitleTracks.toArray().contentEquals(newSubtitleTracks.toArray())) {
|
|
169
|
+
sendEvent(PlayerEvent.AvailableSubtitleTracksChanged(newSubtitleTracks, oldSubtitleTracks))
|
|
170
|
+
}
|
|
171
|
+
if (oldCurrentTrack != newCurrentSubtitleTrack) {
|
|
172
|
+
sendEvent(PlayerEvent.SubtitleTrackChanged(newCurrentSubtitleTrack, oldCurrentTrack))
|
|
173
|
+
}
|
|
158
174
|
super.onTracksChanged(tracks)
|
|
159
175
|
}
|
|
160
176
|
|
|
177
|
+
override fun onTrackSelectionParametersChanged(parameters: TrackSelectionParameters) {
|
|
178
|
+
val oldTrack = subtitles.currentSubtitleTrack
|
|
179
|
+
sendEvent(PlayerEvent.TrackSelectionParametersChanged(parameters))
|
|
180
|
+
|
|
181
|
+
val newTrack = subtitles.currentSubtitleTrack
|
|
182
|
+
sendEvent(PlayerEvent.SubtitleTrackChanged(newTrack, oldTrack))
|
|
183
|
+
super.onTrackSelectionParametersChanged(parameters)
|
|
184
|
+
}
|
|
185
|
+
|
|
161
186
|
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
|
162
187
|
this@VideoPlayer.duration = 0f
|
|
163
188
|
this@VideoPlayer.isLive = false
|
|
164
189
|
if (reason == Player.MEDIA_ITEM_TRANSITION_REASON_REPEAT) {
|
|
165
190
|
sendEvent(PlayerEvent.PlayedToEnd())
|
|
166
191
|
}
|
|
192
|
+
subtitles.setSubtitlesEnabled(false)
|
|
167
193
|
super.onMediaItemTransition(mediaItem, reason)
|
|
168
194
|
}
|
|
169
195
|
|
|
@@ -207,6 +233,11 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
|
|
|
207
233
|
ExpoVideoPlaybackService.startService(appContext, context, serviceConnection)
|
|
208
234
|
player.addListener(playerListener)
|
|
209
235
|
VideoManager.registerVideoPlayer(this)
|
|
236
|
+
|
|
237
|
+
// ExoPlayer will enable subtitles automatically at the start, we want them disabled by default
|
|
238
|
+
appContext.mainQueue.launch {
|
|
239
|
+
subtitles.setSubtitlesEnabled(false)
|
|
240
|
+
}
|
|
210
241
|
}
|
|
211
242
|
|
|
212
243
|
override fun close() {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package expo.modules.video.player
|
|
2
2
|
|
|
3
3
|
import androidx.annotation.OptIn
|
|
4
|
+
import androidx.media3.common.TrackSelectionParameters
|
|
4
5
|
import androidx.media3.common.Tracks
|
|
5
6
|
import androidx.media3.common.util.UnstableApi
|
|
6
7
|
import expo.modules.video.enums.AudioMixingMode
|
|
@@ -18,6 +19,7 @@ interface VideoPlayerListener {
|
|
|
18
19
|
fun onSourceChanged(player: VideoPlayer, source: VideoSource?, oldSource: VideoSource?) {}
|
|
19
20
|
fun onPlaybackRateChanged(player: VideoPlayer, rate: Float, oldRate: Float?) {}
|
|
20
21
|
fun onTracksChanged(player: VideoPlayer, tracks: Tracks) {}
|
|
22
|
+
fun onTrackSelectionParametersChanged(player: VideoPlayer, trackSelectionParameters: TrackSelectionParameters) {}
|
|
21
23
|
fun onTimeUpdate(player: VideoPlayer, timeUpdate: TimeUpdate) {}
|
|
22
24
|
fun onPlayedToEnd(player: VideoPlayer) {}
|
|
23
25
|
fun onAudioMixingModeChanged(player: VideoPlayer, audioMixingMode: AudioMixingMode, oldAudioMixingMode: AudioMixingMode?) {}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
package expo.modules.video.player
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.OptIn
|
|
4
|
+
import androidx.media3.common.C
|
|
5
|
+
import androidx.media3.common.Format
|
|
6
|
+
import androidx.media3.common.MimeTypes
|
|
7
|
+
import androidx.media3.common.TrackGroup
|
|
8
|
+
import androidx.media3.common.TrackSelectionOverride
|
|
9
|
+
import androidx.media3.common.TrackSelectionParameters
|
|
10
|
+
import androidx.media3.common.Tracks
|
|
11
|
+
import androidx.media3.common.util.UnstableApi
|
|
12
|
+
import expo.modules.video.records.SubtitleTrack
|
|
13
|
+
import java.lang.ref.WeakReference
|
|
14
|
+
|
|
15
|
+
@OptIn(UnstableApi::class)
|
|
16
|
+
class VideoPlayerSubtitles(owner: VideoPlayer) : VideoPlayerListener {
|
|
17
|
+
private val owner = WeakReference(owner)
|
|
18
|
+
private val videoPlayer: VideoPlayer?
|
|
19
|
+
get() {
|
|
20
|
+
return owner.get()
|
|
21
|
+
}
|
|
22
|
+
private val formatsToGroups = mutableMapOf<Format, Pair<TrackGroup, Int>>()
|
|
23
|
+
private var currentSubtitleFormat: Format? = null
|
|
24
|
+
private var currentOverride: TrackSelectionOverride? = null
|
|
25
|
+
|
|
26
|
+
var currentSubtitleTrack: SubtitleTrack?
|
|
27
|
+
get() {
|
|
28
|
+
return SubtitleTrack.fromFormat(currentSubtitleFormat)
|
|
29
|
+
}
|
|
30
|
+
set(value) {
|
|
31
|
+
applySubtitleTrack(value)
|
|
32
|
+
}
|
|
33
|
+
val availableSubtitleTracks = arrayListOf<SubtitleTrack>()
|
|
34
|
+
|
|
35
|
+
init {
|
|
36
|
+
owner.addListener(this)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
fun setSubtitlesEnabled(enabled: Boolean) {
|
|
40
|
+
val currentParams = videoPlayer?.player?.trackSelectionParameters ?: return
|
|
41
|
+
var params = currentParams.buildUpon().setTrackTypeDisabled(C.TRACK_TYPE_TEXT, !enabled).build()
|
|
42
|
+
if (!enabled) {
|
|
43
|
+
params = params.buildUpon().clearOverridesOfType(C.TRACK_TYPE_TEXT).build()
|
|
44
|
+
}
|
|
45
|
+
videoPlayer?.player?.trackSelectionParameters = params
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// VideoPlayerListener
|
|
49
|
+
override fun onTrackSelectionParametersChanged(player: VideoPlayer, trackSelectionParameters: TrackSelectionParameters) {
|
|
50
|
+
currentSubtitleFormat = findSelectedSubtitleFormat()
|
|
51
|
+
super.onTrackSelectionParametersChanged(player, trackSelectionParameters)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
override fun onTracksChanged(player: VideoPlayer, tracks: Tracks) {
|
|
55
|
+
formatsToGroups.clear()
|
|
56
|
+
availableSubtitleTracks.clear()
|
|
57
|
+
for (group in tracks.groups) {
|
|
58
|
+
for (i in 0..<group.length) {
|
|
59
|
+
val format: Format = group.getTrackFormat(i)
|
|
60
|
+
|
|
61
|
+
if (MimeTypes.isText(format.sampleMimeType)) {
|
|
62
|
+
formatsToGroups[format] = Pair(group.mediaTrackGroup, i)
|
|
63
|
+
val track = SubtitleTrack.fromFormat(format) ?: continue
|
|
64
|
+
availableSubtitleTracks.add(track)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
currentSubtitleFormat = findSelectedSubtitleFormat()
|
|
69
|
+
super.onTracksChanged(player, tracks)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Private methods
|
|
73
|
+
private fun applySubtitleTrack(subtitleTrack: SubtitleTrack?) {
|
|
74
|
+
val player = videoPlayer?.player ?: return
|
|
75
|
+
var newParameters: TrackSelectionParameters = player.trackSelectionParameters
|
|
76
|
+
currentOverride?.let { override ->
|
|
77
|
+
newParameters = newParameters.buildUpon().clearOverridesOfType(C.TRACK_TYPE_TEXT).build()
|
|
78
|
+
}
|
|
79
|
+
if (subtitleTrack == null) {
|
|
80
|
+
player.trackSelectionParameters = newParameters
|
|
81
|
+
setSubtitlesEnabled(false)
|
|
82
|
+
currentOverride = null
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
val format = formatsToGroups.keys.firstOrNull {
|
|
86
|
+
it.id == subtitleTrack.id
|
|
87
|
+
}
|
|
88
|
+
format?.let {
|
|
89
|
+
formatsToGroups[it]?.let { subtitlePair ->
|
|
90
|
+
val override = TrackSelectionOverride(subtitlePair.first, subtitlePair.second)
|
|
91
|
+
newParameters = newParameters.buildUpon().addOverride(override).build()
|
|
92
|
+
player.trackSelectionParameters = newParameters
|
|
93
|
+
setSubtitlesEnabled(true)
|
|
94
|
+
currentOverride = override
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private fun findSelectedSubtitleFormat(): Format? {
|
|
100
|
+
val trackSelectionParameters = videoPlayer?.player?.trackSelectionParameters
|
|
101
|
+
val preferredTextLanguages = trackSelectionParameters?.preferredTextLanguages
|
|
102
|
+
val overriddenFormat: Format? = trackSelectionParameters?.overrides?.let {
|
|
103
|
+
for ((group, override) in it) {
|
|
104
|
+
if (group.type == C.TRACK_TYPE_TEXT) {
|
|
105
|
+
// For subtitles only one index will be replaced
|
|
106
|
+
return@let override.trackIndices.firstOrNull()?.let { index ->
|
|
107
|
+
group.getFormat(index)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return@let null
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
val preferredFormat: Format? = preferredTextLanguages?.let { preferredTextLanguages ->
|
|
115
|
+
for (preferredLanguage in preferredTextLanguages) {
|
|
116
|
+
return@let formatsToGroups.keys.firstOrNull {
|
|
117
|
+
it.language == preferredLanguage
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return@let null
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return overriddenFormat ?: preferredFormat
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package expo.modules.video.records
|
|
2
|
+
|
|
3
|
+
import androidx.media3.common.Format
|
|
4
|
+
import expo.modules.kotlin.records.Field
|
|
5
|
+
import expo.modules.kotlin.records.Record
|
|
6
|
+
import java.io.Serializable
|
|
7
|
+
import java.util.Locale
|
|
8
|
+
|
|
9
|
+
class SubtitleTrack(
|
|
10
|
+
@Field var id: String,
|
|
11
|
+
@Field var language: String?,
|
|
12
|
+
@Field var label: String?
|
|
13
|
+
) : Record, Serializable {
|
|
14
|
+
companion object {
|
|
15
|
+
fun fromFormat(format: Format?): SubtitleTrack? {
|
|
16
|
+
format ?: return null
|
|
17
|
+
val id = format.id ?: return null
|
|
18
|
+
val language = format.language ?: return null
|
|
19
|
+
val label = Locale(language).displayLanguage
|
|
20
|
+
|
|
21
|
+
return SubtitleTrack(
|
|
22
|
+
id = id,
|
|
23
|
+
language = language,
|
|
24
|
+
label = label
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -44,3 +44,13 @@ class TimeUpdate(
|
|
|
44
44
|
@Field var currentLiveTimestamp: Long?,
|
|
45
45
|
@Field var bufferedPosition: Double = .0
|
|
46
46
|
) : VideoEventPayload
|
|
47
|
+
|
|
48
|
+
class SubtitleTrackChangedEventPayload(
|
|
49
|
+
@Field val subtitleTrack: SubtitleTrack?,
|
|
50
|
+
@Field val oldSubtitleTrack: SubtitleTrack?
|
|
51
|
+
) : VideoEventPayload
|
|
52
|
+
|
|
53
|
+
class AvailableSubtitleTracksChangedEventPayload(
|
|
54
|
+
@Field val availableSubtitleTracks: List<SubtitleTrack>,
|
|
55
|
+
@Field val oldAvailableSubtitleTracks: List<SubtitleTrack>
|
|
56
|
+
) : VideoEventPayload
|
package/build/VideoPlayer.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { VideoSource, VideoPlayer } from './VideoPlayer.types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a direct instance of `VideoPlayer` that doesn't release automatically.
|
|
4
|
+
*
|
|
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
|
|
7
|
+
*/
|
|
8
|
+
export declare function createVideoPlayer(source: VideoSource): VideoPlayer;
|
|
2
9
|
/**
|
|
3
10
|
* Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.
|
|
4
11
|
* @param source - A video source that is used to initialize the player.
|
|
5
12
|
* @param setup - A function that allows setting up the player. It will run after the player is created.
|
|
6
13
|
*/
|
|
7
14
|
export declare function useVideoPlayer(source: VideoSource, setup?: (player: VideoPlayer) => void): VideoPlayer;
|
|
8
|
-
declare const _default: typeof VideoPlayer;
|
|
9
|
-
export default _default;
|
|
10
15
|
//# sourceMappingURL=VideoPlayer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.tsx"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAS/D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAElE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GACpC,WAAW,CAQb"}
|
package/build/VideoPlayer.js
CHANGED
|
@@ -6,6 +6,15 @@ const replace = NativeVideoModule.VideoPlayer.prototype.replace;
|
|
|
6
6
|
NativeVideoModule.VideoPlayer.prototype.replace = function (source) {
|
|
7
7
|
return replace.call(this, parseSource(source));
|
|
8
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Creates a direct instance of `VideoPlayer` that doesn't release automatically.
|
|
11
|
+
*
|
|
12
|
+
* > **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.
|
|
13
|
+
* @param source
|
|
14
|
+
*/
|
|
15
|
+
export function createVideoPlayer(source) {
|
|
16
|
+
return new NativeVideoModule.VideoPlayer(parseSource(source));
|
|
17
|
+
}
|
|
9
18
|
/**
|
|
10
19
|
* Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.
|
|
11
20
|
* @param source - A video source that is used to initialize the player.
|
|
@@ -31,5 +40,4 @@ function parseSource(source) {
|
|
|
31
40
|
}
|
|
32
41
|
return source;
|
|
33
42
|
}
|
|
34
|
-
export default NativeVideoModule.VideoPlayer;
|
|
35
43
|
//# sourceMappingURL=VideoPlayer.js.map
|
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,UAAU,MAAmB;IAC7E,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAmB,EACnB,KAAqC;IAErC,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAEzC,OAAO,wBAAwB,CAAC,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QAC/D,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC;QAChB,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,MAAmB;IACtC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC9B,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;KAChD;SAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QACrC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;KACxB;IAED,IAAI,OAAO,MAAM,EAAE,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;QACtD,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC;KACnE;IACD,OAAO,MAAM,CAAC;AAChB,CAAC
|
|
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,UAAU,MAAmB;IAC7E,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAmB;IACnD,OAAO,IAAI,iBAAiB,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AAChE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAmB,EACnB,KAAqC;IAErC,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAEzC,OAAO,wBAAwB,CAAC,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QAC/D,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC;QAChB,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,MAAmB;IACtC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC9B,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;KAChD;SAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QACrC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;KACxB;IAED,IAAI,OAAO,MAAM,EAAE,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE;QACtD,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC;KACnE;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { useReleasingSharedObject } from 'expo-modules-core';\n\nimport NativeVideoModule from './NativeVideoModule';\nimport { VideoSource, VideoPlayer } 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 (source: VideoSource) {\n return replace.call(this, parseSource(source));\n};\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\n */\nexport function createVideoPlayer(source: VideoSource): VideoPlayer {\n return new NativeVideoModule.VideoPlayer(parseSource(source));\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 */\nexport function useVideoPlayer(\n source: VideoSource,\n setup?: (player: VideoPlayer) => void\n): VideoPlayer {\n const parsedSource = parseSource(source);\n\n return useReleasingSharedObject(() => {\n const player = new NativeVideoModule.VideoPlayer(parsedSource);\n setup?.(player);\n return player;\n }, [JSON.stringify(parsedSource)]);\n}\n\nfunction parseSource(source: VideoSource): VideoSource {\n if (typeof source === 'number') {\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 return { ...source, uri: resolveAssetSource(source.assetId).uri };\n }\n return source;\n}\n"]}
|
|
@@ -130,6 +130,23 @@ export declare class VideoPlayer extends SharedObject<VideoPlayerEvents> {
|
|
|
130
130
|
* @platform ios
|
|
131
131
|
*/
|
|
132
132
|
bufferOptions: BufferOptions;
|
|
133
|
+
/**
|
|
134
|
+
* Specifies the subtitle track which is currently displayed by the player. `null` when no subtitles are displayed.
|
|
135
|
+
*
|
|
136
|
+
* > To ensure a valid subtitle track, always assign one of the subtitle tracks from the [`availableSubtitleTracks`](#availablesubtitletracks) array.
|
|
137
|
+
*
|
|
138
|
+
* @default null
|
|
139
|
+
* @platform android
|
|
140
|
+
* @platform ios
|
|
141
|
+
*/
|
|
142
|
+
subtitleTrack: SubtitleTrack | null;
|
|
143
|
+
/**
|
|
144
|
+
* An array of subtitle tracks available for the current video.
|
|
145
|
+
*
|
|
146
|
+
* @platform android
|
|
147
|
+
* @platform ios
|
|
148
|
+
*/
|
|
149
|
+
readonly availableSubtitleTracks: SubtitleTrack[];
|
|
133
150
|
/**
|
|
134
151
|
* Initializes a new video player instance with the given source.
|
|
135
152
|
* @hidden
|
|
@@ -338,4 +355,20 @@ export type BufferOptions = {
|
|
|
338
355
|
* > On iOS, the Now Playing notification is dependent on the audio mode. If the audio mode is different from `doNotMix` or `auto` this feature will not work.
|
|
339
356
|
*/
|
|
340
357
|
export type AudioMixingMode = 'mixWithOthers' | 'duckOthers' | 'auto' | 'doNotMix';
|
|
358
|
+
export type SubtitleTrack = {
|
|
359
|
+
/**
|
|
360
|
+
* A string used by `expo-video` to identify the subtitle track.
|
|
361
|
+
*
|
|
362
|
+
* @platform android
|
|
363
|
+
*/
|
|
364
|
+
id: string;
|
|
365
|
+
/**
|
|
366
|
+
* Language of the subtitle track. For example, `en`, `pl`, `de`.
|
|
367
|
+
*/
|
|
368
|
+
language: string;
|
|
369
|
+
/**
|
|
370
|
+
* Label of the subtitle track in the language of the device.
|
|
371
|
+
*/
|
|
372
|
+
label: string;
|
|
373
|
+
};
|
|
341
374
|
//# sourceMappingURL=VideoPlayer.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayer.types.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VideoPlayer.types.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayer.types.js","sourceRoot":"","sources":["../src/VideoPlayer.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC","sourcesContent":["import { SharedObject } from 'expo';\n\nimport { VideoPlayerEvents } from './VideoPlayerEvents.types';\nimport { VideoThumbnail } from './VideoThumbnail';\n\n/**\n * A class that represents an instance of the video player.\n */\nexport declare class VideoPlayer extends SharedObject<VideoPlayerEvents> {\n /**\n * Boolean value whether the player is currently playing.\n * > Use `play` and `pause` methods to control the playback.\n */\n readonly playing: boolean;\n\n /**\n * Determines whether the player should automatically replay after reaching the end of the video.\n * @default false\n */\n loop: boolean;\n\n /**\n * Determines whether the player should allow external playback.\n * @default true\n * @platform ios\n */\n allowsExternalPlayback: boolean;\n\n /**\n * Determines how the player will interact with other audio playing in the system.\n *\n * @default 'auto'\n * @platform android\n * @platform ios\n */\n audioMixingMode: AudioMixingMode;\n\n /**\n * Boolean value whether the player is currently muted.\n * Setting this property to `true`/`false` will mute/unmute the player.\n * @default false\n */\n muted: boolean;\n\n /**\n * Float value indicating the current playback time in seconds.\n *\n * If the player is not yet playing, this value indicates the time position\n * at which playback will begin once the `play()` method is called.\n *\n * Setting `currentTime` to a new value seeks the player to the given time.\n */\n currentTime: number;\n\n /**\n * The exact timestamp when the currently displayed video frame was sent from the server,\n * based on the `EXT-X-PROGRAM-DATE-TIME` tag in the livestream metadata.\n * If this metadata is missing, this property will return `null`.\n * @platform android\n * @platform ios\n */\n readonly currentLiveTimestamp: number | null;\n\n /**\n * Float value indicating the latency of the live stream in seconds.\n * If a livestream doesn't have the required metadata, this will return `null`.\n * @platform android\n * @platform ios\n */\n readonly currentOffsetFromLive: number | null;\n\n /**\n * Float value indicating the time offset from the live in seconds.\n * @platform ios\n */\n targetOffsetFromLive: number;\n\n /**\n * Float value indicating the duration of the current video in seconds.\n */\n readonly duration: number;\n\n /**\n * Float value between `0` and `1.0` representing the current volume.\n * Muting the player doesn't affect the volume. In other words, when the player is muted, the volume is the same as\n * when unmuted. Similarly, setting the volume doesn't unmute the player.\n * @default 1.0\n */\n volume: number;\n\n /**\n * Boolean value indicating if the player should correct audio pitch when the playback speed changes.\n * @default true\n */\n preservesPitch: boolean;\n\n /**\n * Float value indicating the interval in seconds at which the player will emit the [`timeUpdate`](#videoplayerevents) event.\n * When the value is equal to `0`, the event will not be emitted.\n *\n * @default 0\n */\n timeUpdateEventInterval: number;\n\n /**\n * Float value between `0` and `16.0` indicating the current playback speed of the player.\n * @default 1.0\n */\n playbackRate: number;\n\n /**\n * Boolean value indicating whether the player is currently playing a live stream.\n */\n readonly isLive: boolean;\n\n /**\n * Indicates the current status of the player.\n */\n readonly status: VideoPlayerStatus;\n\n /**\n * Boolean value determining whether the player should show the now playing notification.\n *\n * @default false\n * @platform android\n * @platform ios\n */\n showNowPlayingNotification: boolean;\n\n /**\n * Determines whether the player should continue playing after the app enters the background.\n * @default false\n * @platform ios\n * @platform android\n */\n staysActiveInBackground: boolean;\n\n /**\n * Float value indicating how far the player has buffered the video in seconds.\n *\n * This value is 0 when the player has not buffered up to the current playback time.\n * When it's impossible to determine the buffer state (for example, when the player isn't playing any media), this value is -1.\n */\n readonly bufferedPosition: number;\n\n /**\n * Specifies buffer options which will be used by the player when buffering the video.\n *\n * > You should provide a `BufferOptions` object when setting this property. Setting individual buffer properties is not supported.\n * @platform android\n * @platform ios\n */\n bufferOptions: BufferOptions;\n\n /**\n * Initializes a new video player instance with the given source.\n * @hidden\n */\n constructor(source: VideoSource);\n\n /**\n * Resumes the player.\n */\n play(): void;\n\n /**\n * Pauses the player.\n */\n pause(): void;\n\n /**\n * Replaces the current source with a new one.\n */\n replace(source: VideoSource): void;\n\n /**\n * Seeks the playback by the given number of seconds.\n */\n seekBy(seconds: number): void;\n\n /**\n * Seeks the playback to the beginning.\n */\n replay(): void;\n\n /**\n * Generates thumbnails from the currently played asset. The thumbnails are references to native images,\n * thus they can be used as a source of the `Image` component from `expo-image`.\n * @platform ios\n */\n generateThumbnailsAsync(times: number | number[]): Promise<VideoThumbnail[]>;\n}\n\n/**\n * Describes the current status of the player.\n * - `idle`: The player is not playing or loading any videos.\n * - `loading`: The player is loading video data from the provided source\n * - `readyToPlay`: The player has loaded enough data to start playing or to continue playback.\n * - `error`: The player has encountered an error while loading or playing the video.\n */\nexport type VideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error';\n\nexport type VideoSource =\n | string\n | number\n | null\n | {\n /**\n * The URI of the video.\n *\n * This property is exclusive with the `assetId` property. When both are present, the `assetId` will be ignored.\n */\n uri?: string;\n\n /**\n * The asset ID of a local video asset, acquired with the `require` function.\n * This property is exclusive with the `uri` property. When both are present, the `assetId` will be ignored.\n */\n assetId?: number;\n\n /**\n * Specifies the DRM options which will be used by the player while loading the video.\n */\n drm?: DRMOptions;\n\n /**\n * Specifies information which will be displayed in the now playing notification.\n * When undefined the player will display information contained in the video metadata.\n * @platform android\n * @platform ios\n */\n metadata?: VideoMetadata;\n\n /**\n * Specifies headers sent with the video request.\n * > For DRM license headers use the `headers` field of [`DRMOptions`](#drmoptions).\n * @platform android\n * @platform ios\n */\n headers?: Record<string, string>;\n };\n\n/**\n * Contains information about any errors that the player encountered during the playback\n */\nexport type PlayerError = {\n message: string;\n};\n\n/**\n * Contains information that will be displayed in the now playing notification when the video is playing.\n * @platform android\n * @platform ios\n */\nexport type VideoMetadata = {\n /**\n * The title of the video.\n * @platform android\n * @platform ios\n */\n title?: string;\n /**\n * Secondary text that will be displayed under the title.\n * @platform android\n * @platform ios\n */\n artist?: string;\n /**\n * The uri of the video artwork.\n * @platform android\n * @platform ios\n */\n artwork?: string;\n};\n\n/**\n * Specifies which type of DRM to use:\n * - Android supports ClearKey, PlayReady and Widevine.\n * - iOS supports FairPlay.\n */\nexport type DRMType = 'clearkey' | 'fairplay' | 'playready' | 'widevine';\n\n/**\n * Specifies DRM options which will be used by the player while loading the video.\n */\nexport type DRMOptions = {\n /**\n * Determines which type of DRM to use.\n */\n type: DRMType;\n\n /**\n * Determines the license server URL.\n */\n licenseServer: string;\n\n /**\n * Determines headers sent to the license server on license requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Specifies whether the DRM is a multi-key DRM.\n * @platform android\n */\n multiKey?: boolean;\n\n /**\n * Specifies the content ID of the stream.\n * @platform ios\n */\n contentId?: string;\n\n /**\n * Specifies the certificate URL for the FairPlay DRM.\n * @platform ios\n */\n certificateUrl?: string;\n\n /**\n * Specifies the base64 encoded certificate data for the FairPlay DRM.\n * When this property is set, the `certificateUrl` property is ignored.\n * @platform ios\n */\n base64CertificateData?: string;\n};\n\n/**\n * Specifies buffer options which will be used by the player when buffering the video.\n *\n * @platform android\n * @platform ios\n */\nexport type BufferOptions = {\n /**\n * The duration in seconds which determines how much media the player should buffer ahead of the current playback time.\n *\n * On iOS when set to `0` the player will automatically decide appropriate buffer duration.\n *\n * Equivalent to [`AVPlayerItem.preferredForwardBufferDuration`](https://developer.apple.com/documentation/avfoundation/avplayeritem/1643630-preferredforwardbufferduration).\n * @default Android: 20, iOS: 0\n * @platform android\n * @platform ios\n */\n readonly preferredForwardBufferDuration?: number;\n\n /**\n * A Boolean value that indicates whether the player should automatically delay playback in order to minimize stalling.\n *\n * Equivalent to [`AVPlayer.automaticallyWaitsToMinimizeStalling`](https://developer.apple.com/documentation/avfoundation/avplayer/1643482-automaticallywaitstominimizestal).\n * @default true\n * @platform ios\n */\n readonly waitsToMinimizeStalling?: boolean;\n\n /**\n * Minimum duration of the buffer in seconds required to continue playing after the player has been paused or started buffering.\n *\n * > This property will be ignored if `preferredForwardBufferDuration` is lower.\n * @default 2\n * @platform android\n */\n readonly minBufferForPlayback?: number;\n\n /**\n * The maximum number of bytes that the player can buffer from the network.\n * When 0 the player will automatically decide appropriate buffer size.\n *\n * @default 0\n * @platform android\n */\n readonly maxBufferBytes?: number | null;\n\n /**\n * A Boolean value which determines whether the player should prioritize time over size when buffering media.\n *\n * @default false\n * @platform android\n */\n readonly prioritizeTimeOverSizeThreshold?: boolean;\n};\n\n/**\n * Specifies the audio mode that the player should use. Audio mode is set on per-app basis, if there are multiple players playing and\n * have different a `AudioMode` specified, the highest priority mode will be used. Priority order: 'doNotMix' > 'auto' > 'duckOthers' > 'mixWithOthers'.\n *\n * - `mixWithOthers`: The player will mix its audio output with other apps.\n * - `duckOthers`: The player will lower the volume of other apps if any of the active players is outputting audio.\n * - `auto`: The player will allow other apps to keep playing audio only when it is muted. On iOS it will always interrupt other apps when `showNowPlayingNotification` is `true` due to system requirements.\n * - `doNotMix`: The player will pause playback in other apps, even when it's muted.\n *\n * > On iOS, the Now Playing notification is dependent on the audio mode. If the audio mode is different from `doNotMix` or `auto` this feature will not work.\n */\nexport type AudioMixingMode = 'mixWithOthers' | 'duckOthers' | 'auto' | 'doNotMix';\n"]}
|
|
1
|
+
{"version":3,"file":"VideoPlayer.types.js","sourceRoot":"","sources":["../src/VideoPlayer.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC","sourcesContent":["import { SharedObject } from 'expo';\n\nimport { VideoPlayerEvents } from './VideoPlayerEvents.types';\nimport { VideoThumbnail } from './VideoThumbnail';\n\n/**\n * A class that represents an instance of the video player.\n */\nexport declare class VideoPlayer extends SharedObject<VideoPlayerEvents> {\n /**\n * Boolean value whether the player is currently playing.\n * > Use `play` and `pause` methods to control the playback.\n */\n readonly playing: boolean;\n\n /**\n * Determines whether the player should automatically replay after reaching the end of the video.\n * @default false\n */\n loop: boolean;\n\n /**\n * Determines whether the player should allow external playback.\n * @default true\n * @platform ios\n */\n allowsExternalPlayback: boolean;\n\n /**\n * Determines how the player will interact with other audio playing in the system.\n *\n * @default 'auto'\n * @platform android\n * @platform ios\n */\n audioMixingMode: AudioMixingMode;\n\n /**\n * Boolean value whether the player is currently muted.\n * Setting this property to `true`/`false` will mute/unmute the player.\n * @default false\n */\n muted: boolean;\n\n /**\n * Float value indicating the current playback time in seconds.\n *\n * If the player is not yet playing, this value indicates the time position\n * at which playback will begin once the `play()` method is called.\n *\n * Setting `currentTime` to a new value seeks the player to the given time.\n */\n currentTime: number;\n\n /**\n * The exact timestamp when the currently displayed video frame was sent from the server,\n * based on the `EXT-X-PROGRAM-DATE-TIME` tag in the livestream metadata.\n * If this metadata is missing, this property will return `null`.\n * @platform android\n * @platform ios\n */\n readonly currentLiveTimestamp: number | null;\n\n /**\n * Float value indicating the latency of the live stream in seconds.\n * If a livestream doesn't have the required metadata, this will return `null`.\n * @platform android\n * @platform ios\n */\n readonly currentOffsetFromLive: number | null;\n\n /**\n * Float value indicating the time offset from the live in seconds.\n * @platform ios\n */\n targetOffsetFromLive: number;\n\n /**\n * Float value indicating the duration of the current video in seconds.\n */\n readonly duration: number;\n\n /**\n * Float value between `0` and `1.0` representing the current volume.\n * Muting the player doesn't affect the volume. In other words, when the player is muted, the volume is the same as\n * when unmuted. Similarly, setting the volume doesn't unmute the player.\n * @default 1.0\n */\n volume: number;\n\n /**\n * Boolean value indicating if the player should correct audio pitch when the playback speed changes.\n * @default true\n */\n preservesPitch: boolean;\n\n /**\n * Float value indicating the interval in seconds at which the player will emit the [`timeUpdate`](#videoplayerevents) event.\n * When the value is equal to `0`, the event will not be emitted.\n *\n * @default 0\n */\n timeUpdateEventInterval: number;\n\n /**\n * Float value between `0` and `16.0` indicating the current playback speed of the player.\n * @default 1.0\n */\n playbackRate: number;\n\n /**\n * Boolean value indicating whether the player is currently playing a live stream.\n */\n readonly isLive: boolean;\n\n /**\n * Indicates the current status of the player.\n */\n readonly status: VideoPlayerStatus;\n\n /**\n * Boolean value determining whether the player should show the now playing notification.\n *\n * @default false\n * @platform android\n * @platform ios\n */\n showNowPlayingNotification: boolean;\n\n /**\n * Determines whether the player should continue playing after the app enters the background.\n * @default false\n * @platform ios\n * @platform android\n */\n staysActiveInBackground: boolean;\n\n /**\n * Float value indicating how far the player has buffered the video in seconds.\n *\n * This value is 0 when the player has not buffered up to the current playback time.\n * When it's impossible to determine the buffer state (for example, when the player isn't playing any media), this value is -1.\n */\n readonly bufferedPosition: number;\n\n /**\n * Specifies buffer options which will be used by the player when buffering the video.\n *\n * > You should provide a `BufferOptions` object when setting this property. Setting individual buffer properties is not supported.\n * @platform android\n * @platform ios\n */\n bufferOptions: BufferOptions;\n\n /**\n * Specifies the subtitle track which is currently displayed by the player. `null` when no subtitles are displayed.\n *\n * > To ensure a valid subtitle track, always assign one of the subtitle tracks from the [`availableSubtitleTracks`](#availablesubtitletracks) array.\n *\n * @default null\n * @platform android\n * @platform ios\n */\n subtitleTrack: SubtitleTrack | null;\n\n /**\n * An array of subtitle tracks available for the current video.\n *\n * @platform android\n * @platform ios\n */\n readonly availableSubtitleTracks: SubtitleTrack[];\n\n /**\n * Initializes a new video player instance with the given source.\n * @hidden\n */\n constructor(source: VideoSource);\n\n /**\n * Resumes the player.\n */\n play(): void;\n\n /**\n * Pauses the player.\n */\n pause(): void;\n\n /**\n * Replaces the current source with a new one.\n */\n replace(source: VideoSource): void;\n\n /**\n * Seeks the playback by the given number of seconds.\n */\n seekBy(seconds: number): void;\n\n /**\n * Seeks the playback to the beginning.\n */\n replay(): void;\n\n /**\n * Generates thumbnails from the currently played asset. The thumbnails are references to native images,\n * thus they can be used as a source of the `Image` component from `expo-image`.\n * @platform ios\n */\n generateThumbnailsAsync(times: number | number[]): Promise<VideoThumbnail[]>;\n}\n\n/**\n * Describes the current status of the player.\n * - `idle`: The player is not playing or loading any videos.\n * - `loading`: The player is loading video data from the provided source\n * - `readyToPlay`: The player has loaded enough data to start playing or to continue playback.\n * - `error`: The player has encountered an error while loading or playing the video.\n */\nexport type VideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error';\n\nexport type VideoSource =\n | string\n | number\n | null\n | {\n /**\n * The URI of the video.\n *\n * This property is exclusive with the `assetId` property. When both are present, the `assetId` will be ignored.\n */\n uri?: string;\n\n /**\n * The asset ID of a local video asset, acquired with the `require` function.\n * This property is exclusive with the `uri` property. When both are present, the `assetId` will be ignored.\n */\n assetId?: number;\n\n /**\n * Specifies the DRM options which will be used by the player while loading the video.\n */\n drm?: DRMOptions;\n\n /**\n * Specifies information which will be displayed in the now playing notification.\n * When undefined the player will display information contained in the video metadata.\n * @platform android\n * @platform ios\n */\n metadata?: VideoMetadata;\n\n /**\n * Specifies headers sent with the video request.\n * > For DRM license headers use the `headers` field of [`DRMOptions`](#drmoptions).\n * @platform android\n * @platform ios\n */\n headers?: Record<string, string>;\n };\n\n/**\n * Contains information about any errors that the player encountered during the playback\n */\nexport type PlayerError = {\n message: string;\n};\n\n/**\n * Contains information that will be displayed in the now playing notification when the video is playing.\n * @platform android\n * @platform ios\n */\nexport type VideoMetadata = {\n /**\n * The title of the video.\n * @platform android\n * @platform ios\n */\n title?: string;\n /**\n * Secondary text that will be displayed under the title.\n * @platform android\n * @platform ios\n */\n artist?: string;\n /**\n * The uri of the video artwork.\n * @platform android\n * @platform ios\n */\n artwork?: string;\n};\n\n/**\n * Specifies which type of DRM to use:\n * - Android supports ClearKey, PlayReady and Widevine.\n * - iOS supports FairPlay.\n */\nexport type DRMType = 'clearkey' | 'fairplay' | 'playready' | 'widevine';\n\n/**\n * Specifies DRM options which will be used by the player while loading the video.\n */\nexport type DRMOptions = {\n /**\n * Determines which type of DRM to use.\n */\n type: DRMType;\n\n /**\n * Determines the license server URL.\n */\n licenseServer: string;\n\n /**\n * Determines headers sent to the license server on license requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Specifies whether the DRM is a multi-key DRM.\n * @platform android\n */\n multiKey?: boolean;\n\n /**\n * Specifies the content ID of the stream.\n * @platform ios\n */\n contentId?: string;\n\n /**\n * Specifies the certificate URL for the FairPlay DRM.\n * @platform ios\n */\n certificateUrl?: string;\n\n /**\n * Specifies the base64 encoded certificate data for the FairPlay DRM.\n * When this property is set, the `certificateUrl` property is ignored.\n * @platform ios\n */\n base64CertificateData?: string;\n};\n\n/**\n * Specifies buffer options which will be used by the player when buffering the video.\n *\n * @platform android\n * @platform ios\n */\nexport type BufferOptions = {\n /**\n * The duration in seconds which determines how much media the player should buffer ahead of the current playback time.\n *\n * On iOS when set to `0` the player will automatically decide appropriate buffer duration.\n *\n * Equivalent to [`AVPlayerItem.preferredForwardBufferDuration`](https://developer.apple.com/documentation/avfoundation/avplayeritem/1643630-preferredforwardbufferduration).\n * @default Android: 20, iOS: 0\n * @platform android\n * @platform ios\n */\n readonly preferredForwardBufferDuration?: number;\n\n /**\n * A Boolean value that indicates whether the player should automatically delay playback in order to minimize stalling.\n *\n * Equivalent to [`AVPlayer.automaticallyWaitsToMinimizeStalling`](https://developer.apple.com/documentation/avfoundation/avplayer/1643482-automaticallywaitstominimizestal).\n * @default true\n * @platform ios\n */\n readonly waitsToMinimizeStalling?: boolean;\n\n /**\n * Minimum duration of the buffer in seconds required to continue playing after the player has been paused or started buffering.\n *\n * > This property will be ignored if `preferredForwardBufferDuration` is lower.\n * @default 2\n * @platform android\n */\n readonly minBufferForPlayback?: number;\n\n /**\n * The maximum number of bytes that the player can buffer from the network.\n * When 0 the player will automatically decide appropriate buffer size.\n *\n * @default 0\n * @platform android\n */\n readonly maxBufferBytes?: number | null;\n\n /**\n * A Boolean value which determines whether the player should prioritize time over size when buffering media.\n *\n * @default false\n * @platform android\n */\n readonly prioritizeTimeOverSizeThreshold?: boolean;\n};\n\n/**\n * Specifies the audio mode that the player should use. Audio mode is set on per-app basis, if there are multiple players playing and\n * have different a `AudioMode` specified, the highest priority mode will be used. Priority order: 'doNotMix' > 'auto' > 'duckOthers' > 'mixWithOthers'.\n *\n * - `mixWithOthers`: The player will mix its audio output with other apps.\n * - `duckOthers`: The player will lower the volume of other apps if any of the active players is outputting audio.\n * - `auto`: The player will allow other apps to keep playing audio only when it is muted. On iOS it will always interrupt other apps when `showNowPlayingNotification` is `true` due to system requirements.\n * - `doNotMix`: The player will pause playback in other apps, even when it's muted.\n *\n * > On iOS, the Now Playing notification is dependent on the audio mode. If the audio mode is different from `doNotMix` or `auto` this feature will not work.\n */\nexport type AudioMixingMode = 'mixWithOthers' | 'duckOthers' | 'auto' | 'doNotMix';\n\nexport type SubtitleTrack = {\n /**\n * A string used by `expo-video` to identify the subtitle track.\n *\n * @platform android\n */\n id: string;\n\n /**\n * Language of the subtitle track. For example, `en`, `pl`, `de`.\n */\n language: string;\n\n /**\n * Label of the subtitle track in the language of the device.\n */\n label: string;\n};\n"]}
|