You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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()
    )
}

关键修改点

  1. 手动绑定播放器:通过mediaListPlayer.mediaPlayer().setMediaPlayer()将MediaListPlayer与嵌入式的MediaPlayer关联,强制视频渲染到Compose的SwingPanel容器中。
  2. 资源释放:添加DisposableEffect确保播放器组件在Compose销毁时正确释放VLC资源,避免内存泄漏。
  3. 复用嵌入式容器:直接使用EmbeddedMediaPlayerComponent作为渲染载体,和常规播放器保持一致的嵌入逻辑。

内容的提问来源于stack exchange,提问作者Lol Lol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:47:03