เพิ่มวิดีโอเสียงรอบทิศทางลงในแอป

อุปกรณ์ XR ที่รองรับ
คำแนะนำนี้จะช่วยคุณสร้างประสบการณ์การใช้งานสำหรับอุปกรณ์ XR ประเภทนี้
ชุดหูฟัง XR
แว่นตา XR แบบมีสาย

Jetpack XR SDK รองรับการเล่นวิดีโอแบบเคียงข้างกันแบบสามมิติบนพื้นผิวเรียบ วิดีโอสเตอริโอสโคปแต่ละเฟรม ประกอบด้วยรูปภาพสำหรับตาซ้ายและรูปภาพสำหรับตาขวาเพื่อให้ผู้ชมรู้สึกถึง ความลึก ซึ่งเรียกอีกอย่างว่าสเตอริโอออปซิส

คุณสามารถแสดงวิดีโอ 2 มิติที่ไม่ใช่สเตอริโอในแอป Android XR ได้โดยใช้API สื่อ มาตรฐานที่ใช้สำหรับการพัฒนา Android ในอุปกรณ์รูปแบบอื่นๆ

เล่นวิดีโอแบบเคียงข้างกันโดยใช้ Jetpack SceneCore

วิดีโอแบบเคียงข้างกันจะแสดงแต่ละเฟรมสเตอริโอเป็นรูปภาพ 2 รูป ที่จัดเรียงในแนวนอนติดกัน เฟรมวิดีโอด้านบนและด้านล่างจะ จัดเรียงในแนวตั้งติดกัน

วิดีโอแบบเคียงข้างกันไม่ใช่ตัวแปลงรหัส แต่เป็นวิธีจัดระเบียบเฟรมสเตอริโอสโคป ซึ่งหมายความว่าสามารถเข้ารหัสในตัวแปลงรหัสที่ 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()

เล่นวิดีโอ MV-HEVC โดยใช้ Jetpack SceneCore

มาตรฐานตัวแปลงรหัส MV-HEVC ได้รับการเพิ่มประสิทธิภาพและออกแบบมาสำหรับวิดีโอสเตอริโอ เพื่อให้แอปของคุณเล่นวิดีโอที่สมจริงได้อย่างมีประสิทธิภาพและมีคุณภาพสูง ไฟล์ MV-HEVC มีสตรีมหลัก ซึ่งมักจะเป็นตาซ้าย และสตรีมสเตอริโอ ที่มีตาอีกข้าง

คุณโหลดวิดีโอแบบเดียวกันได้โดยใช้ Media3 Exoplayer และ แสดงผลโดยใช้ SurfaceEntity คุณจะต้องระบุว่าไฟล์ MV-HEVC เป็นไฟล์หลักด้านซ้ายหรือขวาในพารามิเตอร์ stereoMode เมื่อเรียกใช้ SurfaceEntity.create

// 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()

เล่นวิดีโอเชิงมิติพื้นที่ที่ได้รับการคุ้มครองโดย DRM โดยใช้ Jetpack SceneCore

Jetpack XR SDK รองรับการเล่นสตรีมวิดีโอที่เข้ารหัสโดยใช้เฟรมเวิร์กการจัดการสิทธิ์ดิจิทัล (DRM) ในตัวของ Android DRM ปกป้องเนื้อหาของคุณด้วยการเปิดใช้การจัดจำหน่ายที่ปลอดภัยและป้องกัน การคัดลอกหรือการเล่นที่ไม่ได้รับอนุญาต

กระบวนการนี้เกี่ยวข้องกับแอปพลิเคชันมีเดียเพลเยอร์ที่ติดต่อเซิร์ฟเวอร์ใบอนุญาต เพื่อรับคีย์การถอดรหัส ใน Android กระบวนการนี้จะได้รับการจัดการอย่างปลอดภัย และ เฟรมวิดีโอที่ถอดรหัสแล้วจะแสดงในบัฟเฟอร์กราฟิกที่ได้รับการป้องกันซึ่งระบบหรือแอปพลิเคชันอื่นๆ จะเข้าถึงไม่ได้ จึงป้องกันการจับภาพหน้าจอ

หากต้องการเล่นวิดีโอที่มีการป้องกัน DRM ด้วย Jetpack SceneCore คุณต้องทำดังนี้

  1. กำหนดค่า SurfaceEntity เพื่อขอพื้นผิวที่ได้รับการปกป้อง
  2. กำหนดค่า Media3 Exoplayer ด้วยข้อมูล DRM ที่จำเป็นเพื่อจัดการ การแลกเปลี่ยนคีย์
  3. ตั้งค่าเอาต์พุตของเพลเยอร์เป็นพื้นผิวของ SurfaceEntity

ตัวอย่างต่อไปนี้แสดงวิธีกำหนดค่า 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()

ดูภาพรวมโดยละเอียดเพิ่มเติมเกี่ยวกับเฟรมเวิร์ก DRM ของสื่อใน Android ได้ที่เอกสารประกอบ DRM ของสื่อใน source.android.com

เล่นวิดีโอ 180 องศาและ 360 องศาโดยใช้ Jetpack SceneCore

SurfaceEntity รองรับการเล่นวิดีโอ 180 องศาบนพื้นผิวครึ่งทรงกลม และวิดีโอ 360 องศาบนพื้นผิวทรงกลม พารามิเตอร์ radius หมายถึง ขนาดรัศมีของพื้นผิวที่เกี่ยวข้องในหน่วยเมตรโดยค่าเริ่มต้น

โค้ดต่อไปนี้แสดงวิธีตั้งค่า SurfaceEntity สำหรับการเล่นบนครึ่งทรงกลม 180° และทรงกลม 360° เมื่อใช้รูปร่าง Canvas เหล่านี้ ให้วางตำแหน่ง พื้นผิวโดยใช้ประโยชน์จากท่าทางศีรษะของผู้ใช้เพื่อมอบประสบการณ์ที่สมจริง

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 ขั้นสูง

หากต้องการควบคุมการเรนเดอร์วิดีโอและรูปภาพขั้นสูง เช่น การใช้ เอฟเฟกต์วัสดุที่กำหนดเอง คุณสามารถทำงานร่วมกับ SurfaceEntity ได้โดยตรงจากไลบรารี SceneCore

ส่วนต่อไปนี้จะอธิบายฟีเจอร์ขั้นสูงบางอย่างที่พร้อมใช้งานใน SurfaceEntity

ใช้การฟุ้งขอบ

ลดความคมชัดของขอบพื้นผิวเพื่อช่วยให้กลมกลืนกับสภาพแวดล้อมโดยการตั้งค่าพร็อพเพอร์ตี้ edgeFeatheringParams

// 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)

ใช้มาสก์อัลฟ่า

ใช้มาสก์อัลฟ่าเพื่อสร้างพื้นผิวที่ไม่ใช่สี่เหลี่ยมผืนผ้าหรือเพิ่มเอฟเฟกต์ความโปร่งใส ก่อนอื่น ให้โหลด 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 สำหรับ XR

หากสนใจเรียนรู้วิธีเล่นวิดีโอโดยใช้ Jetpack Compose สำหรับ XR โปรดดูวิธีเพิ่ม Surface สำหรับเนื้อหารูปภาพหรือวิดีโอ