ข่าวสารเกี่ยวกับผลิตภัณฑ์

ขอแนะนำ CameraX 1.5: การบันทึกวิดีโอประสิทธิภาพสูงและการถ่ายภาพระดับมืออาชีพ

อ่าน 7 นาที
Scott Nien
วิศวกรซอฟต์แวร์

ทีม CameraX ยินดีเป็นอย่างยิ่งที่จะประกาศเปิดตัวเวอร์ชัน 1.5! การอัปเดตล่าสุดนี้มุ่งเน้นที่การนำความสามารถระดับมืออาชีพมาไว้ที่ปลายนิ้วของคุณ พร้อมทั้งทำให้การกำหนดค่าเซสชันกล้องง่ายกว่าที่เคย

สำหรับการบันทึกวิดีโอ ตอนนี้ผู้ใช้สามารถบันทึกวิดีโอสโลว์โมชันหรือวิดีโอที่มีอัตราเฟรมสูงได้อย่างง่ายดาย ที่สำคัญกว่านั้นคือ Feature Group API ใหม่ช่วยให้คุณเปิดใช้การผสมผสานที่ซับซ้อน เช่น HDR 10 บิตและ 60 FPS ได้อย่างมั่นใจ ซึ่งจะช่วยให้ได้ผลลัพธ์ที่สอดคล้องกันในอุปกรณ์ที่รองรับ

ในส่วนของการถ่ายภาพ คุณจะได้รับความยืดหยุ่นสูงสุดด้วยการรองรับการบันทึกไฟล์ DNG (RAW) ที่ยังไม่ได้ประมวลผลและไม่ได้บีบอัด นอกจากนี้ ตอนนี้คุณยังใช้เอาต์พุต Ultra HDR ได้แม้จะใช้ Camera Extensions ที่มีประสิทธิภาพสูงก็ตาม

ฟีเจอร์เหล่านี้ทำงานด้วย SessionConfig API ใหม่ ซึ่งช่วยลดความซับซ้อนในการตั้งค่าและกำหนดค่ากล้องใหม่ ตอนนี้เรามาดูรายละเอียดของฟีเจอร์ใหม่ที่น่าตื่นเต้นเหล่านี้กัน

การบันทึกวิดีโอประสิทธิภาพสูง: ความเร็วสูงและการผสมผสานฟีเจอร์

CameraX 1.5 ขยายขีดความสามารถด้านวิดีโออย่างมาก ซึ่งช่วยให้คุณได้รับประสบการณ์การบันทึกที่สร้างสรรค์และมีประสิทธิภาพมากขึ้น

วิดีโอสโลว์โมชันและวิดีโอที่มีอัตราเฟรมสูง

วิดีโอสโลว์โมชัน ซึ่งเป็นหนึ่งในฟีเจอร์ที่เรารอคอยมากที่สุดพร้อมใช้งานแล้ว ตอนนี้คุณสามารถบันทึกวิดีโอความเร็วสูง (เช่น 120 หรือ 240 fps) และเข้ารหัสเป็นวิดีโอสโลว์โมชันที่น่าทึ่งได้โดยตรง หรือจะบันทึกด้วยอัตราเฟรมสูงเท่าเดิมเพื่อสร้างวิดีโอที่ราบรื่นเป็นพิเศษก็ได้

การใช้งานฟีเจอร์นี้ทำได้ง่ายหากคุณคุ้นเคยกับ VideoCapture API

1. ตรวจสอบการรองรับความเร็วสูง: ใช้เมธอด Recorder.getHighSpeedVideoCapabilities() ใหม่เพื่อค้นหาว่าอุปกรณ์รองรับฟีเจอร์นี้หรือไม่

val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)

val highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)

if (highSpeedCapabilities == null) {
    // This camera device does not support high-speed video.
    return
}

2. กำหนดค่าและผูก Use Case: ใช้ videoCapabilities ที่แสดงผล (ซึ่งมีข้อมูลคุณภาพวิดีโอที่รองรับ) เพื่อสร้าง HighSpeedVideoSessionConfig จากนั้นคุณต้องค้นหาช่วงอัตราเฟรมที่รองรับผ่าน cameraInfo.getSupportedFrameRateRanges() และตั้งค่าช่วงที่ต้องการ เรียกใช้ setSlowMotionEnabled(true) เพื่อบันทึกวิดีโอสโลว์โมชัน ไม่เช่นนั้นระบบจะบันทึกวิดีโอที่มีอัตราเฟรมสูง ขั้นตอนสุดท้ายคือการใช้ Recorder.prepareRecording().start() ปกติเพื่อเริ่มบันทึกวิดีโอ

val preview = Preview.Builder().build()
val quality = highSpeedCapabilities
        .getSupportedQualities(DynamicRange.SDR).first()

val recorder = Recorder.Builder()
      .setQualitySelector(QualitySelector.from(quality)))
      .build()

val videoCapture = VideoCapture.withOutput(recorder)

val frameRateRange = cameraInfo.getSupportedFrameRateRanges(      
       HighSpeedVideoSessionConfig(videoCapture, preview)
).first()

val sessionConfig = HighSpeedVideoSessionConfig(
    videoCapture, 
    preview, 
    frameRateRange = frameRateRange, 
    // Set true for slow-motion playback, or false for high-frame-rate
    isSlowMotionEnabled = true
)

cameraProvider.bindToLifecycle(
     lifecycleOwner, cameraSelector, sessionConfig)

// Start recording slow motion videos. 
val recording = recorder.prepareRecording(context, outputOption)
      .start(executor, {})

ความเข้ากันได้และข้อจำกัด

การบันทึกความเร็วสูงต้องมีการรองรับ CameraConstrainedHighSpeedCaptureSession และ CamcorderProfile ที่เฉพาะเจาะจง ตรวจสอบความสามารถเสมอ และเปิดใช้การบันทึกความเร็วสูงในอุปกรณ์ที่รองรับเท่านั้นเพื่อป้องกันไม่ให้ผู้ใช้ได้รับประสบการณ์ที่ไม่ดี ปัจจุบันฟีเจอร์นี้รองรับกล้องหลังของอุปกรณ์ Pixel เกือบทั้งหมดและบางรุ่นจากผู้ผลิตรายอื่นๆ

ดูรายละเอียดเพิ่มเติมได้ในโพสต์ในบล็อก

ผสมผสานฟีเจอร์ต่างๆ ได้อย่างมั่นใจด้วย Feature Group API

CameraX 1.5 ขอแนะนำ Feature Group API ซึ่งช่วยขจัดความไม่แน่นอนเกี่ยวกับความเข้ากันได้ของฟีเจอร์ ตอนนี้คุณสามารถเปิดใช้ฟีเจอร์หลายรายการพร้อมกันได้อย่างมั่นใจ โดยรับประกันว่าเซสชันกล้องจะเสถียร โดยอิงตาม Feature Combination Query API ของ Android 15 ปัจจุบัน Feature Group รองรับ HDR (HLG), 60 fps, การป้องกันภาพสั่นไหวในการแสดงตัวอย่าง และ Ultra HDR เช่น คุณสามารถเปิดใช้ HDR, 60 fps และการป้องกันภาพสั่นไหวในการแสดงตัวอย่างพร้อมกันใน Pixel 10 และ Galaxy S25 Series เราวางแผนที่จะเพิ่มการบันทึก 4K และการซูมอัลตราไวด์ในอนาคต

Feature Group API ช่วยให้คุณใช้งาน Use Case ที่สำคัญ 2 รายการได้ ดังนี้

Use Case 1: การจัดลำดับความสำคัญของคุณภาพที่ดีที่สุด

หากต้องการบันทึกโดยใช้การผสมผสานฟีเจอร์ที่ดีที่สุดเท่าที่จะเป็นไปได้ คุณสามารถระบุรายการที่จัดลำดับความสำคัญได้ CameraX จะพยายามเปิดใช้ฟีเจอร์ตามลำดับ โดยเลือกการผสมผสานแรกที่อุปกรณ์รองรับอย่างเต็มที่

val sessionConfig = SessionConfig(
    useCases = listOf(preview, videoCapture),
    preferredFeatureGroup = listOf(
        GroupableFeature.HDR_HLG10,
        GroupableFeature.FPS_60,
        GroupableFeature.PREVIEW_STABILIZATION
    )
).apply {
    // (Optional) Get a callback with the enabled features to update your UI.
    setFeatureSelectionListener { selectedFeatures ->
        updateUiIndicators(selectedFeatures)
    }
}
processCameraProvider.bindToLifecycle(activity, cameraSelector, sessionConfig)

ในตัวอย่างนี้ CameraX จะพยายามเปิดใช้ฟีเจอร์ตามลำดับต่อไปนี้

  1. HDR + 60 FPS + การป้องกันภาพสั่นไหวในการแสดงตัวอย่าง
  2. HDR + 60 FPS
  3. HDR + การป้องกันภาพสั่นไหวในการแสดงตัวอย่าง
  4. HDR
  5. 60 FPS + การป้องกันภาพสั่นไหวในการแสดงตัวอย่าง
  6. 60 FPS
  7. การป้องกันภาพสั่นไหวในการแสดงตัวอย่าง
  8. ไม่มี

Use Case 2: การสร้าง UI การตั้งค่าที่ผู้ใช้มองเห็น

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

unsupported-features-disabled.gif

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

fun disableFeatureIfNotSuported(
   enabledFeatures: Set<GroupableFeature>,     
   featureToCheck:GroupableFeature
) {
 val sessionConfig = SessionConfig(
     useCases = useCases,
     requiredFeatureGroup = enabledFeatures + featureToCheck
 )
 val isSupported = cameraInfo.isFeatureGroupSupported(sessionConfig)

 if (!isSupported) {
     // disable the toggle for featureToCheck
 }
}

โปรดดูข้อมูลเพิ่มเติมได้ในโพสต์ในบล็อกเกี่ยวกับ Feature Group

การปรับปรุงวิดีโอเพิ่มเติม

  • การปรับปรุงกล้องพร้อมกัน: ตอนนี้ CameraX 1.5.1 ช่วยให้คุณผูก Use Case ของการแสดงตัวอย่าง + การถ่ายภาพ + การบันทึกวิดีโอพร้อมกันสำหรับ SingleCameraConfig แต่ละรายการใน โหมดที่ไม่ใช่โหมดการจัดองค์ประกอบ ได้แล้ว นอกจากนี้ ในโหมดการจัดองค์ประกอบ (Use Case เดียวกันกับ CompositionSettings) ตอนนี้คุณสามารถตั้งค่า CameraEffect ที่จะใช้กับผลลัพธ์การจัดองค์ประกอบสุดท้ายได้แล้ว
  • การปิดเสียงแบบไดนามิก: ตอนนี้คุณสามารถเริ่มการบันทึกในสถานะปิดเสียงได้โดยใช้ PendingRecording.withAudioEnabled(boolean initialMuted) และอนุญาตให้ผู้ใช้เปิดเสียงได้ในภายหลังโดยใช้ Recording.mute(boolean muted)
  • การจัดการพื้นที่เก็บข้อมูลไม่เพียงพอที่ดีขึ้น: ตอนนี้ CameraX จะส่งข้อผิดพลาด VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE ได้อย่างน่าเชื่อถือ ซึ่งช่วยให้แอปจัดการสถานการณ์ที่พื้นที่เก็บข้อมูลเหลือน้อยและแจ้งให้ผู้ใช้ทราบได้อย่างเหมาะสม
  • การเพิ่มประสิทธิภาพในที่แสงน้อย: ในอุปกรณ์ที่รองรับ (เช่น Pixel 10 Series) คุณสามารถเปิดใช้ CameraControl.enableLowLightBoostAsync เพื่อเพิ่มความสว่างให้การแสดงตัวอย่างและวิดีโอสตรีมโดยอัตโนมัติในสภาพแวดล้อมที่มืด

การถ่ายภาพระดับมืออาชีพ

CameraX 1.5 มีการอัปเกรด ImageCapture ครั้งใหญ่สำหรับนักพัฒนาแอปที่ต้องการคุณภาพและความยืดหยุ่นสูงสุด

ปลดปล่อยการควบคุมที่สร้างสรรค์ด้วยการบันทึก DNG (RAW)

CameraX รองรับการบันทึก DNG (RAW) แล้ว ซึ่งช่วยให้คุณควบคุมการประมวลผลภายหลังได้อย่างสมบูรณ์ ฟีเจอร์นี้ช่วยให้คุณเข้าถึงข้อมูลรูปภาพที่ยังไม่ได้ประมวลผลและไม่ได้บีบอัดจากเซ็นเซอร์กล้องโดยตรง ซึ่งช่วยให้คุณแก้ไขและปรับสีได้ในระดับมืออาชีพ API รองรับการบันทึกไฟล์ DNG เพียงอย่างเดียว หรือการบันทึกเอาต์พุต JPEG และ DNG พร้อมกัน ดูโค้ดตัวอย่างด้านล่างเพื่อดูวิธีบันทึกไฟล์ JPEG และ DNG พร้อมกัน

val capabilities = ImageCapture.getImageCaptureCapabilities(cameraInfo)
val imageCapture = ImageCapture.Builder().apply {
    if (capabilities.supportedOutputFormats
             .contains(OUTPUT_FORMAT_RAW_JPEG)) {
        // Capture both RAW and JPEG formats.
        setOutputFormat(OUTPUT_FORMAT_RAW_JPEG)
    }
}.build()
// ... bind imageCapture to lifecycle ...


// Provide separate output options for each format.
val outputOptionRaw = /* ... configure for image/x-adobe-dng ... */
val outputOptionJpeg = /* ... configure for image/jpeg ... */
imageCapture.takePicture(
    outputOptionRaw,
    outputOptionJpeg,
    executor,
    object : ImageCapture.OnImageSavedCallback {
        override fun onImageSaved(results: OutputFileResults) {
            // This callback is invoked twice: once for the RAW file
            // and once for the JPEG file.
        }

        override fun onError(exception: ImageCaptureException) {}
    }
)

Ultra HDR สำหรับ Camera Extensions

รับสิ่งที่ดีที่สุดจากทั้ง 2 โลก นั่นคือ การถ่ายภาพแบบดิจิทัลที่น่าทึ่งของ Camera Extensions (เช่น โหมดกลางคืน) ผสานกับสีสันสดใสและช่วงไดนามิกที่ยอดเยี่ยมของ Ultra HDR ตอนนี้ฟีเจอร์นี้รองรับโทรศัพท์ Android ระดับพรีเมียมรุ่นล่าสุดหลายรุ่น เช่น Pixel 9/10 Series และ Samsung S24/S25 Series

// Support UltraHDR when Extension is enabled. 

val extensionsEnabledCameraSelector = extensionsManager
     .getExtensionEnabledCameraSelector(
        CameraSelector.DEFAULT_BACK_CAMERA, ExtensionMode.NIGHT)

val imageCapabilities = ImageCapture.getImageCaptureCapabilities(
               cameraProvider.getCameraInfo(extensionsEnabledCameraSelector)

val imageCapture = ImageCapture.Builder()
     .apply {
       if (imageCapabilities.supportedOutputFormats
                .contains(OUTPUT_FORMAT_JPEG_ULTRA_HDR) {
           setOutputFormat(OUTPUT_FORMAT_JPEG_ULTRA_HDR)

       }

     }.build()

การปรับปรุง API หลักและความสามารถในการใช้งาน

วิธีใหม่ในการกำหนดค่า: SessionConfig

ดังที่เห็นในตัวอย่างข้างต้น SessionConfig เป็นแนวคิดใหม่ใน CameraX 1.5 ซึ่งรวมการกำหนดค่าไว้ที่ส่วนกลางและลดความซับซ้อนของ API ใน 2 วิธีหลักๆ ดังนี้

  1. ไม่ต้องเรียกใช้ unbind() ด้วยตนเองอีกต่อไป: CameraX API ตระหนักถึงวงจรการทำงาน ระบบจะ "ยกเลิกการผูก" Use Case ของคุณโดยนัยเมื่อกิจกรรมหรือ LifecycleOwner อื่นๆ ถูกทำลาย แต่การอัปเดต Use Case หรือการเปลี่ยนกล้องยังคงต้องเรียกใช้ unbind() หรือ unbindAll() ก่อนที่จะผูกอีกครั้ง ตอนนี้เมื่อคุณผูก SessionConfig ใหม่ด้วย CameraX 1.5 ระบบจะอัปเดตเซสชันให้คุณอย่างราบรื่น ซึ่งช่วยลดความจำเป็นในการเรียกใช้ unbind
  2. การควบคุมอัตราเฟรมแบบดีเทอร์มินิสติก: SessionConfig API ใหม่นำเสนอวิธีแบบดีเทอร์มินิสติกในการจัดการอัตราเฟรม ซึ่งแตกต่างจาก setTargetFrameRate ก่อนหน้านี้ซึ่งเป็นเพียงคำแนะนำ วิธีใหม่นี้รับประกัน ว่าช่วงอัตราเฟรมที่ระบุจะถูกนำไปใช้เมื่อกำหนดค่าสำเร็จ คุณต้องค้นหาอัตราเฟรมที่รองรับโดยใช้ CameraInfo.getSupportedFrameRateRanges(SessionConfig) เพื่อให้แน่ใจว่าถูกต้อง การส่ง SessionConfig แบบเต็มจะช่วยให้ CameraX กำหนดช่วงที่รองรับได้อย่างถูกต้องตามการกำหนดค่าสตรีม

Camera-Compose เสถียรแล้ว

เรารู้ว่าคุณชื่นชอบ Jetpack Compose มากเพียงใด และยินดีที่จะประกาศว่าตอนนี้ไลบรารี camera-compose เสถียรแล้วในเวอร์ชัน 1.5.1! รุ่นนี้มีการแก้ไขข้อบกพร่องที่สำคัญที่เกี่ยวข้องกับการใช้งาน CameraXViewfinder กับฟีเจอร์ Compose เช่น moveableContentOf และ Pager รวมถึงการแก้ไขปัญหาการยืดการแสดงตัวอย่าง เราจะเพิ่มฟีเจอร์เพิ่มเติมลงใน camera-compose ในรุ่นต่อๆ ไป

การปรับปรุง ImageAnalysis และ CameraControl

  • การปรับความแรงของไฟฉาย: ควบคุมไฟฉายของอุปกรณ์ได้อย่างละเอียดด้วย API ใหม่ คุณสามารถค้นหาความแรงสูงสุดที่รองรับได้โดยใช้ CameraInfo.getMaxTorchStrengthLevel() แล้วตั้งค่าระดับที่ต้องการด้วย CameraControl.setTorchStrengthLevel()
  • การรองรับ NV21 ใน ImageAnalysis: ตอนนี้คุณสามารถขอรูปแบบรูปภาพ NV21 จาก ImageAnalysis ได้โดยตรง ซึ่งช่วยลดความซับซ้อนในการผสานรวมกับไลบรารีและ API อื่นๆ คุณสามารถเปิดใช้ฟีเจอร์นี้ได้โดยการเรียกใช้ ImageAnalysis.Builder.setOutputImageFormat(OUTPUT_IMAGE_FORMAT_NV21)

เริ่มต้นใช้งานได้เลยวันนี้

อัปเดตทรัพยากร Dependency เป็น CameraX 1.5 วันนี้ แล้วสำรวจฟีเจอร์ใหม่ที่น่าตื่นเต้น เราแทบรอไม่ไหวที่จะได้เห็นสิ่งที่คุณสร้าง

หากต้องการใช้ CameraX 1.5 โปรดเพิ่มทรัพยากร Dependency ต่อไปนี้ลงใน libs.versions.toml (เราขอแนะนำให้ใช้เวอร์ชัน 1.5.1 ซึ่งมีการแก้ไขข้อบกพร่องที่สำคัญหลายรายการและการปรับปรุงกล้องพร้อมกัน)

[versions]

camerax = "1.5.1"


[libraries]

..

androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "camerax" }

androidx-camera-compose = { module = "androidx.camera:camera-compose", version.ref = "camerax" }

androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "camerax" }

androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "camerax" }

androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camerax" }

androidx-camera-extensions = { module = "androidx.camera:camera-extensions", version.ref = "camerax" }

จากนั้นเพิ่มทรัพยากร Dependency เหล่านี้ลงใน build.gradle.kts ของโมดูล

dependencies {

  ..

  implementation(libs.androidx.camera.core)
  implementation(libs.androidx.camera.lifecycle)

  implementation(libs.androidx.camera.camera2)

  implementation(libs.androidx.camera.view) // for PreviewView 
  implementation(libs.androidx.camera.compose) // for compose UI

  implementation(libs.androidx.camera.extensions) // For Extensions 

}

หากมีคำถามหรือต้องการติดต่อกับทีม CameraX เข้าร่วมกลุ่มสนทนาสำหรับนักพัฒนาแอป CameraX หรือยื่นรายงานข้อบกพร่องได้ที่

เขียนโดย

อ่านต่อ