expo-libvlc-player 0.1.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/.eslintrc.js +2 -0
- package/README.md +107 -0
- package/android/.gradle/9.0-milestone-1/checksums/checksums.lock +0 -0
- package/android/.gradle/9.0-milestone-1/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.0-milestone-1/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.0-milestone-1/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/config.properties +2 -0
- package/android/.gradle/ideaInitScripts/ijtgtmapper.gradle +3 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/.idea/AndroidProjectSystem.xml +6 -0
- package/android/.idea/android.iml +9 -0
- package/android/.idea/caches/deviceStreaming.xml +835 -0
- package/android/.idea/deviceManager.xml +13 -0
- package/android/.idea/gradle.xml +13 -0
- package/android/.idea/misc.xml +3 -0
- package/android/.idea/modules.xml +8 -0
- package/android/.idea/runConfigurations.xml +17 -0
- package/android/.idea/vcs.xml +6 -0
- package/android/.idea/workspace.xml +72 -0
- package/android/build.gradle +53 -0
- package/android/local.properties +8 -0
- package/android/proguard-rules.pro +19 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/expo/modules/libvlcplayer/AudioFocusManager.kt +210 -0
- package/android/src/main/java/expo/modules/libvlcplayer/VlcPlayerManager.kt +82 -0
- package/android/src/main/java/expo/modules/libvlcplayer/VlcPlayerModule.kt +129 -0
- package/android/src/main/java/expo/modules/libvlcplayer/VlcPlayerView.kt +328 -0
- package/android/src/main/java/expo/modules/libvlcplayer/enums/AudioMixingMode.kt +20 -0
- package/app.plugin.js +1 -0
- package/build/VlcPlayer.types.d.ts +278 -0
- package/build/VlcPlayer.types.d.ts.map +1 -0
- package/build/VlcPlayer.types.js +2 -0
- package/build/VlcPlayer.types.js.map +1 -0
- package/build/VlcPlayerModule.d.ts +6 -0
- package/build/VlcPlayerModule.d.ts.map +1 -0
- package/build/VlcPlayerModule.js +4 -0
- package/build/VlcPlayerModule.js.map +1 -0
- package/build/VlcPlayerView.d.ts +5 -0
- package/build/VlcPlayerView.d.ts.map +1 -0
- package/build/VlcPlayerView.js +36 -0
- package/build/VlcPlayerView.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +5 -0
- package/build/index.js.map +1 -0
- package/build/utils/props.d.ts +3 -0
- package/build/utils/props.d.ts.map +1 -0
- package/build/utils/props.js +11 -0
- package/build/utils/props.js.map +1 -0
- package/eslint.config.js +50 -0
- package/expo-module.config.json +16 -0
- package/ios/Enums/AudioMixingMode.swift +35 -0
- package/ios/ExpoLibVlcPlayer.podspec +29 -0
- package/ios/VlcPlayerManager.swift +116 -0
- package/ios/VlcPlayerModule.swift +110 -0
- package/ios/VlcPlayerView.swift +321 -0
- package/package.json +49 -0
- package/plugin/build/withExpoLibVlcPlayer.d.ts +3 -0
- package/plugin/build/withExpoLibVlcPlayer.js +18 -0
- package/plugin/src/withExpoLibVlcPlayer.ts +21 -0
- package/plugin/tsconfig.json +9 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/src/VlcPlayer.types.ts +291 -0
- package/src/VlcPlayerModule.ts +7 -0
- package/src/VlcPlayerView.tsx +73 -0
- package/src/index.ts +4 -0
- package/src/utils/props.ts +20 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import AVFoundation
|
|
2
|
+
import ExpoModulesCore
|
|
3
|
+
import MobileVLCKit
|
|
4
|
+
|
|
5
|
+
let defaultPlayerRate: Float = 1.0
|
|
6
|
+
let minPlayerVolume: Int = 0
|
|
7
|
+
let maxPlayerVolume: Int = 100
|
|
8
|
+
let playerVolumeStep: Int = 10
|
|
9
|
+
|
|
10
|
+
private let useTextureViews = false
|
|
11
|
+
private let enableSubtitles = true
|
|
12
|
+
|
|
13
|
+
class VlcPlayerView: ExpoView, VLCMediaPlayerDelegate {
|
|
14
|
+
var mediaPlayer: VLCMediaPlayer?
|
|
15
|
+
|
|
16
|
+
private var uri: String = ""
|
|
17
|
+
private var options: [String] = []
|
|
18
|
+
private var previousVolume: Int = maxPlayerVolume
|
|
19
|
+
private var shouldRepeat: Bool = false
|
|
20
|
+
var audioMixingMode: AudioMixingMode = .auto
|
|
21
|
+
var playInBackground: Bool = false
|
|
22
|
+
private var autoplay: Bool = true
|
|
23
|
+
|
|
24
|
+
private let onBuffering = EventDispatcher()
|
|
25
|
+
private let onPlaying = EventDispatcher()
|
|
26
|
+
private let onPaused = EventDispatcher()
|
|
27
|
+
private let onStopped = EventDispatcher()
|
|
28
|
+
private let onEnded = EventDispatcher()
|
|
29
|
+
private let onRepeat = EventDispatcher()
|
|
30
|
+
private let onWarn = EventDispatcher()
|
|
31
|
+
private let onError = EventDispatcher()
|
|
32
|
+
private let onPositionChanged = EventDispatcher()
|
|
33
|
+
private let onLoad = EventDispatcher()
|
|
34
|
+
let onBackground = EventDispatcher()
|
|
35
|
+
|
|
36
|
+
required init(appContext: AppContext? = nil) {
|
|
37
|
+
super.init(appContext: appContext)
|
|
38
|
+
|
|
39
|
+
backgroundColor = UIColor.black
|
|
40
|
+
|
|
41
|
+
VlcPlayerManager.shared.registerView(view: self)
|
|
42
|
+
|
|
43
|
+
clipsToBounds = true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
func mediaPlayerStateChanged(_: Notification) {
|
|
47
|
+
guard let player = mediaPlayer else { return }
|
|
48
|
+
|
|
49
|
+
switch player.state {
|
|
50
|
+
case .buffering:
|
|
51
|
+
onBuffering([:])
|
|
52
|
+
|
|
53
|
+
var audioTracks: [[String: Any]] = []
|
|
54
|
+
|
|
55
|
+
if let audios = player.audioTrackNames as? [String] {
|
|
56
|
+
if let audioIndexes = player.audioTrackIndexes as? [NSNumber] {
|
|
57
|
+
for (index, name) in audios.enumerated() {
|
|
58
|
+
let trackId = audioIndexes[index].intValue
|
|
59
|
+
if trackId != -1 && name != "Disable" {
|
|
60
|
+
audioTracks.append([
|
|
61
|
+
"id": trackId,
|
|
62
|
+
"name": name,
|
|
63
|
+
])
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
var subtitleTracks: [[String: Any]] = []
|
|
70
|
+
|
|
71
|
+
if let subtitles = player.videoSubTitlesNames as? [String] {
|
|
72
|
+
if let subtitleIndexes = player.videoSubTitlesIndexes as? [NSNumber] {
|
|
73
|
+
for (index, name) in subtitles.enumerated() {
|
|
74
|
+
let trackId = subtitleIndexes[index].intValue
|
|
75
|
+
subtitleTracks.append([
|
|
76
|
+
"id": trackId,
|
|
77
|
+
"name": name,
|
|
78
|
+
])
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let video = player.videoSize
|
|
84
|
+
let ratio = player.videoAspectRatio
|
|
85
|
+
var length = 0
|
|
86
|
+
if let media = player.media {
|
|
87
|
+
length = Int(media.length.intValue)
|
|
88
|
+
}
|
|
89
|
+
let tracks = [
|
|
90
|
+
"audio": audioTracks,
|
|
91
|
+
"subtitle": subtitleTracks,
|
|
92
|
+
]
|
|
93
|
+
let seekable = player.isSeekable
|
|
94
|
+
|
|
95
|
+
let videoInfo: [String: Any] = [
|
|
96
|
+
"width": Int(video.width),
|
|
97
|
+
"height": Int(video.height),
|
|
98
|
+
"aspectRatio": ratio,
|
|
99
|
+
"duration": Double(length),
|
|
100
|
+
"tracks": tracks,
|
|
101
|
+
"seekable": seekable,
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
onLoad(videoInfo)
|
|
105
|
+
case .playing:
|
|
106
|
+
onPlaying([:])
|
|
107
|
+
VlcPlayerManager.shared.setAppropriateAudioSessionOrWarn()
|
|
108
|
+
case .paused:
|
|
109
|
+
onPaused([:])
|
|
110
|
+
VlcPlayerManager.shared.setAppropriateAudioSessionOrWarn()
|
|
111
|
+
case .stopped:
|
|
112
|
+
onStopped([:])
|
|
113
|
+
VlcPlayerManager.shared.setAppropriateAudioSessionOrWarn()
|
|
114
|
+
|
|
115
|
+
let position = 0.0
|
|
116
|
+
onPositionChanged(["position": position])
|
|
117
|
+
case .ended:
|
|
118
|
+
onEnded([:])
|
|
119
|
+
|
|
120
|
+
let manualRepeat = !options.hasRepeatOptions() && shouldRepeat
|
|
121
|
+
|
|
122
|
+
if manualRepeat {
|
|
123
|
+
player.stop()
|
|
124
|
+
player.play()
|
|
125
|
+
onRepeat([:])
|
|
126
|
+
}
|
|
127
|
+
case .error:
|
|
128
|
+
let error = ["error": "Player encountered an error"]
|
|
129
|
+
onError(error)
|
|
130
|
+
default:
|
|
131
|
+
break
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func mediaPlayerPositionChanged(_: Notification) {
|
|
136
|
+
guard let player = mediaPlayer else { return }
|
|
137
|
+
|
|
138
|
+
let position = ["position": player.position]
|
|
139
|
+
onPositionChanged(position)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
func createPlayer() {
|
|
143
|
+
destroyPlayer()
|
|
144
|
+
|
|
145
|
+
mediaPlayer = VLCMediaPlayer(options: options)
|
|
146
|
+
|
|
147
|
+
if let player = mediaPlayer {
|
|
148
|
+
player.delegate = self
|
|
149
|
+
player.drawable = self
|
|
150
|
+
|
|
151
|
+
guard let url = URL(string: uri) else {
|
|
152
|
+
let error = ["error": "Invalid URI, media could not be set"]
|
|
153
|
+
onError(error)
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
player.media = VLCMedia(url: url)
|
|
158
|
+
|
|
159
|
+
if autoplay {
|
|
160
|
+
player.play()
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
func destroyPlayer() {
|
|
166
|
+
if let player = mediaPlayer {
|
|
167
|
+
player.stop()
|
|
168
|
+
mediaPlayer = nil
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
func setUri(_ uri: String) {
|
|
173
|
+
let old = self.uri
|
|
174
|
+
self.uri = uri
|
|
175
|
+
|
|
176
|
+
if uri != old {
|
|
177
|
+
createPlayer()
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
func setSubtitle(_ subtitle: [String: Any]?) {
|
|
182
|
+
guard let player = mediaPlayer,
|
|
183
|
+
let subtitle = subtitle,
|
|
184
|
+
!subtitle.isEmpty else { return }
|
|
185
|
+
|
|
186
|
+
let uri = subtitle["uri"] as? String ?? ""
|
|
187
|
+
|
|
188
|
+
guard let url = URL(string: uri) else {
|
|
189
|
+
let error = ["error": "Invalid URI, subtitle could not be set"]
|
|
190
|
+
onError(error)
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let enable = subtitle["enable"] as? Bool ?? enableSubtitles
|
|
195
|
+
|
|
196
|
+
player.addPlaybackSlave(url, type: .subtitle, enforce: enable)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
func setOptions(_ options: [String]) {
|
|
200
|
+
let old = self.options
|
|
201
|
+
self.options = options
|
|
202
|
+
|
|
203
|
+
if options != old {
|
|
204
|
+
createPlayer()
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
func setVolume(_ volume: Int) {
|
|
209
|
+
guard let player = mediaPlayer else { return }
|
|
210
|
+
|
|
211
|
+
let newVolume = max(minPlayerVolume, min(maxPlayerVolume, volume))
|
|
212
|
+
previousVolume = newVolume
|
|
213
|
+
|
|
214
|
+
player.audio?.volume = Int32(newVolume)
|
|
215
|
+
VlcPlayerManager.shared.setAppropriateAudioSessionOrWarn()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
func setMute(_ mute: Bool) {
|
|
219
|
+
guard let player = mediaPlayer else { return }
|
|
220
|
+
|
|
221
|
+
let newVolume = !mute ?
|
|
222
|
+
max(playerVolumeStep, min(maxPlayerVolume, previousVolume)) :
|
|
223
|
+
minPlayerVolume
|
|
224
|
+
|
|
225
|
+
player.audio?.volume = Int32(newVolume)
|
|
226
|
+
VlcPlayerManager.shared.setAppropriateAudioSessionOrWarn()
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
func setRate(_ rate: Float) {
|
|
230
|
+
guard let player = mediaPlayer else { return }
|
|
231
|
+
|
|
232
|
+
player.rate = rate
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
func setTracks(_ tracks: [String: Any]?) {
|
|
236
|
+
guard let player = mediaPlayer,
|
|
237
|
+
let tracks = tracks,
|
|
238
|
+
!tracks.isEmpty else { return }
|
|
239
|
+
|
|
240
|
+
let audioTrack = tracks["audio"] as? Int ?? -1
|
|
241
|
+
let subtitleTrack = tracks["subtitle"] as? Int ?? -1
|
|
242
|
+
|
|
243
|
+
player.currentAudioTrackIndex = Int32(audioTrack)
|
|
244
|
+
player.currentVideoSubTitleIndex = Int32(subtitleTrack)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
func setRepeat(_ shouldRepeat: Bool) {
|
|
248
|
+
if shouldRepeat && options.hasRepeatOptions() {
|
|
249
|
+
let warn = ["warn": "Repeat already enabled in options"]
|
|
250
|
+
return onWarn(warn)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
self.shouldRepeat = shouldRepeat
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
func setAspectRatio(_ aspectRatio: String?) {
|
|
257
|
+
guard let player = mediaPlayer,
|
|
258
|
+
let aspectRatio = aspectRatio else { return }
|
|
259
|
+
|
|
260
|
+
if let cString = strdup(aspectRatio) {
|
|
261
|
+
player.videoAspectRatio = cString
|
|
262
|
+
free(cString)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
func setAudioMixingMode(_ audioMixingMode: AudioMixingMode) {
|
|
267
|
+
self.audioMixingMode = audioMixingMode
|
|
268
|
+
VlcPlayerManager.shared.setAppropriateAudioSessionOrWarn()
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
func setPlayInBackground(_ playInBackground: Bool) {
|
|
272
|
+
self.playInBackground = playInBackground
|
|
273
|
+
VlcPlayerManager.shared.setAppropriateAudioSessionOrWarn()
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
func setAutoplay(_ autoplay: Bool) {
|
|
277
|
+
self.autoplay = autoplay
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
func play() {
|
|
281
|
+
mediaPlayer?.play()
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
func pause() {
|
|
285
|
+
mediaPlayer?.pause()
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
func stop() {
|
|
289
|
+
mediaPlayer?.stop()
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
func seek(_ position: Float) {
|
|
293
|
+
guard let player = mediaPlayer else { return }
|
|
294
|
+
|
|
295
|
+
if player.isSeekable {
|
|
296
|
+
player.position = position
|
|
297
|
+
} else {
|
|
298
|
+
let error = ["error": "Media is not seekable"]
|
|
299
|
+
onError(error)
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
deinit {
|
|
304
|
+
VlcPlayerManager.shared.unregisterView(view: self)
|
|
305
|
+
destroyPlayer()
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private extension Array where Element == String {
|
|
310
|
+
func hasRepeatOptions() -> Bool {
|
|
311
|
+
let prefixes: Set<String> = [
|
|
312
|
+
"--input-repeat=", "-input-repeat=", ":input-repeat=",
|
|
313
|
+
]
|
|
314
|
+
|
|
315
|
+
return contains { arg in
|
|
316
|
+
prefixes.contains { prefix in
|
|
317
|
+
arg.hasPrefix(prefix)
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "expo-libvlc-player",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "LibVLC Player for Expo",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"types": "build/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "expo-module build",
|
|
9
|
+
"clean": "expo-module clean",
|
|
10
|
+
"lint": "expo-module lint",
|
|
11
|
+
"test": "expo-module test",
|
|
12
|
+
"prepare": "expo-module prepare",
|
|
13
|
+
"prepublishOnly": "expo-module prepublishOnly",
|
|
14
|
+
"expo-module": "expo-module",
|
|
15
|
+
"open:ios": "xed example/ios",
|
|
16
|
+
"open:android": "open -a \"Android Studio\" example/android"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"react-native",
|
|
20
|
+
"expo",
|
|
21
|
+
"libvlc",
|
|
22
|
+
"player",
|
|
23
|
+
"expo-libvlc-player",
|
|
24
|
+
"ExpoLibVlcPlayer"
|
|
25
|
+
],
|
|
26
|
+
"repository": "https://github.com/cornejobarraza/expo-libvlc-player",
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/cornejobarraza/expo-libvlc-player/issues"
|
|
29
|
+
},
|
|
30
|
+
"author": "David Cornejo <davidcornejo1@live.com> (https://github.com/cornejobarraza)",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"homepage": "https://github.com/cornejobarraza/expo-libvlc-player#readme",
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@eslint/compat": "^1.3.1",
|
|
35
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
36
|
+
"@eslint/js": "^9.30.0",
|
|
37
|
+
"@types/react": "~19.0.0",
|
|
38
|
+
"eslint": "^9.30.0",
|
|
39
|
+
"expo": "53.0.16",
|
|
40
|
+
"expo-module-scripts": "^4.1.6",
|
|
41
|
+
"globals": "^16.2.0",
|
|
42
|
+
"react-native": "0.79.5"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"expo": "*",
|
|
46
|
+
"react": "*",
|
|
47
|
+
"react-native": "*"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
5
|
+
const withExpoLibVlcPlayer = (config) => {
|
|
6
|
+
(0, config_plugins_1.withInfoPlist)(config, (config) => {
|
|
7
|
+
const currentBackgroundModes = config.modResults.UIBackgroundModes ?? [];
|
|
8
|
+
if (!currentBackgroundModes.includes("audio")) {
|
|
9
|
+
config.modResults.UIBackgroundModes = [
|
|
10
|
+
...currentBackgroundModes,
|
|
11
|
+
"audio",
|
|
12
|
+
];
|
|
13
|
+
}
|
|
14
|
+
return config;
|
|
15
|
+
});
|
|
16
|
+
return config;
|
|
17
|
+
};
|
|
18
|
+
exports.default = withExpoLibVlcPlayer;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type ConfigPlugin, withInfoPlist } from "expo/config-plugins";
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
4
|
+
const withExpoLibVlcPlayer: ConfigPlugin<{}> = (config) => {
|
|
5
|
+
withInfoPlist(config, (config) => {
|
|
6
|
+
const currentBackgroundModes = config.modResults.UIBackgroundModes ?? [];
|
|
7
|
+
|
|
8
|
+
if (!currentBackgroundModes.includes("audio")) {
|
|
9
|
+
config.modResults.UIBackgroundModes = [
|
|
10
|
+
...currentBackgroundModes,
|
|
11
|
+
"audio",
|
|
12
|
+
];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return config;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return config;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default withExpoLibVlcPlayer;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"root":["./src/withExpoLibVlcPlayer.ts"],"version":"5.8.3"}
|