Arsitektur perekaman video CameraX

Sistem perekaman umumnya merekam streaming video dan audio, mengompresinya, menggabungkan dua streaming secara multipleks, lalu menulis streaming yang dihasilkan ke disk.

diagram konseptual untuk sistem perekaman video dan audio
Gambar 1. Diagram konseptual untuk sistem perekaman video dan audio.

Di CameraX, solusi untuk perekaman video adalah kasus penggunaan VideoCapture :

diagram konseptual yang menunjukkan cara CameraX menangani
         kasus penggunaan perekaman video
Gambar 2. Diagram konseptual yang menunjukkan cara CameraX menangani 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 pada LifecycleOwner dengan CameraSelector dan UseCases CameraX lainnya. Untuk mengetahui informasi konsep dan penggunaan ini lebih lanjut, lihat Arsitektur CameraX.
  • Recorder adalah implementasi VideoOutput yang dikaitkan erat dengan VideoCapture. Recorder digunakan untuk melakukan perekaman video dan audio. Aplikasi membuat rekaman dari Recorder.
  • PendingRecording mengonfigurasi perekaman, yang memberikan opsi seperti mengaktifkan audio dan menyetel pemroses peristiwa. Anda harus menggunakan Recorder untuk membuat PendingRecording. PendingRecording tidak merekam apa pun.
  • Recording akan melakukan perekaman yang sebenarnya. Anda harus menggunakan PendingRecording untuk membuat Recording.

Gambar 3 menunjukkan hubungan antara objek ini:

diagram yang menunjukkan interaksi yang terjadi dalam kasus penggunaan
         perekaman video
Gambar 3. Diagram yang menunjukkan interaksi yang terjadi dalam kasus penggunaan VideoCapture.

Keterangan:

  1. Membuat Recorder dengan QualitySelector.
  2. Mengonfigurasi Recorder dengan salah satu OutputOptions.
  3. Mengaktifkan audio dengan withAudioEnabled() jika diperlukan.
  4. Memanggil start() dengan pemroses VideoRecordEvent untuk mulai merekam.
  5. Menggunakan pause()/resume()/stop() pada Recording untuk mengontrol perekaman.
  6. 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:

  1. Ikat VideoCapture.
  2. Siapkan dan konfigurasikan perekaman.
  3. 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 VideoCapture, lakukan langkah-langkah berikut:

  1. Buat objek Recorder.
  2. Buat objek VideoCapture.
  3. 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.QHD untuk ukuran video quad HD (1440p), diperkenalkan di CameraX 1.7.0-alpha02
  • 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.QHD, 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.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()
        }
    }
    
    

    Perhatikan bahwa kemampuan yang ditampilkan dari QualitySelector.getSupportedQualities() dijamin berfungsi untuk kasus penggunaan VideoCapture ataupun kombinasi kasus penggunaan VideoCapture dan Preview. Saat melakukan binding dengan kasus penggunaan ImageCapture atau ImageAnalysis, 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:

  1. Mengonfigurasikan OutputOptions dengan prepareRecording().
  2. (Opsional) Mengaktifkan rekaman audio.
  3. Menggunakan start() untuk mendaftarkan pemroses VideoRecordEvent, 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 dalam FileDescriptor.
  • FileOutputOptions untuk merekam ke dalam File.
  • MediaStoreOutputOptions untuk merekam ke dalam MediaStore.

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>).
  • Mengizinkan perekaman nonstop saat VideoCapture yang terpasang terikat 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)

Meskipun pratinjau kamera dicerminkan di kamera depan secara default, video yang direkam oleh VideoCapture tidak dicerminkan secara default. Dengan CameraX 1.3, Anda kini dapat mencerminkan rekaman video sehingga pratinjau kamera depan dan video yang direkam cocok.

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 pencerminan tidak diaktifkan untuk kamera belakang, tetapi diaktifkan untuk kamera depan. Untuk mengetahui informasi selengkapnya tentang MirrorMode, lihat MirrorMode constants.

Cuplikan kode ini menunjukkan cara memanggil VideoCapture.Builder.setMirrorMode() menggunakan MIRROR_MODE_ON_FRONT_ONLY. Untuk mengetahui 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);

Rentang dinamis (video HDR)

CameraX mendukung perekaman video rentang dinamis tinggi (HDR) 10-bit, seperti HLG10, HDR10, HDR10+, atau Dolby Vision, menggunakan DynamicRange.

Untuk menggunakan perekaman video HDR, selesaikan langkah-langkah berikut:

  1. Buat kueri rentang dinamis yang didukung kamera menggunakan VideoCapabilities.getSupportedDynamicRanges().
  2. Opsional: Jika Anda mengonfigurasi QualitySelector kustom, periksa kualitas yang didukung untuk rentang dinamis tersebut menggunakan getSupportedQualities(DynamicRange).
  3. Konfigurasikan VideoCapture.Builder dengan setDynamicRange().

Contoh berikut mengaktifkan perekaman HDR 10-bit HLG jika kamera mendukungnya:

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

Stabilisasi video

CameraX mendukung stabilisasi video untuk mengurangi guncangan dan jitter saat merekam video.

Untuk mengaktifkan stabilisasi video, selesaikan langkah-langkah berikut:

  1. Periksa apakah perangkat kamera mendukung stabilisasi menggunakan VideoCapabilities.isStabilizationSupported().
  2. Aktifkan di VideoCapture.Builder menggunakan setVideoStabilizationEnabled(true).

Contoh berikut mengaktifkan stabilisasi jika kamera mendukungnya:

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

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.

Amplitudo dan status audio real-time

Selama perekaman, peristiwa VideoRecordEvent.Status memberikan statistik audio real-time melalui AudioStats:

  • AudioStats.getAudioAmplitude() menampilkan amplitudo puncak audio saat ini, mulai dari 0.0 hingga 1.0. Anda dapat menggunakan nilai ini untuk mendorong meteran UI atau visualizer bentuk gelombang audio.
  • AudioStats.getAudioState() menunjukkan status streaming audio saat ini, seperti AUDIO_STATE_ACTIVE, AUDIO_STATE_MUTED, atau AUDIO_STATE_SOURCE_SILENCED.

Contoh berikut membaca amplitudo audio dari peristiwa status:

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);
    }
}

Video berkecepatan tinggi dan gerakan lambat

CameraX mendukung perekaman video berkecepatan tinggi, seperti 120, 240, atau 480 fps, yang memungkinkan dua kasus penggunaan yang berbeda:

  • Video kecepatan frame tinggi (gerakan lambat yang ditangani pemutar): CameraX mengambil dan menyimpan frame pada kecepatan frame tinggi (misalnya, 120 fps). Pemutar video mengontrol kecepatan pemutaran, sehingga pengguna dapat beralih antara kecepatan normal dan gerak lambat atau melakukan analisis frame demi frame.
  • Video gerakan lambat yang siap diputar: CameraX memproses streaming berkecepatan tinggi dan menghasilkan file video standar 30 fps dengan stempel waktu frame yang disesuaikan. Efek gerak lambat "disematkan", sehingga video diputar dalam gerak lambat secara otomatis di pemutar video standar mana pun tanpa dukungan pemutar video khusus. Misalnya, perekaman 120 fps yang diputar kembali pada 30 fps akan menghasilkan video gerak lambat 1/4x.

Memeriksa kemampuan kecepatan tinggi

Perekaman video berkecepatan tinggi memerlukan dukungan hardware dan definisi CamcorderProfile yang sesuai dari produsen perangkat, seperti CamcorderProfile.QUALITY_HIGH_SPEED_1080P atau QUALITY_HIGH_SPEED_720P.

Sebelum mengonfigurasi perekaman kecepatan tinggi, buat kueri kemampuan kecepatan tinggi menggunakan 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);

Mengonfigurasi HighSpeedVideoSessionConfig

Untuk menggunakan pengambilan gambar kecepatan tinggi, gabungkan kasus penggunaan VideoCapture dan Preview Anda dalam HighSpeedVideoSessionConfig. Untuk mengonfigurasi sesi, selesaikan langkah-langkah berikut:

  1. Buat kasus penggunaan VideoCapture dan kasus penggunaan Preview.
  2. Lakukan inisialisasi HighSpeedVideoSessionConfig.Builder dengan kasus penggunaan VideoCapture dan lampirkan Preview.
  3. Buat kueri rentang kecepatan frame yang didukung menggunakan CameraInfo.getSupportedFrameRateRanges(SessionConfig) dan tetapkan rentang yang dipilih.
  4. Pilih antara video kecepatan frame tinggi atau video gerakan lambat yang siap diputar:
    • Untuk membuat video dengan kecepatan frame tinggi, biarkan setSlowMotionEnabled(false) (default).
    • Untuk membuat video gerak lambat yang siap diputar, panggil setSlowMotionEnabled(true).
  5. Ikat konfigurasi sesi menggunakan cameraProvider.bindToLifecycle().

Contoh berikut mengonfigurasi dan mengikat sesi gerakan lambat yang siap diputar:

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

Anda juga dapat menggunakan DSL Kotlin, yang diperkenalkan di CameraX 1.7.0-alpha02, untuk mengonfigurasi sesi kecepatan tinggi secara ringkas:

val sessionConfig = highSpeedVideoSessionConfig(videoCapture) {
    this.preview = preview
    isSlowMotionEnabled = true
    frameRateRange = supportedFpsRanges.first()
}
cameraProvider.bindToLifecycle(
    lifecycleOwner,
    CameraSelector.DEFAULT_BACK_CAMERA,
    sessionConfig
)

Merekam video berkecepatan tinggi atau gerak lambat

Setelah mengikat HighSpeedVideoSessionConfig, mulai rekam menggunakan VideoCapture dengan cara yang sama seperti perekaman video standar:

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());
            }
        }
    });

Referensi lainnya

Untuk mempelajari CameraX lebih lanjut, baca referensi tambahan berikut ini: