向应用添加空间视频

适用的 XR 设备
本指南可帮助您为以下类型的 XR 设备打造优质体验。
扩展现实头戴设备
有线扩展现实眼镜

Jetpack XR SDK 支持在平面上播放立体 并排 视频。对于立体视频,每个帧都包含左眼图像和右眼图片,让观看者感受到深度,也称为立体视觉

您可以使用在其他设备类型上进行 Android 开发时使用的标准 媒体 API,在 Android XR 应用上呈现非立体 2D 视频。

使用 Jetpack SceneCore 播放并排视频

对于并排视频,每个立体帧都以两个水平相邻的图像呈现。上下视频帧垂直相邻排列。

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

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

val stereoSurfaceEntity = SurfaceEntity.create(
    session = xrSession,
    stereoMode = SurfaceEntity.StereoMode.SIDE_BY_SIDE,
    pose = Pose(Vector3(0.0f, 0.0f, -1.5f)),
    shape = SurfaceEntity.Shape.Quad(FloatSize2d(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 SceneCore 播放 MV-HEVC 视频

MV-HEVC 编解码器标准经过优化,专为立体视频而设计,可让您的应用以出色的质量高效播放沉浸式视频。 MV-HEVC 文件有一个主视频流(通常是左眼)和一个立体视频流(另一只眼)。

与并排视频类似,您可以使用 Media3 Exoplayer 加载 MV-HEVC 视频,并使用 SurfaceEntity 呈现该视频。在调用 SurfaceEntity.create 时,您需要在 stereoMode 参数中指定 MV-HEVC 文件是左眼还是右眼。

// Create the SurfaceEntity with the StereoMode corresponding to the MV-HEVC content
val stereoSurfaceEntity = SurfaceEntity.create(
    session = xrSession,
    stereoMode = SurfaceEntity.StereoMode.MULTIVIEW_LEFT_PRIMARY,
    pose = Pose(Vector3(0.0f, 0.0f, -1.5f)),
    shape = SurfaceEntity.Shape.Quad(FloatSize2d(1.0f, 1.0f))
)
val videoUri = Uri.Builder()
    .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
    .path("mvhevc_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 SceneCore 播放受 DRM 保护的空间视频

Jetpack XR SDK 支持使用 Android's 内置 数字版权管理 (DRM) 框架播放加密的视频流。DRM 通过启用安全分发并防止未经授权的复制或播放来保护您的内容。

此过程涉及媒体播放器应用与许可服务器联系以获取解密密钥。在 Android 上,此过程受到安全管理,解密的视频帧会呈现到受保护的图形缓冲区,系统或其他应用无法访问该缓冲区,从而防止屏幕截图。

如需使用 Jetpack SceneCore 播放受 DRM 保护的视频,您需要执行以下操作:

  1. 配置 SurfaceEntity 以请求受保护的 Surface。
  2. 使用必要的 DRM 信息配置 Media3 Exoplayer,以处理 密钥交换。
  3. 将播放器的输出设置为 SurfaceEntity 的 Surface。

以下示例展示了如何配置 ExoPlayer 以播放受 DRM 保护的 视频流并在 SurfaceEntity 上呈现该视频流:

// Create a SurfaceEntity with DRM content

// Define the URI for your DRM-protected content and license server.
val videoUri = "https://your-content-provider.com/video.mpd"
val drmLicenseUrl = "https://your-license-server.com/license"

// Create the SurfaceEntity with the PROTECTED content security level.
val protectedSurfaceEntity = SurfaceEntity.create(
    session = xrSession,
    stereoMode = SurfaceEntity.StereoMode.SIDE_BY_SIDE,
    pose = Pose(Vector3(0.0f, 0.0f, -1.5f)),
    shape = SurfaceEntity.Shape.Quad(FloatSize2d(1.0f, 1.0f)),
    surfaceProtection = SurfaceEntity.SurfaceProtection.PROTECTED
)

// Build a MediaItem with the necessary DRM configuration.
val mediaItem = MediaItem.Builder()
    .setUri(videoUri)
    .setDrmConfiguration(
        MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
            .setLicenseUri(drmLicenseUrl)
            .build()
    )
    .build()

// Initialize ExoPlayer and set the protected surface.
val exoPlayer = ExoPlayer.Builder(this).build()
exoPlayer.setVideoSurface(protectedSurfaceEntity.getSurface())

// Set the media item and start playback.
exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()
exoPlayer.play()

如需详细了解 Android 的媒体 DRM 框架,请参阅 source.android.com 上的媒体 DRM 文档

使用 Jetpack SceneCore 播放 180 度视频和 360 度视频

SurfaceEntity 支持在半球形 Surface 上播放 180 度视频,在球形 Surface 上播放 360 度视频。radius 参数默认是指相应 Surface 的半径大小(以米为单位)。

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

val devicePose = ArDevice.getInstance(xrSession).state.value.devicePose
val activitySpacePose = xrSession.scene.perceptionSpace.transformPoseTo(devicePose, xrSession.scene.activitySpace)

// Set up the surface for playing a 180° video on a hemisphere.
val hemisphereStereoSurfaceEntity =
    SurfaceEntity.create(
        session = xrSession,
        stereoMode = SurfaceEntity.StereoMode.SIDE_BY_SIDE,
        pose = activitySpacePose,
        shape = SurfaceEntity.Shape.Hemisphere(1.0f),
    )
// ... and use the surface for playing the media.

val devicePose = ArDevice.getInstance(xrSession).state.value.devicePose
val activitySpacePose = xrSession.scene.perceptionSpace.transformPoseTo(devicePose, xrSession.scene.activitySpace)
// Set up the surface for playing a 360° video on a sphere.
val sphereStereoSurfaceEntity =
    SurfaceEntity.create(
        session = xrSession,
        stereoMode = SurfaceEntity.StereoMode.TOP_BOTTOM,
        pose = activitySpacePose,
        shape = SurfaceEntity.Shape.Sphere(1.0f),
    )
// ... and use the surface for playing the media.

高级 SurfaceEntity 控制

如需对视频和图像呈现进行更高级的控制(例如应用自定义材质效果),您可以直接使用 SceneCore 库中的 SurfaceEntity

以下部分介绍了一些可用于 SurfaceEntity 的高级功能。

应用边缘羽化

通过设置 edgeFeatheringParams 属性,柔化 Surface 的边缘,使其与环境融合。

// Create a SurfaceEntity.
val surfaceEntity = SurfaceEntity.create(
    session = xrSession,
    pose = Pose(Vector3(0.0f, 0.0f, -1.5f))
)

// Feather the edges of the surface.
surfaceEntity.edgeFeatheringParams =
    SurfaceEntity.EdgeFeatheringParams.RectangleFeather(0.1f, 0.1f)

应用 Alpha 蒙版

应用 Alpha 蒙版以创建非矩形 Surface 或添加透明效果。首先,从资源加载 Texture,然后将其分配给 primaryAlphaMaskTexture 属性:

// Create a SurfaceEntity.
val surfaceEntity = SurfaceEntity.create(
    session = xrSession,
    pose = Pose(Vector3(0.0f, 0.0f, -1.5f))
)

// Load the texture in a coroutine scope.
activity.lifecycleScope.launch {
    val alphaMaskTexture =
        Texture.create(
            xrSession,
            Paths.get("textures", "alpha_mask.png"),
        )

    // Apply the alpha mask.
    surfaceEntity.primaryAlphaMaskTexture = alphaMaskTexture

    // To remove the mask, set the property to null.
    surfaceEntity.primaryAlphaMaskTexture = null
}

使用 Jetpack Compose for XR 播放空间视频

如果您有兴趣了解如何使用 Jetpack Compose for XR 播放视频,了解如何为图像或视频内容添加 Surface