如何在Kotlin Compose桌面应用中正确嵌入VLCJ媒体列表播放器
解决Kotlin Compose中VLCJ MediaListPlayer嵌入问题
问题根源在于EmbeddedMediaListPlayerComponent在Compose的SwingPanel环境下,内部的MediaListPlayer没有正确绑定到组件的渲染表面,导致视频默认渲染到独立窗口。我们可以通过手动关联MediaListPlayer与嵌入式MediaPlayer来解决这个问题:
修改后的完整代码
import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.awt.SwingPanel import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window import androidx.compose.ui.window.application import kotlinx.coroutines.delay import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent import uk.co.caprica.vlcj.player.list.MediaListPlayer import uk.co.caprica.vlcj.player.list.MediaListPlayerFactory import uk.co.caprica.vlcj.media.list.MediaListFactory fun main() = application { Window(onCloseRequest = ::exitApplication) { MaterialTheme { val mrl1 = "" // 填入视频路径 val mrl2 = "" // 填入视频路径 Column { // 常规嵌入式播放器 Row(Modifier.weight(1f)) { VideoPlayerRegular(mrl1) } Spacer(Modifier.height(1.dp)) // 修复后的媒体列表播放器 Row(Modifier.weight(1f)) { VideoPlayerList(mrl1, mrl2) } } } } } @Composable fun VideoPlayerList(mrl1: String, mrl2: String) { // 复用常规嵌入式播放器组件作为渲染容器 val mediaPlayerComponent = remember { EmbeddedMediaPlayerComponent() } // 单独创建MediaListPlayer val mediaListPlayer = remember { MediaListPlayerFactory.newMediaListPlayer() } LaunchedEffect(Unit) { // 关键:将MediaListPlayer与嵌入式MediaPlayer绑定 mediaListPlayer.mediaPlayer().setMediaPlayer(mediaPlayerComponent.mediaPlayer()) // 创建并添加媒体列表 val mediaList = MediaListFactory.newMediaList() mediaList.addMedia(mrl1) mediaList.addMedia(mrl2) mediaListPlayer.list().setMediaList(mediaList) // 播放逻辑 mediaListPlayer.controls().play() delay(3000) mediaListPlayer.controls().playNext() } // 确保组件销毁时释放资源 DisposableEffect(Unit) { onDispose { mediaListPlayer.release() mediaPlayerComponent.release() } } SwingPanel( factory = { mediaPlayerComponent }, modifier = Modifier.fillMaxWidth().fillMaxHeight() ) } @Composable fun VideoPlayerRegular(mrl: String) { val mediaPlayerComponent = remember { EmbeddedMediaPlayerComponent() } LaunchedEffect(Unit) { mediaPlayerComponent.mediaPlayer().media().play(mrl) } // 添加资源释放逻辑 DisposableEffect(Unit) { onDispose { mediaPlayerComponent.release() } } SwingPanel( factory = { mediaPlayerComponent }, modifier = Modifier.fillMaxWidth().fillMaxHeight() ) }
关键修改点
- 手动绑定播放器:通过
mediaListPlayer.mediaPlayer().setMediaPlayer()将MediaListPlayer与嵌入式的MediaPlayer关联,强制视频渲染到Compose的SwingPanel容器中。 - 资源释放:添加
DisposableEffect确保播放器组件在Compose销毁时正确释放VLC资源,避免内存泄漏。 - 复用嵌入式容器:直接使用
EmbeddedMediaPlayerComponent作为渲染载体,和常规播放器保持一致的嵌入逻辑。
内容的提问来源于stack exchange,提问作者Lol Lol
相关产品推荐
相关产品推荐

