Cấu trúc quay video của CameraX

Một hệ thống quay video thường ghi lại các luồng video và âm thanh, nén các luồng đó, kết hợp 2 luồng rồi ghi luồng kết quả vào ổ đĩa.

sơ đồ khái niệm cho một hệ thống quay video và ghi âm thanh
Hình 1. Sơ đồ khái niệm cho một hệ thống quay video và ghi âm thanh.

Trong CameraX, giải pháp quay video là trường hợp sử dụng VideoCapture:

sơ đồ khái niệm cho thấy cách CameraX xử lý trường hợp sử dụng quay video
Hình 2. Sơ đồ khái niệm cho thấy cách CameraX xử lý trường hợp sử dụng VideoCapture.

Như minh hoạ trong hình 2, chức năng quay video của CameraX có bao gồm một số thành phần cấu trúc cấp cao:

  • SurfaceProvider cho nguồn video.
  • AudioSource cho nguồn âm thanh.
  • 2 bộ mã hoá để mã hoá và nén video/âm thanh.
  • Một trình kết hợp nội dung đa phương tiện để kết hợp 2 luồng.
  • Một trình lưu tệp để ghi kết quả.

API VideoCapture trừu tượng hoá công cụ quay video phức tạp và mang lại cho các ứng dụng một API đơn giản và dễ hiểu hơn nhiều.

Tổng quan về API VideoCapture

VideoCapture là một trường hợp sử dụng của CameraX, hoạt động độc lập hoặc được kết hợp với các trường hợp sử dụng khác. Những cách kết hợp cụ thể được hỗ trợ phụ thuộc vào chức năng phần cứng của máy ảnh. Tuy nhiên, Preview và VideoCapture là cách kết hợp trường hợp sử dụng hợp lệ trên mọi thiết bị.

API VideoCapture bao gồm những đối tượng sau để kết nối với các ứng dụng:

  • VideoCapture là lớp trường hợp sử dụng cấp cao nhất. VideoCapture liên kết với LifecycleOwner bằng CameraSelector và các UseCase khác của CameraX. Để biết thêm thông tin về những khái niệm và cách sử dụng này, hãy xem bài viết Cấu trúc CameraX.
  • Recorder là một cách triển khai VideoOutput được kết hợp chặt chẽ với VideoCapture. Recorder được dùng để thực hiện quá trình quay video và ghi âm thanh. Một ứng dụng tạo bản ghi từ Recorder.
  • PendingRecording sẽ định cấu hình bản ghi, cung cấp các tuỳ chọn như bật âm thanh và đặt trình nghe sự kiện. Bạn phải dùng Recorder để tạo PendingRecording. PendingRecording không ghi lại nội dung nào.
  • Recording thực hiện quá trình ghi thực tế. Bạn phải dùng PendingRecording để tạo Recording.

Hình 3 cho thấy mối quan hệ giữa các đối tượng này:

sơ đồ cho thấy các hoạt động tương tác diễn ra trong trường hợp sử dụng quay video
Hình 3. Sơ đồ cho thấy các hoạt động tương tác diễn ra trong trường hợp sử dụng VideoCapture.

Chú giải:

  1. Tạo Recorder bằng QualitySelector.
  2. Định cấu hình Recorder bằng một trong các OutputOptions.
  3. Bật âm thanh bằng withAudioEnabled() nếu cần.
  4. Gọi start() bằng trình nghe VideoRecordEvent để bắt đầu quay video.
  5. Sử dụng pause()/resume()/stop() trên Recording để điều khiển quá trình quay video.
  6. Phản hồi VideoRecordEvents bên trong trình nghe sự kiện.

Danh sách API chi tiết nằm ở current.txt bên trong mã nguồn.

Sử dụng API VideoCapture

Để tích hợp trường hợp sử dụng VideoCapture của CameraX vào ứng dụng của bạn, hãy làm như sau:

  1. Liên kết VideoCapture.
  2. Chuẩn bị và định cấu hình quá trình quay video.
  3. Bắt đầu và điều khiển quá trình quay video trong thời gian chạy.

Các phần sau đây trình bày những việc bạn có thể làm ở mỗi bước để thực hiện phiên quay video hai đầu.

Liên kết VideoCapture

Để liên kết trường hợp sử dụng VideoCapture, hãy làm như sau:

  1. Tạo đối tượng Recorder.
  2. Tạo đối tượng VideoCapture.
  3. Liên kết với Lifecycle.

API VideoCapture của CameraX tuân theo mẫu thiết kế của trình tạo. Các ứng dụng dùng Recorder.Builder để tạo Recorder. Bạn cũng có thể định cấu hình độ phân giải video cho Recorder thông qua đối tượng QualitySelector.

Recorder của CameraX hỗ trợ các Qualities định sẵn sau đây cho độ phân giải video:

  • Quality.UHD cho kích thước video độ nét siêu cao 4K (2160p)
  • Quality.QHD cho kích thước video Quad HD (1440p), được giới thiệu trong CameraX 1.7.0-alpha02
  • Quality.FHD cho kích thước video HD đầy đủ (1080p)
  • Quality.HD cho kích thước video HD (720p)
  • Quality.SD cho kích thước video SD (480p)

Lưu ý rằng CameraX cũng có thể chọn những độ phân giải khác khi được ứng dụng cho phép.

Kích thước video chính xác của từng lựa chọn phụ thuộc vào chức năng của máy ảnh và bộ mã hoá. Để biết thêm thông tin, hãy xem tài liệu về CamcorderProfile.

Các ứng dụng có thể định cấu hình độ phân giải bằng cách tạo một QualitySelector. Bạn có thể tạo QualitySelector bằng một trong các phương thức sau đây:

  • Hãy cung cấp một vài độ phân giải ưu tiên bằng cách sử dụng fromOrderedList(), đồng thời thêm chiến lược dự phòng để dùng trong trường hợp không có độ phân giải ưu tiên nào được hỗ trợ.

    CameraX có thể quyết định độ phân giải dự phòng phù hợp nhất dựa trên chức năng của máy ảnh đã chọn, hãy tham khảo FallbackStrategy specification của QualitySelector để biết thêm thông tin chi tiết. Ví dụ: mã sau đây yêu cầu độ phân giải cao nhất được hỗ trợ để quay video. Nếu không có độ phân giải yêu cầu nào được hỗ trợ, hãy cho phép CameraX chọn độ phân giải gần nhất với độ phân giải Quality.SD:

    val qualitySelector = QualitySelector.fromOrderedList(
             listOf(Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD),
             FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))
    
  • Trước tiên, hãy truy vấn chức năng của máy ảnh rồi chọn trong số những độ phân giải được hỗ trợ bằng cách sử dụng 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()
        }
    }
    
    

    Lưu ý rằng chức năng trả về từ QualitySelector.getSupportedQualities() được đảm bảo sẽ hoạt động cho trường hợp sử dụng VideoCapture hoặc sự kết hợp giữa trường hợp sử dụng VideoCapture và Preview. Khi liên kết với nhau bằng trường hợp sử dụng ImageCapture hoặc ImageAnalysis, CameraX có thể vẫn không liên kết được khi cách kết hợp yêu cầu không được hỗ trợ trên máy ảnh yêu cầu.

Sau khi bạn có QualitySelector, ứng dụng có thể tạo một đối tượng VideoCapture và thực hiện quá trình liên kết đó. Xin lưu ý rằng việc liên kết này giống với các trường hợp sử dụng khác:

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

Lưu ý rằng bindToLifecycle() sẽ trả về một đối tượng Camera. Hãy xem hướng dẫn này để biết thêm thông tin về cách kiểm soát đầu ra của máy ảnh, chẳng hạn như thu phóng và độ phơi sáng.

Recorder sẽ chọn định dạng phù hợp nhất với hệ thống. Bộ mã hóa và giải mã video phổ biến nhất là H.264 AVC) có định dạng vùng chứa MPEG-4.

Định cấu hình và tạo bản ghi

Từ Recorder, ứng dụng có thể tạo các đối tượng quay video để thực hiện quá trình quay video và ghi âm thanh. Các ứng dụng tạo bản ghi bằng cách làm như sau:

  1. Định cấu hình OutputOptions bằng prepareRecording().
  2. (Không bắt buộc) Bật tính năng ghi âm.
  3. Sử dụng start() để đăng ký trình nghe VideoRecordEvent và bắt đầu quay video.

Recorder sẽ trả về đối tượng Recording khi bạn gọi hàm start(). Ứng dụng của bạn có thể dùng đối tượng Recording này để hoàn tất quá trình quay video hoặc thực hiện các thao tác khác, chẳng hạn như tạm dừng hoặc tiếp tục.

Mỗi lần, Recorder hỗ trợ một đối tượng Recording. Bạn có thể bắt đầu quá trình quay video mới sau khi gọi Recording.stop() hoặc Recording.close() trên đối tượng Recording trước đó.

Hãy cùng tìm hiểu chi tiết các bước này. Trước tiên, ứng dụng sẽ định cấu hình OutputOptions cho Trình ghi bằng Recorder.prepareRecording(). Recorder hỗ trợ các loại OutputOptions sau:

  • FileDescriptorOutputOptions để ghi vào FileDescriptor.
  • FileOutputOptions để ghi vào File.
  • MediaStoreOutputOptions để ghi vào MediaStore.

Mọi loại OutputOptions đều cho phép bạn đặt kích thước tệp tối đa bằng setFileSizeLimit(). Các tuỳ chọn khác dành riêng cho từng loại đầu ra, chẳng hạn như ParcelFileDescriptor cho FileDescriptorOutputOptions.

prepareRecording() sẽ trả về một đối tượng PendingRecording. Đây là đối tượng trung gian dùng để tạo đối tượng Recording tương ứng. PendingRecording là một lớp tạm thời. Lớp này sẽ không hiển thị trong hầu hết các trường hợp và hiếm khi được ứng dụng lưu vào bộ nhớ đệm.

Các ứng dụng có thể định cấu hình thêm bản ghi, chẳng hạn như:

  • Bật âm thanh bằng withAudioEnabled().
  • Đăng ký một trình nghe để nhận các sự kiện quay video bằng start(Executor, Consumer<VideoRecordEvent>).
  • Dùng PendingRecording.asPersistentRecording() để cho phép một bản ghi quay liên tục trong khi VideoCapture đính kèm bản ghi đó được chuyển lại một camera khác.

Để bắt đầu quay video, hãy gọi PendingRecording.start(). CameraX sẽ chuyển PendingRecording thành Recording, đưa yêu cầu quay video vào hàng đợi và trả về đối tượng Recording mới tạo cho ứng dụng. Sau khi quá trình quay video bắt đầu trên thiết bị Máy ảnh tương ứng, CameraX sẽ gửi một sự kiện VideoRecordEvent.EVENT_TYPE_START.

Ví dụ sau đây cho biết cách quay video và ghi âm thanh vào tệp 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)

Mặc dù bản xem trước của camera được phản chiếu trên camera trước theo mặc định nhưng video quay bằng VideoCapture lại không như vậy. Với CameraX 1.3, giờ đây, bạn có thể phản chiếu các bản ghi video để bản xem trước của camera trước và video đã quay trùng khớp nhau.

Có 3 lựa chọn MirrorMode: MIRROR_MODE_OFF, MIRROR_MODE_ON và MIRROR_MODE_ON_FRONT_ONLY. Để phù hợp với bản xem trước của camera, Google đề xuất sử dụng MIROR_MODE_ON_FRONT_ONLY, tức là tính năng phản chiếu không được bật cho camera sau nhưng lại được bật cho camera trước. Để biết thêm thông tin về MirrorMode, hãy xem MirrorMode constants.

Đoạn mã này cho biết cách gọi VideoCapture.Builder.setMirrorMode() bằng MIRROR_MODE_ON_FRONT_ONLY. Để biết thêm thông tin, hãy xem 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);

Dải động (video HDR)

CameraX hỗ trợ quay video dải động cao (HDR) 10 bit, chẳng hạn như HLG10, HDR10, HDR10+ hoặc Dolby Vision, bằng cách sử dụng DynamicRange.

Để sử dụng tính năng quay video HDR, hãy hoàn tất các bước sau:

  1. Truy vấn dải động được hỗ trợ của máy ảnh bằng cách sử dụng VideoCapabilities.getSupportedDynamicRanges().
  2. Không bắt buộc: Nếu bạn định cấu hình QualitySelector tuỳ chỉnh, hãy kiểm tra xem những chất lượng nào được hỗ trợ cho dải động đó bằng cách sử dụng getSupportedQualities(DynamicRange).
  3. Định cấu hình VideoCapture.Builder bằng setDynamicRange().

Ví dụ sau đây bật tính năng quay video HDR 10 bit HLG khi máy ảnh hỗ trợ:

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

Chống rung video

CameraX hỗ trợ tính năng ổn định video để giảm hiện tượng rung lắc và giật khi quay video bằng tay.

Để bật tính năng ổn định video, hãy hoàn tất các bước sau:

  1. Kiểm tra xem thiết bị camera có hỗ trợ tính năng ổn định bằng VideoCapabilities.isStabilizationSupported() hay không.
  2. Bật tính năng này trên VideoCapture.Builder bằng cách sử dụng setVideoStabilizationEnabled(true).

Ví dụ sau đây bật tính năng ổn định khi máy ảnh hỗ trợ tính năng này:

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

Điều khiển quá trình quay video đang hoạt động

Bạn có thể tạm dừng, tiếp tục và dừng Recording đang diễn ra thông qua các phương thức sau:

  • pause để tạm dừng quá trình quay video đang hoạt động.
  • resume() để tiếp tục quá trình quay video đã tạm dừng.
  • stop() để hoàn tất quá trình quay video và xoá mọi đối tượng quay video liên quan.
  • mute() để tắt hoặc bật tiếng bản ghi video hiện tại.

Xin lưu ý rằng bạn có thể gọi stop() để chấm dứt Recording, bất kể quá trình quay video ở trạng thái đã tạm dừng hay đang hoạt động.

Nếu bạn đã đăng ký EventListener bằng PendingRecording.start(), thì Recording sẽ giao tiếp thông qua VideoRecordEvent.

  • VideoRecordEvent.EVENT_TYPE_STATUS được dùng cho số liệu thống kê quay video, chẳng hạn như kích thước tệp hiện tại và khoảng thời gian được quay.
  • VideoRecordEvent.EVENT_TYPE_FINALIZE được dùng cho kết quả quay video và bao gồm thông tin như URI của tệp cuối cùng kèm theo mọi lỗi liên quan.

Sau khi ứng dụng của bạn nhận được EVENT_TYPE_FINALIZE cho biết phiên quay video thành công, bạn có thể truy cập vào video đã quay từ vị trí được chỉ định trong OutputOptions.

Biên độ và trạng thái âm thanh theo thời gian thực

Trong khi ghi, các sự kiện VideoRecordEvent.Status cung cấp số liệu thống kê âm thanh theo thời gian thực thông qua AudioStats:

  • AudioStats.getAudioAmplitude() trả về biên độ đỉnh âm thanh hiện tại, từ 0.0 đến 1.0. Bạn có thể sử dụng giá trị này để điều khiển đồng hồ đo giao diện người dùng hoặc trình hiển thị dạng sóng âm thanh.
  • AudioStats.getAudioState() cho biết trạng thái hiện tại của luồng âm thanh, chẳng hạn như AUDIO_STATE_ACTIVE, AUDIO_STATE_MUTED hoặc AUDIO_STATE_SOURCE_SILENCED.

Ví dụ sau đây đọc biên độ âm thanh từ một sự kiện trạng thái:

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 tốc độ cao và chuyển động chậm

CameraX hỗ trợ quay video tốc độ cao, chẳng hạn như 120, 240 hoặc 480 khung hình/giây, cho phép hai trường hợp sử dụng riêng biệt:

  • Video có tốc độ khung hình cao (chuyển động chậm do trình phát xử lý): CameraX chụp và lưu khung hình ở tốc độ khung hình cao (ví dụ: 120 khung hình/giây). Trình phát video kiểm soát tốc độ phát, cho phép người dùng chuyển đổi giữa tốc độ bình thường và chuyển động chậm hoặc thực hiện phân tích từng khung hình.
  • Video chuyển động chậm sẵn sàng phát: CameraX xử lý luồng tốc độ cao và xuất ra tệp video 30 khung hình/giây tiêu chuẩn có dấu thời gian khung hình đã điều chỉnh. Hiệu ứng chuyển động chậm được "tích hợp sẵn", vì vậy, video sẽ tự động phát ở chế độ chuyển động chậm trong bất kỳ trình phát tiêu chuẩn nào mà không cần trình phát video hỗ trợ đặc biệt. Ví dụ: video quay ở tốc độ 120 khung hình/giây được phát lại ở tốc độ 30 khung hình/giây sẽ tạo ra video chuyển động chậm 1/4 lần.

Kiểm tra các chức năng tốc độ cao

Tính năng quay video tốc độ cao yêu cầu nhà sản xuất thiết bị hỗ trợ phần cứng và cung cấp các định nghĩa CamcorderProfile tương ứng, chẳng hạn như CamcorderProfile.QUALITY_HIGH_SPEED_1080P hoặc QUALITY_HIGH_SPEED_720P.

Trước khi định cấu hình tính năng quay video tốc độ cao, hãy truy vấn các chức năng tốc độ cao bằng cách sử dụng 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);

Định cấu hình HighSpeedVideoSessionConfig

Để sử dụng tính năng chụp tốc độ cao, hãy kết hợp các trường hợp sử dụng VideoCapture và Preview trong HighSpeedVideoSessionConfig. Để định cấu hình phiên, hãy hoàn tất các bước sau:

  1. Tạo một trường hợp sử dụng VideoCapture và một trường hợp sử dụng Preview.
  2. Khởi động HighSpeedVideoSessionConfig.Builder bằng trường hợp sử dụng VideoCapture và đính kèm Preview.
  3. Truy vấn các dải tốc độ khung hình được hỗ trợ bằng cách sử dụng CameraInfo.getSupportedFrameRateRanges(SessionConfig) và đặt dải đã chọn.
  4. Chọn giữa video có tốc độ khung hình cao hoặc video chuyển động chậm có thể phát ngay:
    • Để tạo video có tốc độ khung hình cao, hãy giữ nguyên setSlowMotionEnabled(false) (mặc định).
    • Để tạo một video chuyển động chậm sẵn sàng phát, hãy gọi setSlowMotionEnabled(true).
  5. Liên kết cấu hình phiên bằng cameraProvider.bindToLifecycle().

Ví dụ sau đây định cấu hình và liên kết một phiên chuyển động chậm sẵn sàng phát:

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

Bạn cũng có thể sử dụng Kotlin DSL (được giới thiệu trong CameraX 1.7.0-alpha02) để định cấu hình các phiên tốc độ cao một cách ngắn gọn:

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

Quay video tốc độ cao hoặc chuyển động chậm

Sau khi liên kết HighSpeedVideoSessionConfig, hãy bắt đầu quay bằng VideoCapture theo cách tương tự như quay video chuẩn:

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

Tài nguyên khác

Để tìm hiểu thêm về CameraX, hãy xem các tài nguyên bổ sung sau đây: