โดยทั่วไปแล้ว ระบบการบันทึกจะบันทึกสตรีมวิดีโอและสตรีมเสียง บีบอัดสตรีม มัลติเพล็กซ์สตรีมทั้ง 2 รายการ แล้วเขียนสตรีมที่ได้ลงในดิสก์
ใน CameraX โซลูชันสำหรับการจับภาพวิดีโอคือกรณีการใช้งาน VideoCapture
VideoCaptureดังที่แสดงในรูปที่ 2 การจับภาพวิดีโอ CameraX ประกอบด้วยคอมโพเนนต์สถาปัตยกรรมระดับสูงบางอย่าง ได้แก่
SurfaceProviderสำหรับแหล่งที่มาของวิดีโอAudioSourceสำหรับแหล่งที่มาของเสียง- โปรแกรมเปลี่ยนไฟล์ 2 รายการเพื่อเข้ารหัสและบีบอัดวิดีโอ/เสียง
- ตัวมัลติเพล็กซ์สื่อเพื่อมัลติเพล็กซ์สตรีมทั้ง 2 รายการ
- เครื่องมือบันทึกไฟล์เพื่อเขียนผลลัพธ์
VideoCapture API จะแยกส่วนเครื่องมือการจับภาพที่ซับซ้อนและมอบ API ที่เรียบง่ายและตรงไปตรงมามากขึ้นให้แก่แอปพลิเคชัน
ภาพรวมของ VideoCapture API
VideoCapture เป็น Use Case ของ CameraX ที่ทำงานได้ดีด้วยตัวเองหรือเมื่อใช้ร่วมกับ Use Case อื่นๆ ชุดค่าผสมที่รองรับโดยเฉพาะจะขึ้นอยู่กับความสามารถของฮาร์ดแวร์กล้อง แต่ Preview และ VideoCapture เป็นชุดค่าผสมของ Use Case ที่ถูกต้องในอุปกรณ์ทั้งหมด
VideoCapture API ประกอบด้วยออบเจ็กต์ต่อไปนี้ที่สื่อสารกับแอปพลิเคชัน
VideoCaptureคือคลาสกรณีการใช้งานระดับบนสุดVideoCaptureจะเชื่อมโยงกับLifecycleOwnerด้วยCameraSelectorและ UseCase อื่นๆ ของ CameraX ดูข้อมูลเพิ่มเติมเกี่ยวกับแนวคิดและการใช้งานเหล่านี้ได้ที่สถาปัตยกรรม CameraXRecorderคือการติดตั้งใช้งาน VideoOutput ที่เชื่อมต่อกับVideoCaptureอย่างแน่นหนาRecorderใช้เพื่อจับภาพวิดีโอและเสียง แอปพลิเคชันจะสร้างการบันทึกจากRecorderPendingRecordingจะกำหนดค่าการบันทึก โดยมีตัวเลือกต่างๆ เช่น การเปิดใช้เสียงและการตั้งค่า Listener เหตุการณ์ คุณต้องใช้Recorderเพื่อสร้างPendingRecordingPendingRecordingจะไม่บันทึกข้อมูลใดๆRecordingจะทำการบันทึกจริง คุณต้องใช้PendingRecordingเพื่อสร้างRecording
รูปที่ 3 แสดงความสัมพันธ์ระหว่างออบเจ็กต์เหล่านี้
คำอธิบาย:
- สร้าง
Recorderด้วยQualitySelector - กำหนดค่า
Recorderด้วยOutputOptionsรายการใดรายการหนึ่ง - เปิดใช้เสียงด้วย
withAudioEnabled()หากจำเป็น - โทรหา
start()พร้อมกับผู้ฟังVideoRecordEventเพื่อเริ่มบันทึก - ใช้
pause()/resume()/stop()บนRecordingเพื่อควบคุมการบันทึก - ตอบสนองต่อ
VideoRecordEventsภายใน Listener เหตุการณ์
รายการ API โดยละเอียดอยู่ใน current.txt ภายในซอร์สโค้ด
การใช้ VideoCapture API
หากต้องการผสานรวม Use Case VideoCapture ของ CameraX เข้ากับแอป ให้ทำดังนี้
- ผูก
VideoCapture - เตรียมและกำหนดค่าการบันทึก
- เริ่มและควบคุมการบันทึกรันไทม์
ส่วนต่อไปนี้จะอธิบายสิ่งที่คุณทำได้ในแต่ละขั้นตอนเพื่อให้ได้เซสชันการบันทึกตั้งแต่ต้นจนจบ
เชื่อมโยง VideoCapture
หากต้องการเชื่อมโยงกรณีการใช้งาน VideoCapture ให้ทำดังนี้
- สร้างออบเจ็กต์
Recorder - สร้างออบเจ็กต์
VideoCaptureรายการ - เชื่อมโยงกับ
Lifecycle
CameraX VideoCapture API เป็นไปตามรูปแบบการออกแบบ Builder แอปพลิเคชันใช้ Recorder.Builder เพื่อสร้าง Recorder นอกจากนี้ คุณยังกำหนดค่าความละเอียดวิดีโอสำหรับ Recorder ผ่านออบเจ็กต์ QualitySelector ได้ด้วย
CameraX Recorder รองรับ Qualities ที่กำหนดไว้ล่วงหน้าต่อไปนี้สำหรับความละเอียดของวิดีโอ
Quality.UHDสำหรับวิดีโอขนาด 4K Ultra HD (2160p)Quality.QHDสำหรับขนาดวิดีโอ Quad HD (1440p) ซึ่งเปิดตัวใน CameraX1.7.0-alpha02Quality.FHDสำหรับขนาดวิดีโอ Full HD (1080p)Quality.HDสำหรับขนาดวิดีโอความละเอียดสูง (720p)Quality.SDสำหรับขนาดวิดีโอ SD (480p)
โปรดทราบว่า CameraX ยังเลือกความละเอียดอื่นๆ ได้ด้วยเมื่อได้รับอนุญาตจากแอป
ขนาดวิดีโอที่แน่นอนของแต่ละตัวเลือกจะขึ้นอยู่กับความสามารถของกล้องและโปรแกรมเปลี่ยนไฟล์ ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบของ CamcorderProfile
แอปพลิเคชันสามารถกำหนดค่าการแปลงได้โดยสร้าง QualitySelector
คุณสร้าง QualitySelector ได้โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้
ระบุความละเอียดที่ต้องการ 2-3 รายการโดยใช้
fromOrderedList()และรวมกลยุทธ์สำรองเพื่อใช้ในกรณีที่ไม่รองรับความละเอียดที่ต้องการCameraX สามารถตัดสินใจเลือกรายการสำรองที่ตรงกันที่สุดตามความสามารถของกล้องที่เลือก โปรดดูรายละเอียดเพิ่มเติมที่
FallbackStrategy specificationของQualitySelectorตัวอย่างเช่น โค้ดต่อไปนี้จะขอความละเอียดสูงสุดที่รองรับสำหรับการบันทึก และหากไม่รองรับความละเอียดที่ขอเลย ให้อนุญาต CameraX เลือกความละเอียดที่ใกล้เคียงกับความละเอียด Quality.SD มากที่สุดval qualitySelector = QualitySelector.fromOrderedList( listOf(Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD), FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))ค้นหาความสามารถของกล้องก่อน แล้วเลือกจากความละเอียดที่รองรับโดยใช้
QualitySelector::from():val cameraInfo = cameraProvider.availableCameraInfos.filter { Camera2CameraInfo .from(it) .getCameraCharacteristic(CameraCharacteristics.LENS\_FACING) == CameraMetadata.LENS_FACING_BACK } val supportedQualities = QualitySelector.getSupportedQualities(cameraInfo[0]) val filteredQualities = arrayListOf (Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD) .filter { supportedQualities.contains(it) } // Use a simple ListView with the id of simple_quality_list_view viewBinding.simpleQualityListView.apply { adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, filteredQualities.map { it.qualityToString() }) // Set up the user interaction to manually show or hide the system UI. setOnItemClickListener { _, _, position, _ -> // Inside View.OnClickListener, // convert Quality.* constant to QualitySelector val qualitySelector = QualitySelector.from(filteredQualities[position]) // Create a new Recorder/VideoCapture for the new quality // and bind to lifecycle val recorder = Recorder.Builder() .setQualitySelector(qualitySelector).build() // ... } } // A helper function to translate Quality to a string fun Quality.qualityToString() : String { return when (this) { Quality.UHD -> "UHD" Quality.QHD -> "QHD" Quality.FHD -> "FHD" Quality.HD -> "HD" Quality.SD -> "SD" else -> throw IllegalArgumentException() } }โปรดทราบว่าความสามารถที่แสดงผลจาก
QualitySelector.getSupportedQualities()รับประกันว่าจะทำงานได้กับกรณีการใช้งานVideoCaptureหรือกรณีการใช้งานVideoCaptureและPreviewร่วมกัน เมื่อเชื่อมโยงร่วมกับ Use CaseImageCaptureหรือImageAnalysisCameraX อาจยังคงเชื่อมโยงไม่สำเร็จเมื่อกล้องที่ขอไม่รองรับชุดค่าผสมที่จำเป็น
เมื่อมี QualitySelector แล้ว แอปพลิเคชันจะสร้างออบเจ็กต์ VideoCapture และทำการเชื่อมโยงได้ โปรดทราบว่าการเชื่อมโยงนี้
เหมือนกับกรณีการใช้งานอื่นๆ
val recorder = Recorder.Builder()
.setExecutor(cameraExecutor).setQualitySelector(qualitySelector)
.build()
val videoCapture = VideoCapture.withOutput(recorder)
try {
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture)
} catch(exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
โปรดทราบว่า bindToLifecycle() จะแสดงผลออบเจ็กต์ Camera ดูข้อมูลเพิ่มเติมเกี่ยวกับการควบคุมเอาต์พุตของกล้อง เช่น การซูมและการเปิดรับแสง ได้ที่คู่มือนี้
Recorder จะเลือกรูปแบบที่เหมาะสมที่สุดสำหรับระบบ ตัวแปลงรหัสวิดีโอที่ใช้กันมากที่สุดคือ H.264 AVC ที่มีรูปแบบคอนเทนเนอร์ MPEG-4
กำหนดค่าและสร้างไฟล์บันทึก
แอปพลิเคชันสามารถสร้างออบเจ็กต์การบันทึกจาก Recorder เพื่อจับภาพวิดีโอและเสียงได้ แอปพลิเคชันจะสร้างไฟล์บันทึกเสียงโดยทำดังนี้
- กำหนดค่า
OutputOptionsด้วยprepareRecording() - (ไม่บังคับ) เปิดใช้การบันทึกเสียง
- ใช้
start()เพื่อลงทะเบียน ListenerVideoRecordEventและเริ่มจับภาพวิดีโอ
Recorder จะแสดงผลออบเจ็กต์ Recording เมื่อคุณเรียกใช้ฟังก์ชัน start()
แอปพลิเคชันของคุณสามารถใช้ออบเจ็กต์ Recording นี้เพื่อจับภาพให้เสร็จหรือดำเนินการอื่นๆ เช่น หยุดชั่วคราวหรือกลับมาทำงานต่อ
Recorder รองรับออบเจ็กต์ Recording ครั้งละ 1 รายการ คุณจะเริ่มการบันทึกใหม่ได้เมื่อเรียกใช้ Recording.stop() หรือ Recording.close() ในออบเจ็กต์ Recording ก่อนหน้าแล้ว
มาดูรายละเอียดเพิ่มเติมของขั้นตอนเหล่านี้กัน ขั้นแรก แอปพลิเคชันจะกำหนดค่า OutputOptions สำหรับโปรแกรมอัดเสียงด้วย Recorder.prepareRecording()
Recorder รองรับOutputOptionsประเภทต่อไปนี้
FileDescriptorOutputOptionsเพื่อบันทึกลงในFileDescriptorFileOutputOptionsสำหรับการบันทึกเป็นFileMediaStoreOutputOptionsเพื่อบันทึกลงในMediaStore
OutputOptions ทุกประเภทช่วยให้คุณกำหนดขนาดไฟล์สูงสุดด้วย setFileSizeLimit() ได้ ตัวเลือกอื่นๆ จะเจาะจงสำหรับประเภทเอาต์พุตแต่ละประเภท เช่น ParcelFileDescriptor สำหรับ FileDescriptorOutputOptions
prepareRecording() แสดงผลออบเจ็กต์ PendingRecording ซึ่งเป็นออบเจ็กต์ระดับกลางที่ใช้สร้างออบเจ็กต์ Recording ที่เกี่ยวข้อง PendingRecording เป็นคลาสชั่วคราวที่ควรจะมองไม่เห็นในกรณีส่วนใหญ่ และแอปไม่ค่อยแคชไว้
แอปพลิเคชันสามารถกำหนดค่าการบันทึกเพิ่มเติมได้ เช่น
- เปิดใช้เสียงด้วย
withAudioEnabled() - ลงทะเบียน Listener เพื่อรับเหตุการณ์การบันทึกวิดีโอด้วย
start(Executor, Consumer<VideoRecordEvent>) - อนุญาตให้การบันทึกต่อเนื่องขณะที่ VideoCapture ที่แนบอยู่ถูกเชื่อมโยงกับกล้องอีกตัวด้วย
PendingRecording.asPersistentRecording()
หากต้องการเริ่มบันทึก ให้โทรหา PendingRecording.start() CameraX จะเปลี่ยน PendingRecording เป็น Recording จัดคิวคำขอบันทึก และแสดงผลออบเจ็กต์ Recording ที่สร้างขึ้นใหม่ไปยังแอปพลิเคชัน
เมื่อการบันทึกเริ่มขึ้นในอุปกรณ์กล้องที่เกี่ยวข้อง CameraX จะส่งเหตุการณ์ VideoRecordEvent.EVENT_TYPE_START
ตัวอย่างต่อไปนี้แสดงวิธีบันทึกวิดีโอและเสียงลงในไฟล์ MediaStore
// Create MediaStoreOutputOptions for our recorder
val name = "CameraX-recording-" +
SimpleDateFormat(FILENAME_FORMAT, Locale.US)
.format(System.currentTimeMillis()) + ".mp4"
val contentValues = ContentValues().apply {
put(MediaStore.Video.Media.DISPLAY_NAME, name)
}
val mediaStoreOutput = MediaStoreOutputOptions.Builder(this.contentResolver,
MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
.setContentValues(contentValues)
.build()
// 2. Configure Recorder and Start recording to the mediaStoreOutput.
val recording = videoCapture.output
.prepareRecording(context, mediaStoreOutput)
.withAudioEnabled()
.start(ContextCompat.getMainExecutor(this), captureListener)
แม้ว่าตัวอย่างภาพจากกล้องจะแสดงแบบกลับด้านในกล้องหน้าโดยค่าเริ่มต้น แต่วิดีโอที่บันทึกโดย VideoCapture จะไม่แสดงแบบกลับด้านโดยค่าเริ่มต้น เมื่อใช้ CameraX 1.3 คุณจะสามารถมิเรอร์การบันทึกวิดีโอเพื่อให้ตัวอย่างจากกล้องหน้าและวิดีโอที่บันทึกไว้ตรงกันได้
ตัวเลือก MirrorMode มี 3 รายการ ได้แก่ MIRROR_MODE_OFF, MIRROR_MODE_ON และ MIRROR_MODE_ON_FRONT_ONLY Google ขอแนะนำให้ใช้ MIROR_MODE_ON_FRONT_ONLY เพื่อให้สอดคล้องกับตัวอย่างภาพจากกล้อง ซึ่งหมายความว่าระบบจะไม่เปิดใช้การมิเรอร์สำหรับกล้องหลัง แต่จะเปิดใช้สำหรับกล้องหน้า ดูข้อมูลเพิ่มเติมเกี่ยวกับ MirrorMode ได้ที่ MirrorMode constants
ข้อมูลโค้ดนี้แสดงวิธีเรียกใช้ VideoCapture.Builder.setMirrorMode() โดยใช้ MIRROR_MODE_ON_FRONT_ONLY ดูข้อมูลเพิ่มเติมได้ที่ setMirrorMode()
Kotlin
val recorder = Recorder.Builder().build() val videoCapture = VideoCapture.Builder(recorder) .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY) .build() useCases.add(videoCapture);
Java
Recorder.Builder builder = new Recorder.Builder(); if (mVideoQuality != QUALITY_AUTO) { builder.setQualitySelector( QualitySelector.from(mVideoQuality)); } VideoCapture<Recorder> videoCapture = new VideoCapture.Builder<>(builder.build()) .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY) .build(); useCases.add(videoCapture);
ช่วงไดนามิก (วิดีโอ HDR)
CameraX รองรับการบันทึกวิดีโอ High Dynamic Range (HDR) 10 บิต เช่น HLG10, HDR10, HDR10+ หรือ Dolby Vision โดยใช้ DynamicRange
หากต้องการใช้การบันทึกวิดีโอ HDR ให้ทำตามขั้นตอนต่อไปนี้
- ค้นหาช่วงไดนามิกที่กล้องรองรับโดยใช้
VideoCapabilities.getSupportedDynamicRanges() - ไม่บังคับ: หากคุณกำหนดค่า
QualitySelectorที่กำหนดเอง ให้ตรวจสอบคุณภาพที่รองรับสำหรับช่วงไดนามิกนั้นโดยใช้getSupportedQualities(DynamicRange) - กำหนดค่า
VideoCapture.Builderด้วยsetDynamicRange()
ตัวอย่างต่อไปนี้จะเปิดใช้การบันทึก HDR 10 บิตแบบ HLG เมื่อกล้องรองรับ
Kotlin
val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo) val supportedHdrRanges = videoCapabilities.supportedDynamicRanges .filter { it != DynamicRange.SDR } val recorder = Recorder.Builder().build() val videoCapture = VideoCapture.Builder(recorder) .apply { if (supportedHdrRanges.contains(DynamicRange.HLG_10_BIT)) { setDynamicRange(DynamicRange.HLG_10_BIT) } } .build()
Java
VideoCapabilities videoCapabilities = Recorder.getVideoCapabilities(cameraInfo); Set<DynamicRange> supportedRanges = videoCapabilities.getSupportedDynamicRanges(); Recorder recorder = new Recorder.Builder().build(); VideoCapture.Builder<Recorder> builder = new VideoCapture.Builder<>(recorder); if (supportedRanges.contains(DynamicRange.HLG_10_BIT)) { builder.setDynamicRange(DynamicRange.HLG_10_BIT); } VideoCapture<Recorder> videoCapture = builder.build();
การป้องกันภาพวิดีโอสั่นไหว
CameraX รองรับระบบกันสั่นของวิดีโอเพื่อลดการสั่นไหวและกระตุกเมื่อถือกล้องถ่ายวิดีโอด้วยมือ
หากต้องการเปิดใช้ระบบกันภาพสั่นไหวของวิดีโอ ให้ทำตามขั้นตอนต่อไปนี้
- ตรวจสอบว่าอุปกรณ์กล้องรองรับระบบกันสั่นหรือไม่โดยใช้
VideoCapabilities.isStabilizationSupported() - เปิดใช้ใน
VideoCapture.Builderโดยใช้setVideoStabilizationEnabled(true)
ตัวอย่างต่อไปนี้จะเปิดใช้ระบบกันภาพสั่นเมื่อกล้องรองรับ
Kotlin
val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo) val videoCapture = VideoCapture.Builder(recorder) .setVideoStabilizationEnabled(videoCapabilities.isStabilizationSupported) .build()
Java
VideoCapabilities videoCapabilities = Recorder.getVideoCapabilities(cameraInfo); VideoCapture<Recorder> videoCapture = new VideoCapture.Builder<>(recorder) .setVideoStabilizationEnabled(videoCapabilities.isStabilizationSupported()) .build();
ควบคุมการบันทึกที่ทำงานอยู่
คุณหยุดชั่วคราว เล่นต่อ และหยุดRecordingที่กำลังดำเนินอยู่ได้โดยใช้วิธีต่อไปนี้
pauseเพื่อหยุดการบันทึกที่กำลังทำงานอยู่ชั่วคราวresume()เพื่อบันทึกต่อจากที่หยุดชั่วคราวไว้stop()เพื่อสิ้นสุดการบันทึกและล้างออบเจ็กต์การบันทึกที่เกี่ยวข้องmute()เพื่อปิดหรือเปิดเสียงไฟล์บันทึกปัจจุบัน
โปรดทราบว่าคุณสามารถเรียกใช้ stop() เพื่อสิ้นสุด Recording ได้ไม่ว่าการบันทึกจะอยู่ในสถานะหยุดชั่วคราวหรือกำลังบันทึกอยู่ก็ตาม
หากคุณลงทะเบียน EventListener ไว้กับ PendingRecording.start() แล้ว Recording จะสื่อสารโดยใช้ VideoRecordEvent
VideoRecordEvent.EVENT_TYPE_STATUSใช้สำหรับบันทึกสถิติ เช่น ขนาดไฟล์ปัจจุบันและระยะเวลาที่บันทึกVideoRecordEvent.EVENT_TYPE_FINALIZEใช้สำหรับผลลัพธ์การบันทึกและมีข้อมูล เช่น URI ของไฟล์สุดท้ายพร้อมกับข้อผิดพลาดที่เกี่ยวข้อง
เมื่อแอปได้รับ EVENT_TYPE_FINALIZE ที่ระบุว่าเซสชันการบันทึกเสร็จสมบูรณ์แล้ว คุณจะเข้าถึงวิดีโอที่บันทึกไว้ได้จากตำแหน่งที่ระบุใน OutputOptions
แอมพลิจูดและสถานะของเสียงแบบเรียลไทม์
ในระหว่างการบันทึก เหตุการณ์ VideoRecordEvent.Status จะให้สถิติเสียงแบบเรียลไทม์ผ่าน AudioStats ดังนี้
AudioStats.getAudioAmplitude()จะแสดงแอมพลิจูดสูงสุดของเสียงในปัจจุบัน ซึ่งมีตั้งแต่0.0ถึง1.0คุณสามารถใช้ค่านี้เพื่อขับเคลื่อนมิเตอร์ UI หรือเครื่องมือแสดงภาพรูปคลื่นเสียงได้AudioStats.getAudioState()ระบุสถานะปัจจุบันของสตรีมเสียง เช่นAUDIO_STATE_ACTIVE,AUDIO_STATE_MUTEDหรือAUDIO_STATE_SOURCE_SILENCED
ตัวอย่างต่อไปนี้จะอ่านแอมพลิจูดของเสียงจากเหตุการณ์สถานะ
Kotlin
when (event) { is VideoRecordEvent.Status -> { val audioStats = event.recordingStats.audioStats if (audioStats.hasAudio()) { val amplitude = audioStats.audioAmplitude updateAudioWaveform(amplitude) } } // ... }
Java
if (event instanceof VideoRecordEvent.Status) { VideoRecordEvent.Status status = (VideoRecordEvent.Status) event; AudioStats audioStats = status.getRecordingStats().getAudioStats(); if (audioStats.hasAudio()) { double amplitude = audioStats.getAudioAmplitude(); updateAudioWaveform(amplitude); } }
วิดีโอความเร็วสูงและสโลว์โมชัน
CameraX รองรับการบันทึกวิดีโอความเร็วสูง เช่น 120, 240 หรือ 480 FPS ซึ่งช่วยให้ใช้งานได้ 2 กรณีที่แตกต่างกัน ดังนี้
- วิดีโอที่มีอัตราเฟรมสูง (สโลว์โมชันที่จัดการโดยเพลเยอร์): CameraX จะจับภาพและบันทึกเฟรมที่อัตราเฟรมสูง (เช่น 120 FPS) วิดีโอเพลเยอร์จะควบคุมความเร็วในการเล่น ซึ่งช่วยให้ผู้ใช้สลับระหว่างความเร็วปกติกับสโลว์โมชันหรือทำการวิเคราะห์แบบเฟรมต่อเฟรมได้
- วิดีโอสโลว์โมชันที่พร้อมเล่น: CameraX จะประมวลผลสตรีมความเร็วสูงและแสดงผลไฟล์วิดีโอมาตรฐาน 30 FPS พร้อมการประทับเวลาเฟรมที่ปรับแล้ว เอฟเฟกต์สโลว์โมชันจะ "ฝังอยู่" ในวิดีโอ ดังนั้นวิดีโอจะเล่นแบบสโลว์โมชันโดยอัตโนมัติในวิดีโอเพลเยอร์มาตรฐานโดยไม่ต้องใช้เพลเยอร์พิเศษ ตัวอย่างเช่น การจับภาพ 120 FPS ที่เล่นที่ 30 FPS จะสร้างวิดีโอสโลว์โมชัน 1/4 เท่า
ตรวจสอบความสามารถในการเชื่อมต่อความเร็วสูง
การจับภาพวิดีโอความเร็วสูงต้องใช้การรองรับฮาร์ดแวร์และคำจำกัดความ CamcorderProfile ที่เกี่ยวข้องจากผู้ผลิตอุปกรณ์ เช่น CamcorderProfile.QUALITY_HIGH_SPEED_1080P หรือ QUALITY_HIGH_SPEED_720P
ก่อนกำหนดค่าการบันทึกความเร็วสูง ให้ค้นหาความสามารถความเร็วสูงโดยใช้ Recorder.getHighSpeedVideoCapabilities(CameraInfo) ดังนี้
Kotlin
val highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo) if (highSpeedCapabilities == null) { // Camera does not support high-speed video capture return } val supportedQualities = highSpeedCapabilities.getSupportedQualities(DynamicRange.SDR)
Java
VideoCapabilities highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo); if (highSpeedCapabilities == null) { // Camera does not support high-speed video capture return; } List<Quality> supportedQualities = highSpeedCapabilities.getSupportedQualities(DynamicRange.SDR);
กำหนดค่า HighSpeedVideoSessionConfig
หากต้องการใช้การจับภาพความเร็วสูง ให้รวมกรณีการใช้งาน VideoCapture และ Preview ไว้ใน HighSpeedVideoSessionConfig หากต้องการกำหนดค่าเซสชัน ให้ทำตามขั้นตอนต่อไปนี้
- สร้างกรณีการใช้งาน
VideoCaptureและกรณีการใช้งานPreview - เริ่มต้น
HighSpeedVideoSessionConfig.Builderด้วยกรณีการใช้งานVideoCaptureและแนบPreview - ค้นหาช่วงอัตราเฟรมที่รองรับโดยใช้
CameraInfo.getSupportedFrameRateRanges(SessionConfig)และตั้งค่าช่วงที่เลือก - เลือกระหว่างวิดีโอที่มีอัตราเฟรมสูงหรือวิดีโอสโลว์โมชันที่พร้อมเล่น โดยทำดังนี้
- หากต้องการสร้างวิดีโอที่มีอัตราเฟรมสูง ให้ปล่อย
setSlowMotionEnabled(false)ไว้ (ค่าเริ่มต้น) - หากต้องการสร้างวิดีโอสโลว์โมชันที่พร้อมเล่น ให้เรียกใช้
setSlowMotionEnabled(true)
- หากต้องการสร้างวิดีโอที่มีอัตราเฟรมสูง ให้ปล่อย
- เชื่อมโยงการกำหนดค่าเซสชันโดยใช้
cameraProvider.bindToLifecycle()
ตัวอย่างต่อไปนี้จะกำหนดค่าและเชื่อมโยงเซสชันสโลว์โมชันที่พร้อมเล่น
Kotlin
val preview = Preview.Builder().build() val recorder = Recorder.Builder() .setQualitySelector(QualitySelector.from(supportedQualities.first())) .build() val videoCapture = VideoCapture.withOutput(recorder) // Build HighSpeedVideoSessionConfig val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture) .setPreview(preview) // Enable automatic slow-motion playback at 30 fps .setSlowMotionEnabled(true) // Query and set a supported high-speed frame rate range (such as 120 or 240 fps). // The set is non-empty because getHighSpeedVideoCapabilities() returned non-null earlier. val supportedFpsRanges = cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build()) sessionConfigBuilder.setFrameRateRange(supportedFpsRanges.first()) val sessionConfig = sessionConfigBuilder.build() // Bind session config to lifecycle cameraProvider.bindToLifecycle( lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA, sessionConfig )
Java
Preview preview = new Preview.Builder().build(); Recorder recorder = new Recorder.Builder() .setQualitySelector(QualitySelector.from(supportedQualities.get(0))) .build(); VideoCapture<Recorder> videoCapture = VideoCapture.withOutput(recorder); HighSpeedVideoSessionConfig.Builder sessionConfigBuilder = new HighSpeedVideoSessionConfig.Builder(videoCapture) .setPreview(preview) .setSlowMotionEnabled(true); // The set is non-empty because getHighSpeedVideoCapabilities() returned non-null earlier. Set<Range<Integer>> supportedFpsRanges = cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build()); sessionConfigBuilder.setFrameRateRange(supportedFpsRanges.iterator().next()); HighSpeedVideoSessionConfig sessionConfig = sessionConfigBuilder.build(); cameraProvider.bindToLifecycle( lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA, sessionConfig );
นอกจากนี้ คุณยังใช้ Kotlin DSL ซึ่งเปิดตัวใน CameraX 1.7.0-alpha02 เพื่อกำหนดค่าเซสชันความเร็วสูงอย่างกระชับได้ด้วย โดยทำดังนี้
val sessionConfig = highSpeedVideoSessionConfig(videoCapture) {
this.preview = preview
isSlowMotionEnabled = true
frameRateRange = supportedFpsRanges.first()
}
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
sessionConfig
)
บันทึกวิดีโอความเร็วสูงหรือสโลว์โมชัน
หลังจากเชื่อมต่อ HighSpeedVideoSessionConfig แล้ว ให้เริ่มบันทึกโดยใช้ VideoCapture ในลักษณะเดียวกับการบันทึกวิดีโอมาตรฐาน ดังนี้
Kotlin
val recording = videoCapture.output .prepareRecording(context, mediaStoreOutput) .withAudioEnabled() .start(ContextCompat.getMainExecutor(context)) { event -> when (event) { is VideoRecordEvent.Start -> Log.d(TAG, "Recording started") is VideoRecordEvent.Finalize -> { if (!event.hasError()) { Log.d(TAG, "Video saved: ${event.outputResults.outputUri}") } } } }
Java
Recording recording = videoCapture.getOutput() .prepareRecording(context, mediaStoreOutput) .withAudioEnabled() .start(ContextCompat.getMainExecutor(context), event -> { if (event instanceof VideoRecordEvent.Start) { Log.d(TAG, "Recording started"); } else if (event instanceof VideoRecordEvent.Finalize) { VideoRecordEvent.Finalize finalize = (VideoRecordEvent.Finalize) event; if (!finalize.hasError()) { Log.d(TAG, "Video saved: " + finalize.getOutputResults().getOutputUri()); } } });
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับ CameraX ได้ที่แหล่งข้อมูลเพิ่มเติมต่อไปนี้
- Codelab สำหรับการเริ่มต้นใช้งาน CameraX
- แอปตัวอย่าง CameraX อย่างเป็นทางการ
- รายการ API การจับภาพวิดีโอ CameraX ล่าสุด
- บันทึกประจำรุ่นของ CameraX
- ซอร์สโค้ด CameraX
- การจับภาพความเร็วสูงและวิดีโอสโลว์โมชันด้วย CameraX 1.5