Got working subtitles/audio

This commit is contained in:
Alex Kim
2024-11-18 03:06:29 +11:00
parent 6b751cf154
commit 558480ea9d
11 changed files with 52 additions and 73 deletions

View File

@@ -0,0 +1,2 @@
#Sun Nov 17 18:25:45 AEDT 2024
gradle.version=8.9

View File

@@ -39,7 +39,6 @@ if (useManagedAndroidSdkVersions) {
dependencies { dependencies {
implementation 'org.videolan.android:libvlc-all:3.6.0-eap12' implementation 'org.videolan.android:libvlc-all:3.6.0-eap12'
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.31" implementation "org.jetbrains.kotlin:kotlin-stdlib:1.5.31"
implementation 'com.facebook.react:react-native:+'
} }
android { android {

View File

@@ -45,25 +45,25 @@ class VlcPlayerModule : Module() {
view.seekTo(time) view.seekTo(time)
} }
// AsyncFunction("setAudioTrack") { view: VlcPlayerView, trackIndex: Int -> AsyncFunction("setAudioTrack") { view: VlcPlayerView, trackIndex: Int ->
// view.setAudioTrack(trackIndex) view.setAudioTrack(trackIndex)
// } }
// AsyncFunction("getAudioTracks") { view: VlcPlayerView -> List<Map<String, Ansy>>? -> AsyncFunction("getAudioTracks") { view: VlcPlayerView ->
// view.getAudioTracks() view.getAudioTracks()
// } }
// AsyncFunction("setSubtitleTrack") { view: VlcPlayerView, trackIndex: Int -> AsyncFunction("setSubtitleTrack") { view: VlcPlayerView, trackIndex: Int ->
// view.setSubtitleTrack(trackIndex) view.setSubtitleTrack(trackIndex)
// } }
// AsyncFunction("getSubtitleTracks") { view: VlcPlayerView -> List<Map<String, Any>>? -> AsyncFunction("getSubtitleTracks") { view: VlcPlayerView ->
// view.getSubtitleTracks() view.getSubtitleTracks()
// } }
// AsyncFunction("setSubtitleURL") { view: VlcPlayerView, url: String, name: String -> AsyncFunction("setSubtitleURL") { view: VlcPlayerView, url: String, name: String ->
// view.setSubtitleURL(url, name) view.setSubtitleURL(url, name)
// } }
} }
} }
} }

View File

@@ -6,14 +6,12 @@ import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.LifecycleObserver
import android.net.Uri import android.net.Uri
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.modules.core.DeviceEventManagerModule
import expo.modules.kotlin.AppContext import expo.modules.kotlin.AppContext
import expo.modules.kotlin.views.ExpoView import expo.modules.kotlin.views.ExpoView
import expo.modules.kotlin.viewevent.EventDispatcher
import org.videolan.libvlc.LibVLC import org.videolan.libvlc.LibVLC
import org.videolan.libvlc.Media import org.videolan.libvlc.Media
import org.videolan.libvlc.MediaPlayer import org.videolan.libvlc.MediaPlayer
import org.videolan.libvlc.util.VLCVideoLayout import org.videolan.libvlc.util.VLCVideoLayout
@@ -28,6 +26,10 @@ class VlcPlayerView(context: Context, appContext: AppContext) : ExpoView(context
private var lastReportedIsPlaying: Boolean? = null private var lastReportedIsPlaying: Boolean? = null
private var startPosition: Int? = null private var startPosition: Int? = null
private val onVideoProgress by EventDispatcher()
private val onVideoStateChange by EventDispatcher()
private val onVideoLoadEnd by EventDispatcher()
init { init {
setupView() setupView()
} }
@@ -81,10 +83,6 @@ class VlcPlayerView(context: Context, appContext: AppContext) : ExpoView(context
if (autoplay) { if (autoplay) {
Log.d("VlcPlayerView", "Playing...") Log.d("VlcPlayerView", "Playing...")
play() play()
// if (startPosition > 0) {
// Log.d("VlcPlayerView", "Debug: Starting at position: $startPosition")
// seekTo(startPosition)
// }
} }
} }
@@ -119,36 +117,36 @@ class VlcPlayerView(context: Context, appContext: AppContext) : ExpoView(context
} }
} }
// fun setAudioTrack(trackIndex: Int) { fun setAudioTrack(trackIndex: Int) {
// mediaPlayer?.setAudioTrack(trackIndex) mediaPlayer?.setAudioTrack(trackIndex)
// } }
// fun getAudioTracks(): List<Map<String, Any>>? { fun getAudioTracks(): List<Map<String, Any>>? {
// val trackNames = mediaPlayer?.audioTrackNames ?: return null
// val trackIndexes = mediaPlayer?.audioTracks ?: return null
// return trackNames.zip(trackIndexes).map { (name, index) -> println("getAudioTracks")
// mapOf("name" to name, "index" to index) println(mediaPlayer?.getAudioTracks())
// } val trackDescriptions = mediaPlayer?.audioTracks ?: return null
// }
// fun setSubtitleTrack(trackIndex: Int) { return trackDescriptions.map { trackDescription ->
// mediaPlayer?.setSpuTrack(trackIndex) mapOf("name" to trackDescription.name, "index" to trackDescription.id)
// } }
}
// fun getSubtitleTracks(): List<Map<String, Any>>? { fun setSubtitleTrack(trackIndex: Int) {
// val trackNames = mediaPlayer?.spuTrackNames ?: return null mediaPlayer?.setSpuTrack(trackIndex)
// val trackIndexes = mediaPlayer?.spuTracks ?: return null }
// return trackNames.zip(trackIndexes).map { (name, index) -> fun getSubtitleTracks(): List<Map<String, Any>>? {
// mapOf("name" to name, "index" to index) return mediaPlayer?.getSpuTracks()?.map { trackDescription ->
// } mapOf("name" to trackDescription.name, "index" to trackDescription.id)
// } }
}
// fun setSubtitleURL(subtitleURL: String, name: String) { fun setSubtitleURL(subtitleURL: String, name: String) {
// val media = mediaPlayer?.media ?: return // val media = mediaPlayer?.media ?: return
// media.addSlave(Media.Slave(Media.Slave.Type.Subtitle, subtitleURL, true)) // media.addSlave(Media.Slave(Media.Slave.Type.Subtitle, 0, Uri.parse(subtitleURL)))
// } mediaPlayer?.addSlave(1, Uri.parse(subtitleURL), false)
}
override fun onDetachedFromWindow() { override fun onDetachedFromWindow() {
super.onDetachedFromWindow() super.onDetachedFromWindow()
@@ -196,7 +194,7 @@ class VlcPlayerView(context: Context, appContext: AppContext) : ExpoView(context
MediaPlayer.Event.EncounteredError -> { MediaPlayer.Event.EncounteredError -> {
Log.e("VlcPlayerView", "player.state ~ error") Log.e("VlcPlayerView", "player.state ~ error")
stateInfo["state"] = "Error" stateInfo["state"] = "Error"
sendEvent("onVideoLoadEnd", stateInfo) onVideoLoadEnd(stateInfo);
} }
MediaPlayer.Event.Opening -> { MediaPlayer.Event.Opening -> {
Log.d("VlcPlayerView", "player.state ~ opening") Log.d("VlcPlayerView", "player.state ~ opening")
@@ -207,14 +205,14 @@ class VlcPlayerView(context: Context, appContext: AppContext) : ExpoView(context
// Determine if the media has finished loading // Determine if the media has finished loading
if (player.isPlaying && !isMediaReady) { if (player.isPlaying && !isMediaReady) {
isMediaReady = true isMediaReady = true
sendEvent("onVideoLoadEnd", stateInfo) onVideoLoadEnd(stateInfo)
seekToStartTime() seekToStartTime()
} }
if (lastReportedState != currentState || lastReportedIsPlaying != player.isPlaying) { if (lastReportedState != currentState || lastReportedIsPlaying != player.isPlaying) {
lastReportedState = currentState lastReportedState = currentState
lastReportedIsPlaying = player.isPlaying lastReportedIsPlaying = player.isPlaying
sendEvent("onVideoStateChange", stateInfo) onVideoStateChange(stateInfo)
} }
} }
@@ -239,31 +237,11 @@ class VlcPlayerView(context: Context, appContext: AppContext) : ExpoView(context
val currentTimeMs = player.time.toInt() val currentTimeMs = player.time.toInt()
val durationMs = player.media?.duration?.toInt() ?: 0 val durationMs = player.media?.duration?.toInt() ?: 0
println("currentTimeMs: $currentTimeMs, durationMs: $durationMs")
if (currentTimeMs >= 0 && currentTimeMs < durationMs) { if (currentTimeMs >= 0 && currentTimeMs < durationMs) {
val progressInfo = mapOf( onVideoProgress(mapOf(
"currentTime" to currentTimeMs, "currentTime" to currentTimeMs,
"duration" to durationMs "duration" to durationMs
) ));
sendEvent("onVideoProgress", progressInfo)
} }
} }
private fun sendEvent(eventName: String, params: Map<String, Any>) {
val reactContext = appContext.reactContext as? ReactContext
Log.d("VlcPlayerView", "Sending event: $eventName with params: $params")
val eventMap = Arguments.createMap()
params.forEach { (key, value) ->
when (value) {
is Int -> eventMap.putInt(key, value)
is String -> eventMap.putString(key, value)
is Boolean -> eventMap.putBoolean(key, value)
}
}
reactContext?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
?.emit(eventName, eventMap)
}
var onVideoLoadEnd: ((Map<String, Any>) -> Unit)? = null
var onVideoStateChange: ((Map<String, Any>) -> Unit)? = null
} }