โดยทั่วไป ระบบการจับภาพจะบันทึกสตรีมวิดีโอและเสียง บีบอัด มัลติเพล็กซ์สตรีมทั้ง 2 แล้วเขียนสตรีมผลลัพธ์ลงในดิสก์
ใน CameraX โซลูชันสำหรับการจับภาพวิดีโอคือ
VideoCapture
กรณีการใช้งานต่อไปนี้
VideoCapture Use Caseดังที่แสดงในรูปที่ 2 การจับภาพวิดีโอด้วย CameraX มีคอมโพเนนต์ระดับสูง 2-3 รายการในสถาปัตยกรรม ดังนี้
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และ CameraX UseCases อื่นๆ ดูข้อมูลเพิ่มเติมเกี่ยวกับแนวคิดและการใช้งานเหล่านี้ได้ที่ สถาปัตยกรรม CameraXRecorderคือการใช้งาน VideoOutput ที่เชื่อมโยงอย่างใกล้ชิดกับVideoCaptureRecorderใช้เพื่อบันทึกวิดีโอและเสียง แอปพลิเคชันสร้างการบันทึกจาก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 ของ CameraX VideoCapture เข้ากับแอป ให้ทำดังนี้
- เชื่อมโยง
VideoCapture - เตรียมและกำหนดค่าการบันทึก
- เริ่มและควบคุมการบันทึกรันไทม์
ส่วนต่อไปนี้จะอธิบายสิ่งที่คุณทำได้ในแต่ละขั้นตอนเพื่อให้ได้เซสชันการบันทึกแบบครบวงจร
เชื่อมโยง VideoCapture
หากต้องการเชื่อมโยงกรณีการใช้งาน VideoCapture ให้ทำดังนี้
- สร้างออบเจ็กต์
Recorder - สร้าง
VideoCaptureออบเจ็กต์ - เชื่อมโยงกับ
Lifecycle
VideoCapture API ของ CameraX เป็นไปตามรูปแบบการออกแบบ Builder แอปพลิเคชัน
ใช้ Recorder.Builder เพื่อสร้าง Recorder นอกจากนี้ คุณยังกำหนดค่า
ความละเอียดของวิดีโอสำหรับ Recorder ผ่านออบเจ็กต์ QualitySelector ได้ด้วย
CameraX Recorder รองรับQualities
ที่กำหนดไว้ล่วงหน้าต่อไปนี้สำหรับความละเอียดของวิดีโอ
Quality.UHDสำหรับขนาดวิดีโอ 4K Ultra HD (2160p)Quality.FHDสำหรับขนาดวิดีโอ Full HD (1080p)Quality.HDสำหรับขนาดวิดีโอ HD (720p)Quality.SDสำหรับขนาดวิดีโอ SD (480p)
โปรดทราบว่า CameraX ยังเลือกความละเอียดอื่นๆ ได้ด้วยเมื่อแอปได้รับอนุญาต
ขนาดวิดีโอที่แน่นอนของแต่ละตัวเลือกจะขึ้นอยู่กับความสามารถของกล้องและตัวเข้ารหัส
ดูข้อมูลเพิ่มเติมได้ในเอกสารประกอบสำหรับ
CamcorderProfile
แอปพลิเคชันสามารถกำหนดค่าความละเอียดได้โดยการสร้าง
QualitySelector
คุณสร้าง QualitySelector ได้โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้
ระบุความละเอียดที่ต้องการ 2-3 รายการโดยใช้
fromOrderedList()และ ใส่กลยุทธ์สำรองไว้ใช้ในกรณีที่ระบบไม่รองรับความละเอียดที่ต้องการCameraX สามารถกำหนดการจับคู่สำรองที่ดีที่สุดตามความสามารถของกล้องที่เลือก โปรดดูรายละเอียดเพิ่มเติมใน
QualitySelectorFallbackStrategy specificationตัวอย่างเช่น โค้ดต่อไปนี้จะขอความละเอียดสูงสุดที่รองรับ สำหรับการบันทึก และหากไม่มีความละเอียดที่ขอใดที่รองรับได้ ให้สิทธิ์ CameraX เลือกความละเอียดที่ใกล้เคียงกับความละเอียด Quality.SD มากที่สุดval qualitySelector = QualitySelector.fromOrderedList( listOf(Quality.UHD, 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.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.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()เพื่อลงทะเบียนVideoRecordEventListener และเริ่มจับภาพวิดีโอ
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);
ควบคุมการบันทึกที่ใช้งานอยู่
คุณหยุดชั่วคราว เล่นต่อ และหยุด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
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับ CameraX ได้ที่แหล่งข้อมูลเพิ่มเติมต่อไปนี้
- Codelab การเริ่มต้นใช้งาน CameraX
- แอปตัวอย่าง CameraX อย่างเป็นทางการ
- รายการ CameraX Video Capture API ล่าสุด
- บันทึกประจำรุ่นของ CameraX
- ซอร์สโค้ด CameraX