expo-video 2.1.9 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/android/build.gradle +2 -2
  3. package/android/src/main/java/expo/modules/video/VideoModule.kt +21 -1
  4. package/android/src/main/java/expo/modules/video/VideoView.kt +7 -4
  5. package/android/src/main/java/expo/modules/video/player/FirstFrameEventGenerator.kt +3 -2
  6. package/android/src/main/java/expo/modules/video/player/PlayerEvent.kt +20 -2
  7. package/android/src/main/java/expo/modules/video/player/VideoPlayer.kt +16 -1
  8. package/android/src/main/java/expo/modules/video/player/VideoPlayerAudioTracks.kt +125 -0
  9. package/android/src/main/java/expo/modules/video/records/Tracks.kt +21 -0
  10. package/android/src/main/java/expo/modules/video/records/VideoEventPayloads.kt +12 -1
  11. package/build/VideoPlayer.types.d.ts +30 -0
  12. package/build/VideoPlayer.types.d.ts.map +1 -1
  13. package/build/VideoPlayer.types.js.map +1 -1
  14. package/build/VideoPlayer.web.d.ts +3 -1
  15. package/build/VideoPlayer.web.d.ts.map +1 -1
  16. package/build/VideoPlayer.web.js +2 -0
  17. package/build/VideoPlayer.web.js.map +1 -1
  18. package/build/VideoPlayerEvents.types.d.ts +34 -1
  19. package/build/VideoPlayerEvents.types.d.ts.map +1 -1
  20. package/build/VideoPlayerEvents.types.js.map +1 -1
  21. package/build/VideoView.types.d.ts +1 -1
  22. package/build/VideoView.types.d.ts.map +1 -1
  23. package/build/VideoView.types.js.map +1 -1
  24. package/build/index.d.ts +1 -1
  25. package/build/index.d.ts.map +1 -1
  26. package/build/index.js.map +1 -1
  27. package/expo-module.config.json +7 -1
  28. package/ios/Records/Tracks.swift +13 -0
  29. package/ios/Records/VideoEventPayloads.swift +11 -0
  30. package/ios/VideoModule.swift +11 -0
  31. package/ios/VideoPlayer.swift +21 -2
  32. package/ios/VideoPlayerAudioTracks.swift +72 -0
  33. package/ios/VideoPlayerItem.swift +3 -1
  34. package/ios/VideoPlayerObserver.swift +89 -22
  35. package/ios/VideoSourceLoader.swift +44 -8
  36. package/ios/VideoSourceLoaderListener.swift +34 -0
  37. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar +0 -0
  38. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar.md5 +1 -0
  39. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar.sha1 +1 -0
  40. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar.sha256 +1 -0
  41. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1-sources.jar.sha512 +1 -0
  42. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar +0 -0
  43. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar.md5 +1 -0
  44. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar.sha1 +1 -0
  45. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar.sha256 +1 -0
  46. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.aar.sha512 +1 -0
  47. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module +147 -0
  48. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module.md5 +1 -0
  49. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module.sha1 +1 -0
  50. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module.sha256 +1 -0
  51. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.module.sha512 +1 -0
  52. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom +88 -0
  53. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom.md5 +1 -0
  54. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom.sha1 +1 -0
  55. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom.sha256 +1 -0
  56. package/local-maven-repo/host/exp/exponent/expo.modules.video/2.2.1/expo.modules.video-2.2.1.pom.sha512 +1 -0
  57. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml +13 -0
  58. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.md5 +1 -0
  59. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha1 +1 -0
  60. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha256 +1 -0
  61. package/local-maven-repo/host/exp/exponent/expo.modules.video/maven-metadata.xml.sha512 +1 -0
  62. package/package.json +2 -2
  63. package/src/VideoPlayer.types.ts +35 -0
  64. package/src/VideoPlayer.web.tsx +3 -0
  65. package/src/VideoPlayerEvents.types.ts +40 -0
  66. package/src/VideoView.types.ts +2 -1
  67. package/src/index.ts +1 -0
package/CHANGELOG.md CHANGED
@@ -10,6 +10,26 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 2.2.1 — 2025-06-10
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
17
+ ## 2.2.0 — 2025-06-04
18
+
19
+ ### 🎉 New features
20
+
21
+ - [Android][iOS] Added support for Audio Track feature. You can now set the audio track using `player.audioTrack` and list available audio tracks using `player.availableAudioTracks`. ([#36207](https://github.com/expo/expo/pull/36207) by [@HADeveloper](https://github.com/HADeveloper))
22
+
23
+ ### 🐛 Bug fixes
24
+
25
+ - [Android] Fix `onFirstFrameRender` not being emitted for sources with `pixelWidthHeightRatio` different than 1. ([#37009](https://github.com/expo/expo/pull/37009) by [@behenate](https://github.com/behenate))
26
+ - [Android] Fix `useExoShutter` prop not being exposed to the JS side. ([#37012](https://github.com/expo/expo/pull/37012) by [@behenate](https://github.com/behenate))
27
+ - [Android] Add missing `onFirstFrameRender` event to the `VideoView` definition. ([#37014](https://github.com/expo/expo/pull/37014) by [@behenate](https://github.com/behenate))
28
+ - [iOS] Fix player not entering 'error' state when loading fails on iOS. ([#37177](https://github.com/expo/expo/pull/37177) by [@behenate](https://github.com/behenate))
29
+ - [iOS] Fix player reporting status `readyToPlay` while a source is being loaded asynchronously. ([#37180](https://github.com/expo/expo/pull/37180) by [@behenate](https://github.com/behenate))
30
+ - [iOS] Fix player going into `loading` status for a single frame when unpausing with a full buffer. ([#37181](https://github.com/expo/expo/pull/37181) by [@behenate](https://github.com/behenate))
31
+ - [iOS] Fix player getting stuck in `loading` state for null sources. ([#37183](https://github.com/expo/expo/pull/37183) by [@behenate](https://github.com/behenate))
32
+
13
33
  ## 2.1.9 — 2025-05-08
14
34
 
15
35
  ### 🛠 Breaking changes
@@ -4,13 +4,13 @@ plugins {
4
4
  }
5
5
 
6
6
  group = 'host.exp.exponent'
7
- version = '2.1.9'
7
+ version = '2.2.1'
8
8
 
9
9
  android {
10
10
  namespace "expo.modules.video"
11
11
  defaultConfig {
12
12
  versionCode 1
13
- versionName '2.1.9'
13
+ versionName '2.2.1'
14
14
  }
15
15
  }
16
16
 
@@ -21,6 +21,7 @@ import expo.modules.video.enums.ContentFit
21
21
  import expo.modules.video.player.VideoPlayer
22
22
  import expo.modules.video.records.BufferOptions
23
23
  import expo.modules.video.records.SubtitleTrack
24
+ import expo.modules.video.records.AudioTrack
24
25
  import expo.modules.video.records.VideoSource
25
26
  import expo.modules.video.records.VideoThumbnailOptions
26
27
  import expo.modules.video.utils.runWithPiPMisconfigurationSoftHandling
@@ -146,6 +147,21 @@ class VideoModule : Module() {
146
147
  }
147
148
  }
148
149
 
150
+ Property("availableAudioTracks")
151
+ .get { ref: VideoPlayer ->
152
+ ref.audioTracks.availableAudioTracks
153
+ }
154
+
155
+ Property("audioTrack")
156
+ .get { ref: VideoPlayer ->
157
+ ref.audioTracks.currentAudioTrack
158
+ }
159
+ .set { ref: VideoPlayer, audioTrack: AudioTrack? ->
160
+ appContext.mainQueue.launch {
161
+ ref.audioTracks.currentAudioTrack = audioTrack
162
+ }
163
+ }
164
+
149
165
  Property("currentOffsetFromLive")
150
166
  .get { ref: VideoPlayer ->
151
167
  runBlocking(appContext.mainQueue.coroutineContext) {
@@ -347,7 +363,8 @@ private inline fun <reified T : VideoView> ViewDefinitionBuilder<T>.VideoViewCom
347
363
  "onPictureInPictureStart",
348
364
  "onPictureInPictureStop",
349
365
  "onFullscreenEnter",
350
- "onFullscreenExit"
366
+ "onFullscreenExit",
367
+ "onFirstFrameRender"
351
368
  )
352
369
  Prop("player") { view: T, player: VideoPlayer ->
353
370
  view.videoPlayer = player
@@ -369,6 +386,9 @@ private inline fun <reified T : VideoView> ViewDefinitionBuilder<T>.VideoViewCom
369
386
  view.playerView.applyRequiresLinearPlayback(linearPlayback)
370
387
  view.videoPlayer?.requiresLinearPlayback = linearPlayback
371
388
  }
389
+ Prop("useExoShutter") { view: T, useExoShutter: Boolean? ->
390
+ view.useExoShutter = useExoShutter
391
+ }
372
392
  AsyncFunction("enterFullscreen") { view: T ->
373
393
  view.enterFullscreen()
374
394
  }.runOnQueue(Queues.MAIN)
@@ -55,6 +55,8 @@ open class VideoView(context: Context, appContext: AppContext, useTextureView: B
55
55
  private set
56
56
  var showsSubtitlesButton = false
57
57
  private set
58
+ var showsAudioTracksButton = false
59
+ private set
58
60
 
59
61
  private val currentActivity = appContext.throwingActivity
60
62
  private val decorView = currentActivity.window.decorView
@@ -70,10 +72,10 @@ open class VideoView(context: Context, appContext: AppContext, useTextureView: B
70
72
 
71
73
  var useExoShutter: Boolean? = null
72
74
  set(value) {
73
- if (value == false) {
74
- playerView.setShutterBackgroundColor(Color.TRANSPARENT)
75
- } else {
75
+ if (value == true) {
76
76
  playerView.setShutterBackgroundColor(Color.BLACK)
77
+ } else {
78
+ playerView.setShutterBackgroundColor(Color.TRANSPARENT)
77
79
  }
78
80
  applySurfaceViewVisibility()
79
81
  field = value
@@ -154,7 +156,7 @@ open class VideoView(context: Context, appContext: AppContext, useTextureView: B
154
156
  }
155
157
 
156
158
  fun applySurfaceViewVisibility() {
157
- if (useExoShutter == false && shouldHideSurfaceView) {
159
+ if (useExoShutter != true && shouldHideSurfaceView) {
158
160
  playerView.videoSurfaceView?.alpha = 0f
159
161
  } else {
160
162
  playerView.videoSurfaceView?.alpha = 1f
@@ -263,6 +265,7 @@ open class VideoView(context: Context, appContext: AppContext, useTextureView: B
263
265
 
264
266
  override fun onTracksChanged(player: VideoPlayer, tracks: Tracks) {
265
267
  showsSubtitlesButton = player.subtitles.availableSubtitleTracks.isNotEmpty()
268
+ showsAudioTracksButton = player.audioTracks.availableAudioTracks.size > 1
266
269
  playerView.setShowSubtitleButton(showsSubtitlesButton)
267
270
  super.onTracksChanged(player, tracks)
268
271
  }
@@ -64,7 +64,7 @@ internal class FirstFrameEventGenerator(
64
64
 
65
65
  private fun isPlayerSurfaceLayoutValid(): Boolean {
66
66
  // Sometimes the video size announced by the track will is 1px off the render size.
67
- val epsilon = 0.01
67
+ val epsilon = 0.05
68
68
  val player = playerReference.get() ?: run {
69
69
  return false
70
70
  }
@@ -75,13 +75,14 @@ internal class FirstFrameEventGenerator(
75
75
  val surfaceHeight = player.surfaceSize.height
76
76
  val sourceWidth = player.videoSize.width
77
77
  val sourceHeight = player.videoSize.height
78
+ val sourcePixelWidthHeightRatio = player.videoSize.pixelWidthHeightRatio
78
79
 
79
80
  if (surfaceWidth == 0 || surfaceHeight == 0) {
80
81
  return false
81
82
  }
82
83
 
83
84
  val surfaceAspectRatio = surfaceWidth.toFloat() / surfaceHeight
84
- val trackAspectRatio = sourceWidth.toFloat() / sourceHeight
85
+ val trackAspectRatio = sourceWidth.toFloat() / sourceHeight * sourcePixelWidthHeightRatio
85
86
 
86
87
  val videoSizeIsUnknown = sourceWidth == 0 || sourceHeight == 0
87
88
  val hasFillContentFit = currentPlayerView.resizeMode == ContentFit.FILL.toResizeMode()
@@ -6,7 +6,9 @@ import androidx.media3.common.Tracks
6
6
  import androidx.media3.common.util.UnstableApi
7
7
  import expo.modules.video.enums.AudioMixingMode
8
8
  import expo.modules.video.enums.PlayerStatus
9
+ import expo.modules.video.records.AudioTrack
9
10
  import expo.modules.video.records.AvailableSubtitleTracksChangedEventPayload
11
+ import expo.modules.video.records.AvailableAudioTracksChangedEventPayload
10
12
  import expo.modules.video.records.IsPlayingEventPayload
11
13
  import expo.modules.video.records.MutedChangedEventPayload
12
14
  import expo.modules.video.records.PlaybackError
@@ -15,6 +17,7 @@ import expo.modules.video.records.SourceChangedEventPayload
15
17
  import expo.modules.video.records.StatusChangedEventPayload
16
18
  import expo.modules.video.records.SubtitleTrack
17
19
  import expo.modules.video.records.SubtitleTrackChangedEventPayload
20
+ import expo.modules.video.records.AudioTrackChangedEventPayload
18
21
  import expo.modules.video.records.TimeUpdate
19
22
  import expo.modules.video.records.VideoEventPayload
20
23
  import expo.modules.video.records.VideoSource
@@ -74,6 +77,11 @@ sealed class PlayerEvent {
74
77
  override val jsEventPayload = SubtitleTrackChangedEventPayload(subtitleTrack, oldSubtitleTrack)
75
78
  }
76
79
 
80
+ data class AudioTrackChanged(val audioTrack: AudioTrack?, val oldAudioTrack: AudioTrack?) : PlayerEvent() {
81
+ override val name = "audioTrackChange"
82
+ override val jsEventPayload = AudioTrackChangedEventPayload(audioTrack, oldAudioTrack)
83
+ }
84
+
77
85
  data class VideoTrackChanged(val videoTrack: VideoTrack?, val oldVideoTrack: VideoTrack?) : PlayerEvent() {
78
86
  override val name = "videoTrackChange"
79
87
  override val jsEventPayload = VideoTrackChangedEventPayload(videoTrack, oldVideoTrack)
@@ -94,18 +102,28 @@ sealed class PlayerEvent {
94
102
  override val jsEventPayload = AvailableSubtitleTracksChangedEventPayload(availableSubtitleTracks, oldAvailableSubtitleTracks)
95
103
  }
96
104
 
105
+ data class AvailableAudioTracksChanged(
106
+ val availableAudioTracks: List<AudioTrack>,
107
+ val oldAvailableAudioTracks: List<AudioTrack>
108
+ ) : PlayerEvent() {
109
+ override val name = "availableAudioTracksChange"
110
+ override val jsEventPayload = AvailableAudioTracksChangedEventPayload(availableAudioTracks, oldAvailableAudioTracks)
111
+ }
112
+
97
113
  data class VideoSourceLoaded(
98
114
  val videoSource: VideoSource?,
99
115
  val duration: Double,
100
116
  val availableVideoTracks: List<VideoTrack>,
101
- val availableSubtitleTracks: List<SubtitleTrack>
117
+ val availableSubtitleTracks: List<SubtitleTrack>,
118
+ val availableAudioTracks: List<AudioTrack>
102
119
  ) : PlayerEvent() {
103
120
  override val name = "sourceLoad"
104
121
  override val jsEventPayload = VideoSourceLoadedEventPayload(
105
122
  videoSource,
106
123
  duration,
107
124
  availableVideoTracks,
108
- availableSubtitleTracks
125
+ availableSubtitleTracks,
126
+ availableAudioTracks
109
127
  )
110
128
  }
111
129
 
@@ -54,6 +54,7 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
54
54
  private var currentPlayerView = MutableWeakReference<PlayerView?>(null)
55
55
  val loadControl: VideoPlayerLoadControl = VideoPlayerLoadControl.Builder().build()
56
56
  val subtitles: VideoPlayerSubtitles = VideoPlayerSubtitles(this)
57
+ val audioTracks: VideoPlayerAudioTracks = VideoPlayerAudioTracks(this)
57
58
  val trackSelector = DefaultTrackSelector(context)
58
59
 
59
60
  val player = ExoPlayer
@@ -180,13 +181,17 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
180
181
 
181
182
  override fun onTracksChanged(tracks: Tracks) {
182
183
  val oldSubtitleTracks = ArrayList(subtitles.availableSubtitleTracks)
184
+ val oldAudioTracks = ArrayList(audioTracks.availableAudioTracks)
183
185
  val oldCurrentTrack = subtitles.currentSubtitleTrack
186
+ val oldCurrentAudioTrack = audioTracks.currentAudioTrack
184
187
 
185
188
  // Emit the tracks change event to update the subtitles
186
189
  sendEvent(PlayerEvent.TracksChanged(tracks))
187
190
 
188
191
  val newSubtitleTracks = subtitles.availableSubtitleTracks
192
+ val newAudioTracks = audioTracks.availableAudioTracks
189
193
  val newCurrentSubtitleTrack = subtitles.currentSubtitleTrack
194
+ val newCurrentAudioTrack = audioTracks.currentAudioTrack
190
195
  availableVideoTracks = tracks.toVideoTracks()
191
196
 
192
197
  if (isLoadingNewSource) {
@@ -195,7 +200,8 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
195
200
  commitedSource,
196
201
  this@VideoPlayer.player.duration / 1000.0,
197
202
  availableVideoTracks,
198
- newSubtitleTracks
203
+ newSubtitleTracks,
204
+ newAudioTracks
199
205
  )
200
206
  )
201
207
  isLoadingNewSource = false
@@ -204,18 +210,27 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
204
210
  if (!oldSubtitleTracks.toArray().contentEquals(newSubtitleTracks.toArray())) {
205
211
  sendEvent(PlayerEvent.AvailableSubtitleTracksChanged(newSubtitleTracks, oldSubtitleTracks))
206
212
  }
213
+ if (!oldAudioTracks.toArray().contentEquals(newAudioTracks.toArray())) {
214
+ sendEvent(PlayerEvent.AvailableAudioTracksChanged(newAudioTracks, oldAudioTracks))
215
+ }
207
216
  if (oldCurrentTrack != newCurrentSubtitleTrack) {
208
217
  sendEvent(PlayerEvent.SubtitleTrackChanged(newCurrentSubtitleTrack, oldCurrentTrack))
209
218
  }
219
+ if (oldCurrentAudioTrack != newCurrentAudioTrack) {
220
+ sendEvent(PlayerEvent.AudioTrackChanged(newCurrentAudioTrack, oldCurrentAudioTrack))
221
+ }
210
222
  super.onTracksChanged(tracks)
211
223
  }
212
224
 
213
225
  override fun onTrackSelectionParametersChanged(parameters: TrackSelectionParameters) {
214
226
  val oldTrack = subtitles.currentSubtitleTrack
227
+ val oldAudioTrack = audioTracks.currentAudioTrack
215
228
  sendEvent(PlayerEvent.TrackSelectionParametersChanged(parameters))
216
229
 
217
230
  val newTrack = subtitles.currentSubtitleTrack
231
+ val newAudioTrack = audioTracks.currentAudioTrack
218
232
  sendEvent(PlayerEvent.SubtitleTrackChanged(newTrack, oldTrack))
233
+ sendEvent(PlayerEvent.AudioTrackChanged(newAudioTrack, oldAudioTrack))
219
234
  super.onTrackSelectionParametersChanged(parameters)
220
235
  }
221
236
 
@@ -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.AudioTrack
13
+ import java.lang.ref.WeakReference
14
+
15
+ @OptIn(UnstableApi::class)
16
+ class VideoPlayerAudioTracks(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 currentAudioTrackFormat: Format? = null
24
+ private var currentOverride: TrackSelectionOverride? = null
25
+
26
+ var currentAudioTrack: AudioTrack?
27
+ get() {
28
+ return AudioTrack.fromFormat(currentAudioTrackFormat)
29
+ }
30
+ set(value) {
31
+ applyAudioTrack(value)
32
+ }
33
+ val availableAudioTracks = arrayListOf<AudioTrack>()
34
+
35
+ init {
36
+ owner.addListener(this)
37
+ }
38
+
39
+ fun setAudioTracksEnabled(enabled: Boolean) {
40
+ val currentParams = videoPlayer?.player?.trackSelectionParameters ?: return
41
+ var params = currentParams.buildUpon().setTrackTypeDisabled(C.TRACK_TYPE_AUDIO, !enabled).build()
42
+ if (!enabled) {
43
+ params = params.buildUpon().clearOverridesOfType(C.TRACK_TYPE_AUDIO).build()
44
+ }
45
+ videoPlayer?.player?.trackSelectionParameters = params
46
+ }
47
+
48
+ // VideoPlayerListener
49
+ override fun onTrackSelectionParametersChanged(player: VideoPlayer, trackSelectionParameters: TrackSelectionParameters) {
50
+ currentAudioTrackFormat = findSelectedAudioFormat()
51
+ super.onTrackSelectionParametersChanged(player, trackSelectionParameters)
52
+ }
53
+
54
+ override fun onTracksChanged(player: VideoPlayer, tracks: Tracks) {
55
+ formatsToGroups.clear()
56
+ availableAudioTracks.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.isAudio(format.sampleMimeType)) {
62
+ formatsToGroups[format] = group.mediaTrackGroup to i
63
+ val track = AudioTrack.fromFormat(format) ?: continue
64
+ availableAudioTracks.add(track)
65
+ }
66
+ }
67
+ }
68
+ currentAudioTrackFormat = findSelectedAudioFormat()
69
+ super.onTracksChanged(player, tracks)
70
+ }
71
+
72
+ // Private methods
73
+ private fun applyAudioTrack(audioTrack: AudioTrack?) {
74
+ val player = videoPlayer?.player ?: return
75
+ var newParameters: TrackSelectionParameters = player.trackSelectionParameters
76
+ currentOverride?.let { override ->
77
+ newParameters = newParameters.buildUpon().clearOverridesOfType(C.TRACK_TYPE_AUDIO).build()
78
+ }
79
+ if (audioTrack == null) {
80
+ player.trackSelectionParameters = newParameters
81
+ setAudioTracksEnabled(false)
82
+ currentOverride = null
83
+ return
84
+ }
85
+ val format = formatsToGroups.keys.firstOrNull {
86
+ it.id == audioTrack.id
87
+ }
88
+ format?.let {
89
+ formatsToGroups[it]?.let { subtitlePair ->
90
+ val trackSelectionOverride = TrackSelectionOverride(subtitlePair.first, subtitlePair.second)
91
+ newParameters = newParameters.buildUpon().addOverride(trackSelectionOverride).build()
92
+ player.trackSelectionParameters = newParameters
93
+ setAudioTracksEnabled(true)
94
+ currentOverride = trackSelectionOverride
95
+ }
96
+ }
97
+ }
98
+
99
+ private fun findSelectedAudioFormat(): Format? {
100
+ val trackSelectionParameters = videoPlayer?.player?.trackSelectionParameters
101
+ val preferredAudioLanguages = trackSelectionParameters?.preferredAudioLanguages
102
+ val overriddenFormat: Format? = trackSelectionParameters?.overrides?.let {
103
+ for ((group, trackSelectionOverride) in it) {
104
+ if (group.type == C.TRACK_TYPE_AUDIO) {
105
+ // For audioTracks only one index will be replaced
106
+ return@let trackSelectionOverride.trackIndices.firstOrNull()?.let { index ->
107
+ group.getFormat(index)
108
+ }
109
+ }
110
+ }
111
+ return@let null
112
+ }
113
+
114
+ val preferredFormat: Format? = preferredAudioLanguages?.let { preferredAudioLanguages ->
115
+ for (preferredLanguage in preferredAudioLanguages) {
116
+ return@let formatsToGroups.keys.firstOrNull {
117
+ it.language == preferredLanguage
118
+ }
119
+ }
120
+ return@let null
121
+ }
122
+
123
+ return overriddenFormat ?: preferredFormat
124
+ }
125
+ }
@@ -29,6 +29,27 @@ class SubtitleTrack(
29
29
  }
30
30
  }
31
31
 
32
+ class AudioTrack(
33
+ @Field val id: String,
34
+ @Field val language: String?,
35
+ @Field val label: String?
36
+ ) : Record, Serializable {
37
+ companion object {
38
+ fun fromFormat(format: Format?): AudioTrack? {
39
+ format ?: return null
40
+ val id = format.id ?: return null
41
+ val language = format.language
42
+ val label = language?.let { Locale(it).displayLanguage } ?: "Unknown"
43
+
44
+ return AudioTrack(
45
+ id = id,
46
+ language = language,
47
+ label = label
48
+ )
49
+ }
50
+ }
51
+ }
52
+
32
53
  @OptIn(UnstableApi::class)
33
54
  class VideoTrack(
34
55
  @Field val id: String,
@@ -50,6 +50,11 @@ class SubtitleTrackChangedEventPayload(
50
50
  @Field val oldSubtitleTrack: SubtitleTrack?
51
51
  ) : VideoEventPayload
52
52
 
53
+ class AudioTrackChangedEventPayload(
54
+ @Field val audioTrack: AudioTrack?,
55
+ @Field val oldAudioTrack: AudioTrack?
56
+ ) : VideoEventPayload
57
+
53
58
  class VideoTrackChangedEventPayload(
54
59
  @Field val videoTrack: VideoTrack?,
55
60
  @Field val oldVideoTrack: VideoTrack?
@@ -60,9 +65,15 @@ class AvailableSubtitleTracksChangedEventPayload(
60
65
  @Field val oldAvailableSubtitleTracks: List<SubtitleTrack>
61
66
  ) : VideoEventPayload
62
67
 
68
+ class AvailableAudioTracksChangedEventPayload(
69
+ @Field val availableAudioTracks: List<AudioTrack>,
70
+ @Field val oldAvailableAudioTracks: List<AudioTrack>
71
+ ) : VideoEventPayload
72
+
63
73
  class VideoSourceLoadedEventPayload(
64
74
  @Field val videoSource: VideoSource?,
65
75
  @Field val duration: Double,
66
76
  @Field val availableVideoTracks: List<VideoTrack>,
67
- @Field val availableSubtitleTracks: List<SubtitleTrack>
77
+ @Field val availableSubtitleTracks: List<SubtitleTrack>,
78
+ @Field val availableAudioTracks: List<AudioTrack>
68
79
  ) : VideoEventPayload
@@ -142,6 +142,21 @@ export declare class VideoPlayer extends SharedObject<VideoPlayerEvents> {
142
142
  * @platform ios
143
143
  */
144
144
  subtitleTrack: SubtitleTrack | null;
145
+ /**
146
+ * Specifies the audio track currently played by the player. `null` when no audio is played.
147
+ *
148
+ * @default null
149
+ * @platform android
150
+ * @platform ios
151
+ */
152
+ audioTrack: AudioTrack | null;
153
+ /**
154
+ * An array of audio tracks available for the current video.
155
+ *
156
+ * @platform android
157
+ * @platform ios
158
+ */
159
+ readonly availableAudioTracks: AudioTrack[];
145
160
  /**
146
161
  * An array of subtitle tracks available for the current video.
147
162
  *
@@ -499,4 +514,19 @@ export type VideoSize = {
499
514
  */
500
515
  height: number;
501
516
  };
517
+ export type AudioTrack = {
518
+ /**
519
+ * A string used by expo-video to identify the audio track.
520
+ * @platform android
521
+ */
522
+ id: string;
523
+ /**
524
+ * Language of the audio track. For example, 'en', 'pl', 'de'.
525
+ */
526
+ language: string;
527
+ /**
528
+ * Label of the audio track in the language of the device.
529
+ */
530
+ label: string;
531
+ };
502
532
  //# 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":"","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 * Note that frame accurate seeking may incur additional decoding delay which can impact seeking performance.\n * Consider using the [`seekBy`](#seekbyseconds) function if the time does not have to be set precisely.\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 * Specifies the video track currently played by the player. `null` when no video is displayed.\n *\n * @default null\n * @platform android\n * @platform ios\n */\n readonly videoTrack: VideoTrack | null;\n\n /**\n * An array of video tracks available for the current video.\n *\n * > On iOS, when using a HLS source, make sure that the uri contains `.m3u8` extension or that the [`contentType`](#contenttype) property of the [`VideoSource`](#videosource) has been set to `'hls'`. Otherwise, the video tracks will not be available.\n *\n * @platform android\n * @platform ios\n */\n readonly availableVideoTracks: VideoTrack[];\n\n /**\n * Initializes a new video player instance with the given source.\n *\n * @param source The source of the video to be played.\n * @param useSynchronousReplace Optional parameter, when `true` `source` from the first parameter will be loaded on the main thread.\n * @hidden\n */\n constructor(source: VideoSource, useSynchronousReplace?: boolean);\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 * > On iOS, this method loads the asset data synchronously on the UI thread and can block it for extended periods of time.\n * > Use `replaceAsync` to load the asset asynchronously and avoid UI lags.\n *\n * > This method will be deprecated in the future.\n */\n replace(source: VideoSource, disableWarning?: boolean): void;\n\n /**\n * Replaces the current source with a new one, while offloading loading of the asset to a different thread.\n *\n * > On Android and Web, this method is equivalent to `replace`.\n */\n replaceAsync(source: VideoSource): Promise<void>;\n\n /**\n * Seeks the playback by the given number of seconds. The time to which the player seeks may differ from the specified requested time for efficiency,\n * depending on the encoding and what is currently buffered by the player. Use this function to implement playback controls that seek by specific amount of time,\n * in which case, the actual time usually does not have to be precise. For frame accurate seeking, use the [`currentTime`](#currenttime) property.\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 android\n * @platform ios\n */\n generateThumbnailsAsync(\n times: number | number[],\n options?: VideoThumbnailOptions\n ): Promise<VideoThumbnail[]>;\n}\n\n/**\n * Additional options for video thumbnails generation.\n */\nexport type VideoThumbnailOptions = {\n /**\n * If provided, the generated thumbnail will not exceed this width in pixels, preserving its aspect ratio.\n * @platform android\n * @platform ios\n */\n maxWidth?: number;\n\n /**\n * If provided, the generated thumbnail will not exceed this height in pixels, preserving its aspect ratio.\n * @platform android\n * @platform ios\n */\n maxHeight?: number;\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 * Specifies whether the player should use caching for the video.\n * > Due to platform limitations, the cache cannot be used with HLS video sources on iOS. Caching DRM-protected videos is not supported on Android and iOS.\n * @default false\n * @platform android\n * @platform ios\n */\n useCaching?: boolean;\n\n /**\n * Specifies the content type of the video source. When set to `'auto'`, the player will try to automatically determine the content type.\n *\n * You should use this property when playing HLS, SmoothStreaming or DASH videos from an uri, which does not contain a standardized extension for the corresponding media type.\n * @default 'auto'\n * @platform android\n * @platform ios\n */\n contentType?: ContentType;\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 content type of the source.\n *\n * - `auto`: The player will automatically determine the content type of the video.\n * - `progressive`: The player will use progressive download content type. This is the default `ContentType` when the uri does not contain an extension.\n * - `hls`: The player will use HLS content type.\n * - `dash`: The player will use DASH content type (Android-only).\n * - `smoothStreaming`: The player will use SmoothStreaming content type (Android-only).\n *\n * @default `auto`\n */\nexport type ContentType = 'auto' | 'progressive' | 'hls' | 'dash' | 'smoothStreaming';\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\n/**\n * Specifies a VideoTrack loaded from a [`VideoSource`](#videosource).\n */\nexport type VideoTrack = {\n /**\n * The id of the video track.\n *\n * > This field is platform-specific and may return different depending on the operating system.\n */\n id: string;\n\n /**\n * Size of the video track.\n */\n size: VideoSize;\n\n /**\n * MimeType of the video track or null if unknown.\n */\n mimeType: string | null;\n\n /**\n * Indicates whether the video track format is supported by the device.\n *\n * @platform android\n */\n isSupported: boolean;\n\n /**\n * Specifies the bitrate in bits per second. This is the peak bitrate if known, or else the average bitrate if known, or else null.\n */\n bitrate: number | null;\n\n /**\n * Specifies the frame rate of the video track in frames per second.\n */\n frameRate: number | null;\n};\n\n/**\n * Specifies the size of a video track.\n */\nexport type VideoSize = {\n /**\n * Width of the video track in pixels.\n */\n width: number;\n /**\n * Height of the video track in pixels.\n */\n height: number;\n};\n"]}
1
+ {"version":3,"file":"VideoPlayer.types.js","sourceRoot":"","sources":["../src/VideoPlayer.types.ts"],"names":[],"mappings":"","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 * Note that frame accurate seeking may incur additional decoding delay which can impact seeking performance.\n * Consider using the [`seekBy`](#seekbyseconds) function if the time does not have to be set precisely.\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 * Specifies the audio track currently played by the player. `null` when no audio is played.\n *\n * @default null\n * @platform android\n * @platform ios\n */\n audioTrack: AudioTrack | null;\n\n /**\n * An array of audio tracks available for the current video.\n *\n * @platform android\n * @platform ios\n */\n readonly availableAudioTracks: AudioTrack[];\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 * Specifies the video track currently played by the player. `null` when no video is displayed.\n *\n * @default null\n * @platform android\n * @platform ios\n */\n readonly videoTrack: VideoTrack | null;\n\n /**\n * An array of video tracks available for the current video.\n *\n * > On iOS, when using a HLS source, make sure that the uri contains `.m3u8` extension or that the [`contentType`](#contenttype) property of the [`VideoSource`](#videosource) has been set to `'hls'`. Otherwise, the video tracks will not be available.\n *\n * @platform android\n * @platform ios\n */\n readonly availableVideoTracks: VideoTrack[];\n\n /**\n * Initializes a new video player instance with the given source.\n *\n * @param source The source of the video to be played.\n * @param useSynchronousReplace Optional parameter, when `true` `source` from the first parameter will be loaded on the main thread.\n * @hidden\n */\n constructor(source: VideoSource, useSynchronousReplace?: boolean);\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 * > On iOS, this method loads the asset data synchronously on the UI thread and can block it for extended periods of time.\n * > Use `replaceAsync` to load the asset asynchronously and avoid UI lags.\n *\n * > This method will be deprecated in the future.\n */\n replace(source: VideoSource, disableWarning?: boolean): void;\n\n /**\n * Replaces the current source with a new one, while offloading loading of the asset to a different thread.\n *\n * > On Android and Web, this method is equivalent to `replace`.\n */\n replaceAsync(source: VideoSource): Promise<void>;\n\n /**\n * Seeks the playback by the given number of seconds. The time to which the player seeks may differ from the specified requested time for efficiency,\n * depending on the encoding and what is currently buffered by the player. Use this function to implement playback controls that seek by specific amount of time,\n * in which case, the actual time usually does not have to be precise. For frame accurate seeking, use the [`currentTime`](#currenttime) property.\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 android\n * @platform ios\n */\n generateThumbnailsAsync(\n times: number | number[],\n options?: VideoThumbnailOptions\n ): Promise<VideoThumbnail[]>;\n}\n\n/**\n * Additional options for video thumbnails generation.\n */\nexport type VideoThumbnailOptions = {\n /**\n * If provided, the generated thumbnail will not exceed this width in pixels, preserving its aspect ratio.\n * @platform android\n * @platform ios\n */\n maxWidth?: number;\n\n /**\n * If provided, the generated thumbnail will not exceed this height in pixels, preserving its aspect ratio.\n * @platform android\n * @platform ios\n */\n maxHeight?: number;\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 * Specifies whether the player should use caching for the video.\n * > Due to platform limitations, the cache cannot be used with HLS video sources on iOS. Caching DRM-protected videos is not supported on Android and iOS.\n * @default false\n * @platform android\n * @platform ios\n */\n useCaching?: boolean;\n\n /**\n * Specifies the content type of the video source. When set to `'auto'`, the player will try to automatically determine the content type.\n *\n * You should use this property when playing HLS, SmoothStreaming or DASH videos from an uri, which does not contain a standardized extension for the corresponding media type.\n * @default 'auto'\n * @platform android\n * @platform ios\n */\n contentType?: ContentType;\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 content type of the source.\n *\n * - `auto`: The player will automatically determine the content type of the video.\n * - `progressive`: The player will use progressive download content type. This is the default `ContentType` when the uri does not contain an extension.\n * - `hls`: The player will use HLS content type.\n * - `dash`: The player will use DASH content type (Android-only).\n * - `smoothStreaming`: The player will use SmoothStreaming content type (Android-only).\n *\n * @default `auto`\n */\nexport type ContentType = 'auto' | 'progressive' | 'hls' | 'dash' | 'smoothStreaming';\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\n/**\n * Specifies a VideoTrack loaded from a [`VideoSource`](#videosource).\n */\nexport type VideoTrack = {\n /**\n * The id of the video track.\n *\n * > This field is platform-specific and may return different depending on the operating system.\n */\n id: string;\n\n /**\n * Size of the video track.\n */\n size: VideoSize;\n\n /**\n * MimeType of the video track or null if unknown.\n */\n mimeType: string | null;\n\n /**\n * Indicates whether the video track format is supported by the device.\n *\n * @platform android\n */\n isSupported: boolean;\n\n /**\n * Specifies the bitrate in bits per second. This is the peak bitrate if known, or else the average bitrate if known, or else null.\n */\n bitrate: number | null;\n\n /**\n * Specifies the frame rate of the video track in frames per second.\n */\n frameRate: number | null;\n};\n\n/**\n * Specifies the size of a video track.\n */\nexport type VideoSize = {\n /**\n * Width of the video track in pixels.\n */\n width: number;\n /**\n * Height of the video track in pixels.\n */\n height: number;\n};\n\nexport type AudioTrack = {\n /**\n * A string used by expo-video to identify the audio track.\n * @platform android\n */\n id: string;\n\n /**\n * Language of the audio track. For example, 'en', 'pl', 'de'.\n */\n language: string;\n\n /**\n * Label of the audio track in the language of the device.\n */\n label: string;\n};\n"]}
@@ -1,4 +1,4 @@
1
- import type { BufferOptions, PlayerError, VideoPlayerStatus, VideoSource, VideoPlayer, SubtitleTrack, AudioMixingMode, VideoTrack } from './VideoPlayer.types';
1
+ import type { BufferOptions, PlayerError, VideoPlayerStatus, VideoSource, VideoPlayer, SubtitleTrack, AudioMixingMode, VideoTrack, AudioTrack } from './VideoPlayer.types';
2
2
  import type { VideoPlayerEvents } from './VideoPlayerEvents.types';
3
3
  import { VideoThumbnail } from './VideoThumbnail';
4
4
  export declare function useVideoPlayer(source: VideoSource, setup?: (player: VideoPlayer) => void): VideoPlayer;
@@ -30,6 +30,8 @@ export default class VideoPlayerWeb extends globalThis.expo.SharedObject<VideoPl
30
30
  bufferOptions: BufferOptions;
31
31
  subtitleTrack: SubtitleTrack | null;
32
32
  availableSubtitleTracks: SubtitleTrack[];
33
+ audioTrack: AudioTrack | null;
34
+ availableAudioTracks: AudioTrack[];
33
35
  videoTrack: VideoTrack | null;
34
36
  availableVideoTracks: VideoTrack[];
35
37
  set muted(value: boolean);