android ExoPlayer2无法在Jetpack Composose中正确剪切,并且仍然在与其他ExoPlayers重叠的地方渲染

f45qwnt8  于 2023-06-04  发布在  Android
关注(0)|答案(1)|浏览(166)

我的目标是创建一个视频比较。我想显示两个视频旁边的对方,并能够自由指定的比例和翻译每一个。这两个视频应该被剪辑到它们对应的行的一半。
我创建了一个用于显示图像的解决方案,但是当我试图使用两个ExoPlayer而不是图像时,我遇到了以下问题,其中剪辑确实部分工作,但与另一个Player的重叠仍然被渲染。
ExoPlayersClipOverlapDemonstrationGif
下面是发生的情况的示意图:
ExoPlayersClipOverlapDemonstration
下面是我的Composable代码:

@Composable
fun VideoComparison(
) {
    Row(modifier = Modifier.fillMaxSize()) {
        //First Video
        Box(
            modifier = Modifier.background(Color.Blue).weight(1f).clipToBounds()
        ) {
            //Scaled smaller
            Box(modifier = Modifier.graphicsLayer { scaleX = 0.6f; scaleY = 0.6f}) {
                MyPlayer(
                    Uri.parse("https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
                )
            }
        }
        //Second Video
        Box(
            modifier = Modifier.weight(1f).clipToBounds()
        ) {
            //Scaled larger
            Box(modifier = Modifier.graphicsLayer { scaleX = 1.8f; scaleY = 1.8f}) {
                MyPlayer(
                    Uri.parse("https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
                )
            }
        }
    }
}

下面是我的Player Composable的代码:

@Composable
fun MyPlayer(uri: Uri) {
    val context = LocalContext.current

    val exoPlayer = remember {
        ExoPlayer.Builder(context)
            .build()
            .also { exoPlayer ->
                val mediaItem = MediaItem.Builder()
                    .setUri(uri)
                    .build()
                exoPlayer.setMediaItem(mediaItem)
                exoPlayer.prepare()
            }
    }

    exoPlayer.playWhenReady = true

    DisposableEffect(
        AndroidView(factory = {
            StyledPlayerView(context).apply {
                hideController()
                clipToOutline = true
                clipChildren = true
                useController = false
                player = exoPlayer
            }
        })
    ) {
        onDispose { exoPlayer.release() }
    }
}

在上面发布的代码中,我使用了修饰符.clipToBounds,例如它适用于图像,但不适用于两个ExoPlayers。我还尝试使用.clip().graphicLayer( clip = true),它们的行为都很相似。我还尝试了将裁剪修饰符放在不同元素上的各种组合,例如直接放在AndroidView或父Box上。
我在这里发现了一个类似的问题SimilarQuestion

lstz6jyr

lstz6jyr1#

StyledPlayerView的曲面类型更改为TextureView时,剪裁将起作用。这可以通过使用自定义XML文件覆盖标准属性来完成:

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.exoplayer2.ui.StyledPlayerView xmlns:app="http://schemas.android.com/apk/res-auto"
    app:surface_type="texture_view" />

通过以下方式加载:

val parser = context.resources.getXml(R.xml.styled_player_view_custom)
// Seek to the first tag.
var type = 0
while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
        type = parser.next()
}
val attrs = Xml.asAttributeSet(parser)

并将其添加到StyledPlayerView中,如下所示:

StyledPlayerView(context, attrs)

然而,由于SurfaceView对于ExoPlayer的好处,如更低的功耗,更准确的帧定时等。(如这里所述),如何使用SurfaceView修复它仍然会很有趣。

相关问题