向应用添加空间视频

Jetpack XR SDK 支持在平面上播放立体并排视频。立体视频的每个帧都包含左眼和右眼图像,以便观看者感受到深度。

您可以使用用于在其他设备规格上进行 Android 开发的标准媒体 API,在 Android XR 应用中渲染非立体 2D 视频。

使用 Jetpack XR SDK 并排播放视频

在并排视频中,每个立体图像帧都显示为两张图片,水平排列在一起。顶部和底部的视频帧垂直排列,彼此相邻。

并排视频不是编解码器,而是组织立体声帧的方式,这意味着它可以使用 Android 支持的任何编解码器进行编码。

Jetpack SceneCore

您可以使用 Media3 Exoplayer 加载并排列视频,然后使用新的 SurfaceEntity 进行渲染。如需创建 SurfaceEntity,请调用 SurfaceEntity.create,如以下示例所示。

val stereoSurfaceEntity = SurfaceEntity.create(
    xrSession,
    SurfaceEntity.StereoMode.SIDE_BY_SIDE,
    Pose(Vector3(0.0f, 0.0f, -1.5f)),
    SurfaceEntity.CanvasShape.Quad(1.0f, 1.0f)
)
val videoUri = Uri.Builder()
    .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
    .path("sbs_video.mp4")
    .build()
val mediaItem = MediaItem.fromUri(videoUri)

val exoPlayer = ExoPlayer.Builder(this).build()
exoPlayer.setVideoSurface(stereoSurfaceEntity.getSurface())
exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()
exoPlayer.play()

Jetpack Compose for XR

Alpha04 及更高版本

从版本 1.0.0-alpha04 开始,Jetpack Compose for XR 提供了另一种加载和渲染并排视频的方式。使用 SpatialExternalSurface,这是一个子空间可组合项,用于创建和管理 Surface,应用可在其中绘制内容,例如图片或视频。如需详细了解 SpatialExternalSurface,请参阅使用 Compose for XR 开发界面指南。

此示例演示了如何使用 Media3 ExoplayerSpatialExternalSurface 加载并排视频。

@Composable
fun SpatialExternalSurfaceContent() {
    val context = LocalContext.current
    Subspace {
        SpatialExternalSurface(
            modifier = SubspaceModifier
                .width(1200.dp) // Default width is 400.dp if no width modifier is specified
                .height(676.dp), // Default height is 400.dp if no height modifier is specified
            // Use StereoMode.Mono, StereoMode.SideBySide, or StereoMode.TopBottom, depending
            // upon which type of content you are rendering: monoscopic content, side-by-side stereo
            // content, or top-bottom stereo content
            stereoMode = StereoMode.SideBySide,
        ) {
            val exoPlayer = remember { ExoPlayer.Builder(context).build() }
            val videoUri = Uri.Builder()
                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
                // Represents a side-by-side stereo video, where each frame contains a pair of
                // video frames arranged side-by-side. The frame on the left represents the left
                // eye view, and the frame on the right represents the right eye view.
                .path("sbs_video.mp4")
                .build()
            val mediaItem = MediaItem.fromUri(videoUri)

            // onSurfaceCreated is invoked only one time, when the Surface is created
            onSurfaceCreated { surface ->
                exoPlayer.setVideoSurface(surface)
                exoPlayer.setMediaItem(mediaItem)
                exoPlayer.prepare()
                exoPlayer.play()
            }
            // onSurfaceDestroyed is invoked when the SpatialExternalSurface composable and its
            // associated Surface are destroyed
            onSurfaceDestroyed { exoPlayer.release() }
        }
    }
}

使用 Jetpack XR SDK 播放 180 度和 360 度视频

SurfaceEntity 支持在半球形 Surface 上播放 180 度视频,在球形 Surface 上播放 360 度视频。如果视频是立体视频,则文件应采用并排格式。

以下代码展示了如何设置 SurfaceEntity,以便在 180° 半球和 360° 球面上播放。使用这些画布形状时,请利用用户的头部姿势来定位 Surface,以提供沉浸式体验。

// Set up the surface for playing a 180° video on a hemisphere.
val hemisphereStereoSurfaceEntity =
    SurfaceEntity.create(
        xrSession,
        SurfaceEntity.StereoMode.SIDE_BY_SIDE,
        xrSession.scene.spatialUser.head?.transformPoseTo(
            Pose.Identity,
            xrSession.scene.activitySpace
        )!!,
        SurfaceEntity.CanvasShape.Vr180Hemisphere(1.0f),
    )
// ... and use the surface for playing the media.

// Set up the surface for playing a 360° video on a sphere.
val sphereStereoSurfaceEntity =
    SurfaceEntity.create(
        xrSession,
        SurfaceEntity.StereoMode.TOP_BOTTOM,
        xrSession.scene.spatialUser.head?.transformPoseTo(
            Pose.Identity,
            xrSession.scene.activitySpace
        )!!,
        SurfaceEntity.CanvasShape.Vr360Sphere(1.0f),
    )
// ... and use the surface for playing the media.