Sistem perekaman umumnya merekam streaming video dan audio, mengompresinya, menggabungkan dua streaming secara multipleks, lalu menulis streaming yang dihasilkan ke disk.
Di CameraX, solusi untuk perekaman video adalah kasus penggunaan
VideoCapture
:
Seperti yang ditunjukkan dalam gambar 2, perekaman video CameraX menyertakan beberapa komponen arsitektur tingkat tinggi:
SurfaceProvider
untuk sumber video.AudioSource
untuk sumber audio.- Dua encoder untuk mengenkode dan mengompresi video/audio.
- Penggabung multipleks media untuk menggabungkan dua streaming secara multipleks.
- Penyimpan file untuk menuliskan hasilnya.
VideoCapture API meringkas mesin perekaman yang kompleks serta memberikan API yang jauh lebih sederhana dan mudah ke aplikasi.
Ringkasan VideoCapture API
VideoCapture
adalah kasus penggunaan CameraX yang berfungsi dengan sendirinya atau saat
digabungkan dengan kasus penggunaan lainnya. Kombinasi tertentu yang didukung bergantung pada
kemampuan hardware kamera, tetapi Preview
dan VideoCapture
adalah
kombinasi kasus penggunaan yang valid di semua perangkat.
VideoCapture API terdiri dari objek berikut yang berkomunikasi dengan aplikasi:
VideoCapture
adalah class kasus penggunaan level teratas.VideoCapture
terikat padaLifecycleOwner
denganCameraSelector
dan UseCases CameraX lainnya. Untuk mengetahui informasi konsep dan penggunaan ini lebih lanjut, lihat Arsitektur CameraX.Recorder
adalah implementasi VideoOutput yang dikaitkan erat denganVideoCapture
.Recorder
digunakan untuk melakukan perekaman video dan audio. Aplikasi membuat rekaman dariRecorder
.PendingRecording
mengonfigurasi perekaman, yang memberikan opsi seperti mengaktifkan audio dan menyetel pemroses peristiwa. Anda harus menggunakanRecorder
untuk membuatPendingRecording
.PendingRecording
tidak merekam apa pun.Recording
akan melakukan perekaman yang sebenarnya. Anda harus menggunakanPendingRecording
untuk membuatRecording
.
Gambar 3 menunjukkan hubungan antara objek ini:
Keterangan:
- Membuat
Recorder
denganQualitySelector
. - Mengonfigurasi
Recorder
dengan salah satuOutputOptions
. - Mengaktifkan audio dengan
withAudioEnabled()
jika diperlukan. - Memanggil
start()
dengan pemrosesVideoRecordEvent
untuk mulai merekam. - Menggunakan
pause()
/resume()
/stop()
padaRecording
untuk mengontrol perekaman. - Merespons
VideoRecordEvents
dalam pemroses peristiwa Anda.
Daftar API mendetail ada di current.txt dalam kode sumber.
Menggunakan VideoCapture API
Untuk mengintegrasikan kasus penggunaan VideoCapture
CameraX ke dalam aplikasi Anda,
lakukan langkah-langkah berikut:
- Ikat
VideoCapture
. - Siapkan dan konfigurasikan perekaman.
- Mulai dan kontrol perekaman runtime.
Bagian berikut menguraikan hal-hal yang dapat Anda lakukan di setiap langkah untuk mendapatkan sesi perekaman menyeluruh.
Mengikat VideoCapture
Untuk mengikat kasus penggunaan VideoCapure
, lakukan langkah-langkah berikut:
- Buat objek
Recorder
. - Buat objek
VideoCapture
. - Ikatkan ke
Lifecycle
.
VideoCapture API CameraX mengikuti pola desain builder. Aplikasi
menggunakan Recorder.Builder
untuk membuat Recorder
. Anda juga dapat mengonfigurasi
resolusi video untuk Recorder
melalui objek QualitySelector
.
Recorder
CameraX mendukung Qualities
berikut yang telah ditentukan sebelumnya
untuk resolusi video:
Quality.UHD
untuk ukuran video ultra HD 4K (2160p)Quality.FHD
untuk ukuran video full HD (1080p)Quality.HD
untuk ukuran video HD (720p)Quality.SD
untuk ukuran video SD (480p)
Perhatikan bahwa CameraX juga memilih resolusi lain saat diizinkan oleh aplikasi.
Ukuran video yang tepat dari setiap pilihan bergantung pada kemampuan kamera dan
encoder. Untuk mengetahui informasi selengkapnya, baca dokumentasi untuk
CamcorderProfile
.
Aplikasi dapat mengonfigurasi resolusi dengan membuat
QualitySelector
.
Anda dapat membuat QualitySelector
menggunakan salah satu metode berikut:
Berikan beberapa resolusi pilihan menggunakan
fromOrderedList()
, dan sertakan strategi penggantian untuk digunakan jika tidak ada resolusi pilihan yang didukung.CameraX dapat menentukan pencocokan penggantian terbaik berdasarkan kemampuan kamera yang dipilih, lihat
FallbackStrategy specification
QualitySelector
untuk detail selengkapnya. Misalnya, kode berikut meminta resolusi tertinggi yang didukung untuk perekaman, dan jika tidak ada resolusi permintaan yang dapat didukung, izinkan CameraX untuk memilih resolusi yang paling mendekati resolusi Quality.SD:val qualitySelector = QualitySelector.fromOrderedList( listOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD), FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))
Buat kueri kapabilitas kamera terlebih dahulu, dan pilih dari resolusi yang didukung menggunakan
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() } }
Perhatikan bahwa kemampuan yang ditampilkan dari
QualitySelector.getSupportedQualities()
dijamin berfungsi untuk kasus penggunaanVideoCapture
ataupun kombinasi kasus penggunaanVideoCapture
danPreview
. Saat melakukan binding dengan kasus penggunaanImageCapture
atauImageAnalysis
, CameraX mungkin masih menggagalkan binding jika kombinasi yang diperlukan tidak didukung pada kamera yang diminta.
Setelah Anda memiliki QualitySelector
, aplikasi dapat membuat
objek VideoCapture
dan melakukan binding. Perhatikan bahwa binding ini
sama dengan kasus penggunaan lainnya:
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)
}
Perhatikan bahwa bindToLifecycle()
menampilkan objek Camera
. Lihat panduan ini untuk informasi mengontrol output kamera selengkapnya, seperti zoom dan eksposur.
Recorder
akan memilih format yang paling cocok untuk sistem. Codec video
yang paling umum adalah
H.264 AVC) dengan
format penampung
MPEG-4.
Mengonfigurasi dan membuat rekaman
Dari Recorder
, aplikasi dapat membuat objek perekaman untuk
melakukan perekaman video dan audio. Aplikasi membuat rekaman dengan melakukan
hal-hal berikut:
- Mengonfigurasikan
OutputOptions
denganprepareRecording()
. - (Opsional) Mengaktifkan rekaman audio.
- Menggunakan
start()
untuk mendaftarkan pemrosesVideoRecordEvent
, dan memulai perekaman video.
Recorder
menampilkan objek Recording
saat Anda memanggil fungsi start()
.
Aplikasi Anda dapat menggunakan objek Recording
ini untuk menyelesaikan
perekaman atau melakukan tindakan lainnya, seperti menjeda atau melanjutkan perekaman.
Recorder
mendukung satu objek Recording
dalam satu waktu. Anda dapat memulai
perekaman baru setelah memanggil Recording.stop()
atau
Recording.close()
pada objek Recording
sebelumnya.
Mari kita lihat langkah-langkah ini secara lebih mendetail. Pertama, aplikasi akan mengonfigurasi
OutputOptions
untuk Perekam dengan Recorder.prepareRecording()
.
Recorder
mendukung jenis OutputOptions
berikut:
FileDescriptorOutputOptions
untuk merekam ke dalamFileDescriptor
.FileOutputOptions
untuk merekam ke dalamFile
.MediaStoreOutputOptions
untuk merekam ke dalamMediaStore
.
Semua jenis OutputOptions
memungkinkan Anda untuk menetapkan ukuran file maksimum dengan
setFileSizeLimit()
. Opsi lainnya khusus untuk jenis output
individu, seperti ParcelFileDescriptor
untuk FileDescriptorOutputOptions
.
prepareRecording()
menampilkan objek PendingRecording
yang merupakan
objek perantara yang digunakan untuk membuat
objek Recording
yang sesuai. PendingRecording
adalah class sementara yang seharusnya
tidak terlihat dan jarang di-cache oleh aplikasi.
Aplikasi dapat mengonfigurasi perekaman lebih lanjut, seperti:
- Mengaktifkan audio dengan
withAudioEnabled()
. - Mendaftarkan pemroses untuk menerima peristiwa perekaman video
dengan
start(Executor, Consumer<VideoRecordEvent>)
. - Izinkan rekaman untuk terus direkam saat VideoCapture terlampir
terhubung kembali ke kamera lain, dengan
PendingRecording.asPersistentRecording()
.
Untuk mulai merekam, panggil PendingRecording.start()
. CameraX mengubah
PendingRecording
menjadi Recording
, mengantrekan permintaan perekaman,
dan menampilkan objek Recording
yang baru dibuat ke aplikasi.
Setelah perekaman dimulai pada perangkat Kamera yang sesuai, CameraX akan mengirimkan
peristiwa VideoRecordEvent.EVENT_TYPE_START
.
Contoh berikut menunjukkan cara merekam video dan audio ke
dalam file 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)
Saat pratinjau kamera dicerminkan di kamera depan secara default, video akan yang direkam oleh VideoCapture tidak dicerminkan secara default. Dengan CameraX 1.3, kini memungkinkan untuk mencerminkan rekaman video sehingga pratinjau kamera depan dan kecocokan video yang direkam.
Ada tiga opsi MirrorMode: MIRROR_MODE_OFF, MIRROR_MODE_ON, dan
MIRROR_MODE_ON_FRONT_ONLY. Untuk menyelaraskan dengan
pratinjau kamera, Google merekomendasikan penggunaan MIROR_MODE_ON_FRONT_ONLY, yang berarti
sehingga
pencerminan tidak diaktifkan untuk kamera belakang, tetapi diaktifkan untuk bagian depan
kamera. Untuk mengetahui informasi selengkapnya tentang MirrorMode, lihat
MirrorMode constants
Cuplikan kode ini menunjukkan cara memanggil
VideoCapture.Builder.setMirrorMode()
menggunakan MIRROR_MODE_ON_FRONT_ONLY
. Sebagai
informasi selengkapnya, lihat 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);
Mengontrol perekaman aktif
Anda dapat menjeda, melanjutkan, dan menghentikan Recording
yang sedang berjalan
dengan metode berikut:
pause
untuk menjeda perekaman aktif saat ini.resume()
untuk melanjutkan perekaman aktif yang dijeda.stop()
untuk menyelesaikan perekaman dan menghapus semua objek perekaman terkait.mute()
untuk membisukan atau membunyikan rekaman saat ini.
Perhatikan bahwa Anda dapat memanggil stop()
untuk menghentikan Recording
, terlepas
apakah perekaman dalam status dijeda atau aktif.
Jika Anda telah mendaftarkan EventListener
dengan
PendingRecording.start()
, Recording
akan berkomunikasi
menggunakan
VideoRecordEvent
.
VideoRecordEvent.EVENT_TYPE_STATUS
digunakan untuk merekam statistik seperti ukuran file saat ini dan rentang waktu yang direkam.VideoRecordEvent.EVENT_TYPE_FINALIZE
digunakan untuk hasil perekaman dan mencakup informasi seperti URI file akhir beserta error terkait apa pun.
Setelah aplikasi Anda menerima EVENT_TYPE_FINALIZE
yang menunjukkan bahwa
sesi perekaman berhasil dilakukan, Anda dapat mengakses video yang direkam dari lokasi
yang ditentukan di OutputOptions
.
Referensi lainnya
Untuk mempelajari CameraX lebih lanjut, baca referensi tambahan berikut ini:
- Memulai Codelab CameraX
- Aplikasi contoh CameraX resmi
- Daftar CameraX Video Capture API terbaru
- Catatan rilis CameraX
- Kode sumber CameraX