Новости о продуктах

Представляем CameraX 1.5: мощная видеозапись и профессиональная фотосъемка

Время на чтение: 7 минут
Посмотреть профиль пользователя Scott Nien
Scott Nien Разработчик программного обеспечения

Команда CameraX рада сообщить о выпуске версии 1.5. В этом обновлении мы сосредоточились на том, чтобы сделать профессиональные возможности доступными для всех, а настройку камеры – максимально простой.

При записи видео пользователи теперь могут без труда снимать потрясающие замедленные видео или видео с высокой частотой кадров. Новый Feature Group API позволяет уверенно включать сложные комбинации, такие как 10-битный HDR и 60 кадров/с, обеспечивая стабильные результаты на поддерживаемых устройствах.

Что касается фотосъемки, то теперь вы можете сохранять необработанные и несжатые файлы DNG (RAW). Кроме того, теперь вы можете использовать Ultra HDR даже при работе с мощными расширениями камеры.

В основе этих функций лежит новый SessionConfig API, который упрощает настройку и реконфигурацию камеры. Давайте подробнее рассмотрим эти новые функции.

Мощная видеозапись: высокая скорость и комбинации функций

В CameraX 1.5 значительно расширены возможности видео, что позволяет создавать более креативные и надежные записи.

Замедленная съемка и высокая частота кадров

Теперь вы можете замедлять видео. Это одна из самых ожидаемых функций. Теперь вы можете снимать видео с высокой частотой кадров (например, 120 или 240 кадров/с) и сразу же кодировать его в замедленное видео. Вы также можете записывать видео с высокой частотой кадров, чтобы оно было исключительно плавным.

Если вы знакомы с API VideoCapture, то легко сможете реализовать эту функцию.

1. Проверка поддержки высокоскоростной записи. Используйте новый метод Recorder.getHighSpeedVideoCapabilities() , чтобы узнать, поддерживает ли устройство эту функцию.

val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)

val highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)

if (highSpeedCapabilities == null) {
    // This camera device does not support high-speed video.
    return
}

2. Настройте и привяжите вариант использования. Используйте возвращенный объект videoCapabilities, который содержит информацию о поддерживаемом качестве видео, чтобы создать HighSpeedVideoSessionConfig. Затем запросите поддерживаемые диапазоны частоты кадров с помощью cameraInfo.getSupportedFrameRateRanges() и установите нужный диапазон. Вызовите setSlowMotionEnabled(true), чтобы записывать замедленные видео. В противном случае будут записываться видео с высокой частотой кадров. Наконец, нажмите Recorder.prepareRecording().start(), чтобы начать запись видео.

val preview = Preview.Builder().build()
val quality = highSpeedCapabilities
        .getSupportedQualities(DynamicRange.SDR).first()

val recorder = Recorder.Builder()
      .setQualitySelector(QualitySelector.from(quality)))
      .build()

val videoCapture = VideoCapture.withOutput(recorder)

val frameRateRange = cameraInfo.getSupportedFrameRateRanges(      
       HighSpeedVideoSessionConfig(videoCapture, preview)
).first()

val sessionConfig = HighSpeedVideoSessionConfig(
    videoCapture, 
    preview, 
    frameRateRange = frameRateRange, 
    // Set true for slow-motion playback, or false for high-frame-rate
    isSlowMotionEnabled = true
)

cameraProvider.bindToLifecycle(
     lifecycleOwner, cameraSelector, sessionConfig)

// Start recording slow motion videos. 
val recording = recorder.prepareRecording(context, outputOption)
      .start(executor, {})

Совместимость и ограничения

Для высокоскоростной записи требуется поддержка CameraConstrainedHighSpeedCaptureSession и CamcorderProfile. Всегда проверяйте возможности устройства и включайте высокоскоростную запись только на поддерживаемых устройствах, чтобы не ухудшать пользовательский опыт. Сейчас эта функция поддерживается на основных камерах почти всех устройств Pixel и некоторых моделей других производителей.

Подробную информацию вы найдете в этой записи в блоге.

Объединяйте функции с уверенностью: Feature Group API

В CameraX 1.5 появился Feature Group API, который позволяет не гадать, совместимы ли функции. Благодаря API для запроса комбинаций функций в Android 15 вы можете уверенно включать несколько функций одновременно, не беспокоясь о стабильности работы камеры. В настоящее время Feature Group поддерживает HDR (HLG), 60 кадров/с, стабилизацию предварительного просмотра и Ultra HDR. Например, на устройствах Pixel 10 и Galaxy S25 можно одновременно включить HDR, 60 кадров/с и стабилизацию предпросмотра. В будущем планируется добавить запись в формате 4K и ультраширокоугольный зум. 

Feature Group API позволяет решать две основные задачи:

Пример 1. Приоритет отдается наилучшему качеству

Если вы хотите использовать наилучшее сочетание функций, укажите их в порядке приоритета. CameraX попытается включить их по порядку, выбрав первую комбинацию, которую устройство полностью поддерживает.

val sessionConfig = SessionConfig(
    useCases = listOf(preview, videoCapture),
    preferredFeatureGroup = listOf(
        GroupableFeature.HDR_HLG10,
        GroupableFeature.FPS_60,
        GroupableFeature.PREVIEW_STABILIZATION
    )
).apply {
    // (Optional) Get a callback with the enabled features to update your UI.
    setFeatureSelectionListener { selectedFeatures ->
        updateUiIndicators(selectedFeatures)
    }
}
processCameraProvider.bindToLifecycle(activity, cameraSelector, sessionConfig)

В этом примере CameraX пытается включить функции в следующем порядке:

  1. HDR + 60 кадров/с + стабилизация предпросмотра
  2. HDR + 60 кадров/с
  3. HDR + стабилизация предпросмотра
  4. HDR
  5. 60 кадр/с и стабилизация при предпросмотре
  6. 60 кадров/с
  7. Стабилизация при предпросмотре
  8. Нет

Пример 2. Создание пользовательского интерфейса настроек

Теперь вы можете точно указать, какие комбинации функций поддерживаются в настройках приложения, отключив переключатели для неподдерживаемых параметров, как показано на изображении ниже. 

unsupported-features-disabled.gif

Чтобы определить, нужно ли сделать переключатель серым, используйте следующие коды для проверки поддержки комбинации функций. Сначала запросите статус каждой отдельной функции. После включения функции повторно запросите оставшиеся функции с включенными функциями, чтобы увидеть, должны ли их переключатели теперь быть серыми из-за ограничений совместимости.

fun disableFeatureIfNotSuported(
   enabledFeatures: Set<GroupableFeature>,     
   featureToCheck:GroupableFeature
) {
 val sessionConfig = SessionConfig(
     useCases = useCases,
     requiredFeatureGroup = enabledFeatures + featureToCheck
 )
 val isSupported = cameraInfo.isFeatureGroupSupported(sessionConfig)

 if (!isSupported) {
     // disable the toggle for featureToCheck
 }
}

Подробную информацию можно найти в записи блога о группах функций .

Другие улучшения видео

  • Улучшения параллельной работы камер. В CameraX 1.5.1 теперь можно одновременно привязывать варианты использования Preview, ImageCapture и VideoCapture для каждого объекта SingleCameraConfig в режиме без композиции. Кроме того, в режиме композиции (те же варианты использования с CompositionSettings) теперь можно задать CameraEffect, который будет применяться к итоговому результату композиции.
  • Динамическое отключение звука. Теперь вы можете начать запись с отключенным звуком, используя PendingRecording.withAudioEnabled(boolean initialMuted), и разрешить пользователю включить звук позже, используя Recording.mute(boolean muted).
  • Улучшенная обработка нехватки места в хранилище. Теперь CameraX надежно отправляет ошибку VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE, позволяя приложению корректно обрабатывать ситуации с нехваткой места в хранилище и информировать пользователя.
  • Улучшение при слабом освещении. На поддерживаемых устройствах, например Pixel 10, можно включить CameraControl.enableLowLightBoostAsync, чтобы автоматически повышать яркость предварительного просмотра и видеопотоков в темноте.

Профессиональная фотосъемка

В CameraX 1.5 значительно улучшен класс ImageCapture, что позволяет разработчикам добиться максимального качества и гибкости.

Снимайте в формате DNG (RAW) и управляйте творческим процессом

Для полного контроля над постобработкой CameraX теперь поддерживает захват DNG (RAW). Это позволяет получить доступ к необработанным и несжатым данным изображения непосредственно с датчика камеры, что дает возможность профессионального редактирования и цветокоррекции. API поддерживает съемку только в формате DNG или одновременную съемку в форматах JPEG и DNG. Ниже приведен образец кода, который позволяет одновременно сохранять файлы JPEG и DNG.

val capabilities = ImageCapture.getImageCaptureCapabilities(cameraInfo)
val imageCapture = ImageCapture.Builder().apply {
    if (capabilities.supportedOutputFormats
             .contains(OUTPUT_FORMAT_RAW_JPEG)) {
        // Capture both RAW and JPEG formats.
        setOutputFormat(OUTPUT_FORMAT_RAW_JPEG)
    }
}.build()
// ... bind imageCapture to lifecycle ...


// Provide separate output options for each format.
val outputOptionRaw = /* ... configure for image/x-adobe-dng ... */
val outputOptionJpeg = /* ... configure for image/jpeg ... */
imageCapture.takePicture(
    outputOptionRaw,
    outputOptionJpeg,
    executor,
    object : ImageCapture.OnImageSavedCallback {
        override fun onImageSaved(results: OutputFileResults) {
            // This callback is invoked twice: once for the RAW file
            // and once for the JPEG file.
        }

        override fun onError(exception: ImageCaptureException) {}
    }
)

Ultra HDR для расширений камеры

Получите лучшее из двух миров: потрясающую вычислительную фотографию Camera Extensions (например, ночной режим) в сочетании с великолепными цветами и динамическим диапазоном Ultra HDR. Эта функция поддерживается на многих современных телефонах Android премиум-класса, таких как Pixel 9/10 и Samsung S24/S25.

// Support UltraHDR when Extension is enabled. 

val extensionsEnabledCameraSelector = extensionsManager
     .getExtensionEnabledCameraSelector(
        CameraSelector.DEFAULT_BACK_CAMERA, ExtensionMode.NIGHT)

val imageCapabilities = ImageCapture.getImageCaptureCapabilities(
               cameraProvider.getCameraInfo(extensionsEnabledCameraSelector)

val imageCapture = ImageCapture.Builder()
     .apply {
       if (imageCapabilities.supportedOutputFormats
                .contains(OUTPUT_FORMAT_JPEG_ULTRA_HDR) {
           setOutputFormat(OUTPUT_FORMAT_JPEG_ULTRA_HDR)

       }

     }.build()

Улучшения основного API и удобства использования

Новый способ настройки: SessionConfig

Как показано в примерах выше, SessionConfig – это новая концепция в CameraX 1.5. Он централизует конфигурацию и упрощает API двумя основными способами:

  1. Больше не нужно вручную вызывать unbind(). API CameraX учитывают жизненный цикл. Он неявно отменит привязку вариантов использования, когда действие или другой объект LifecycleOwner будет уничтожен. Однако для обновления вариантов использования или переключения камер по-прежнему требуется вызвать unbind() или unbindAll() перед повторной привязкой. Теперь, когда вы привязываете новый SessionConfig, CameraX автоматически обновляет сеанс, и вызовы отвязки больше не нужны.
  2. Детерминированное управление частотой кадров. Новый API SessionConfig позволяет управлять частотой кадров детерминированным способом. В отличие от предыдущего метода setTargetFrameRate, который был лишь подсказкой, новый метод гарантирует, что после успешной настройки будет применяться указанный диапазон частоты кадров. Чтобы обеспечить точность, необходимо запросить поддерживаемые частоты кадров с помощью CameraInfo.getSupportedFrameRateRanges(SessionConfig). Передавая полный SessionConfig, CameraX может точно определить поддерживаемые диапазоны на основе конфигураций потока.

Стабильная версия Camera-Compose

Мы знаем, что вам нравится Jetpack Compose, и рады сообщить, что библиотека camera-compose теперь стабильна в версии 1.5.1! В этом выпуске исправлены критические ошибки, связанные с использованием CameraXViewfinder с такими функциями Compose, как moveableContentOf и Pager, а также решена проблема с растягиванием предварительного просмотра. Мы продолжим добавлять новые функции в camera-compose в будущих выпусках.

Улучшения ImageAnalysis и CameraControl

  • Регулировка яркости фонарика. Новые API позволяют точнее настраивать яркость фонарика на устройстве. Вы можете запросить максимальную поддерживаемую яркость с помощью CameraInfo.getMaxTorchStrengthLevel(), а затем установить желаемый уровень с помощью CameraControl.setTorchStrengthLevel().
  • Поддержка NV21 в ImageAnalysis. Теперь вы можете запрашивать графический формат NV21 непосредственно из ImageAnalysis, что упрощает интеграцию с другими библиотеками и API. Для этого используется метод ImageAnalysis.Builder.setOutputImageFormat(OUTPUT_IMAGE_FORMAT_NV21).

Начните уже сегодня

Обновите зависимости до CameraX 1.5 и попробуйте новые функции. Нам не терпится увидеть, что вы создадите.

Чтобы использовать CameraX 1.5,  добавьте в файл libs.versions.toml следующие зависимости: Рекомендуем использовать версию 1.5.1, в которой исправлено множество критических ошибок и улучшена работа с несколькими камерами.

[versions]

camerax = "1.5.1"


[libraries]

..

androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "camerax" }

androidx-camera-compose = { module = "androidx.camera:camera-compose", version.ref = "camerax" }

androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "camerax" }

androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "camerax" }

androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camerax" }

androidx-camera-extensions = { module = "androidx.camera:camera-extensions", version.ref = "camerax" }

Затем добавьте в зависимости build.gradle.kts модуля следующее:

dependencies {

  ..

  implementation(libs.androidx.camera.core)
  implementation(libs.androidx.camera.lifecycle)

  implementation(libs.androidx.camera.camera2)

  implementation(libs.androidx.camera.view) // for PreviewView 
  implementation(libs.androidx.camera.compose) // for compose UI

  implementation(libs.androidx.camera.extensions) // For Extensions 

}

У вас есть вопросы или вы хотите связаться с командой CameraX? Присоединитесь к группе обсуждения для разработчиков CameraX или отправьте отчет об ошибке:

Продолжить чтение