Novedades de productos

Presentamos CameraX 1.5: grabación de vídeo potente y captura de imágenes de nivel profesional

Lectura de 7 minutos
Scott Nien
Ingeniero de software

El equipo de CameraX se complace en anunciar el lanzamiento de la versión 1.5. Esta última actualización se centra en poner a tu alcance funciones de nivel profesional y, al mismo tiempo, hacer que la sesión de la cámara sea más fácil de configurar que nunca.

En cuanto a la grabación de vídeo, los usuarios ahora pueden grabar vídeos a cámara lenta o con una alta frecuencia de fotogramas sin esfuerzo. Lo que es más importante, la nueva API Feature Group te permite habilitar con confianza combinaciones complejas, como HDR de 10 bits y 60 FPS, lo que garantiza resultados coherentes en los dispositivos compatibles.

En cuanto a la captura de imágenes, tendrás la máxima flexibilidad gracias a la compatibilidad con la captura de archivos DNG (RAW) sin procesar ni comprimir. Además, ahora puedes aprovechar la salida Ultra HDR incluso cuando usas potentes extensiones de cámara.

Estas funciones se basan en la nueva API SessionConfig, que simplifica la configuración y la reconfiguración de la cámara. Ahora, vamos a ver los detalles de estas nuevas funciones.

Grabación de vídeo potente: combinaciones de alta velocidad y funciones

CameraX 1.5 amplía significativamente sus funciones de vídeo, lo que permite disfrutar de experiencias de grabación más creativas y sólidas.

Vídeo a cámara lenta y con alta frecuencia de imagen

Una de las funciones más esperadas, el vídeo a cámara lenta, ya está disponible. Ahora puedes grabar vídeos a alta velocidad (por ejemplo, a 120 o 240 fps) y codificarlos directamente en un vídeo a cámara lenta espectacular. También puedes grabar con la misma velocidad de fotogramas alta para producir vídeos excepcionalmente fluidos.

Implementar esta función es sencillo si conoces la API VideoCapture.

1. Comprobar si se admite la alta velocidad: usa el nuevo método Recorder.getHighSpeedVideoCapabilities() para consultar si el dispositivo admite esta función.

  val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)

val highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)

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

2. Configura y vincula el caso práctico: usa el videoCapabilities devuelto (que contiene información sobre la calidad de vídeo admitida) para crear un HighSpeedVideoSessionConfig. A continuación, debes consultar los intervalos de velocidad de fotogramas admitidos mediante cameraInfo.getSupportedFrameRateRanges() y definir el intervalo que quieras. Invoca setSlowMotionEnabled(true) para grabar vídeos a cámara lenta. De lo contrario, se grabarán vídeos con una alta frecuencia de fotogramas. El último paso es usar el botón Recorder.prepareRecording().start() para empezar a grabar el vídeo.

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

Compatibilidad y limitaciones

Para grabar a alta velocidad, se necesita compatibilidad con CameraConstrainedHighSpeedCaptureSession y CamcorderProfile. Realiza siempre la comprobación de la capacidad y habilita la grabación a alta velocidad solo en los dispositivos compatibles para evitar la mala experiencia de usuario. Actualmente, esta función es compatible con las cámaras traseras de casi todos los dispositivos Pixel y de algunos modelos de otros fabricantes.

Consulta la entrada de blog para obtener más información.

Combina funciones con confianza: la API Feature Group

CameraX 1.5 incluye la API Feature Group, que elimina las conjeturas sobre la compatibilidad de las funciones. Gracias a la consulta de combinación de funciones de Android 15 API, ahora puedes habilitar varias funciones a la vez con total confianza, lo que garantiza una sesión de cámara estable. Actualmente, el grupo de funciones admite HDR (HLG), 60 fps, Estabilización de vista previa y Ultra HDR. Por ejemplo, puedes habilitar HDR, 60 fps y Estabilización de vista previa simultáneamente en las series Pixel 10 y Galaxy S25. Tenemos previsto incluir mejoras en el futuro, como la grabación en 4K y el zoom ultra gran angular. 

La API Feature Group permite dos casos prácticos esenciales:

Caso práctico 1: priorizar la mejor calidad

Si quieres hacer capturas con la mejor combinación posible de funciones, puedes proporcionar una lista priorizada. CameraX intentará habilitarlos en orden y seleccionará la primera combinación que el dispositivo admita por completo.

  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)

En este ejemplo, CameraX intenta habilitar las funciones en este orden:

  1. HDR + 60 FPS + Estabilización de vista previa
  2. HDR + 60 FPS
  3. Estabilización de vista previa con HDR+
  4. HDR
  5. 60 FPS + Estabilización de vista previa
  6. 60 FPS
  7. Vista previa de la estabilización
  8. Ninguno

Caso práctico 2: crear una interfaz de usuario de ajustes para los usuarios

Ahora puedes reflejar con precisión qué combinaciones de funciones se admiten en la interfaz de usuario de los ajustes de tu aplicación. Para ello, inhabilita los interruptores de las opciones no admitidas, como se muestra en la imagen de abajo. 

unsupported-features-disabled.gif

Para determinar si se debe inhabilitar un interruptor, usa los siguientes códigos para comprobar si se admite la combinación de funciones. Al principio, consulta el estado de cada función. Una vez que se haya habilitado una función, vuelve a consultar las funciones restantes con las funciones habilitadas para ver si sus interruptores ahora deben estar atenuados debido a las restricciones de compatibilidad.

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

Consulta la entrada de blog sobre grupos de funciones para obtener más información. 

Más mejoras de vídeo

  • Mejoras en la cámara simultánea: con CameraX 1.5.1, ahora puedes vincular los casos prácticos de Vista previa, Captura de imagen y Captura de vídeo simultáneamente para cada SingleCameraConfig en el modo de no composición. Además, en el modo de composición (los mismos casos prácticos que con CompositionSettings),  ahora puedes definir el CameraEffect que se aplica al resultado final de la composición.
  • Silencio dinámico: ahora puedes iniciar una grabación en estado silenciado con PendingRecording.withAudioEnabled(boolean initialMuted) y permitir que el usuario reactive el sonido más adelante con Recording.mute(boolean muted).
  • Gestión mejorada del almacenamiento insuficiente: CameraX ahora envía de forma fiable el error VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE, lo que permite que tu aplicación gestione correctamente las situaciones de poco almacenamiento e informe al usuario.
  • Mejora con poca luz: en los dispositivos compatibles (como la serie Pixel 10), puedes habilitar CameraControl.enableLowLightBoostAsync para iluminar automáticamente la vista previa y los flujos de vídeo en entornos oscuros.

Captura de imágenes de calidad profesional

CameraX 1.5 incluye mejoras importantes en ImageCapture para los desarrolladores que exigen la máxima calidad y flexibilidad.

Da rienda suelta a tu creatividad con la captura DNG (RAW)

Para tener un control total sobre el posprocesamiento, CameraX ahora admite la captura en formato DNG (RAW). De esta forma, puedes acceder a los datos de imagen sin procesar ni comprimir directamente desde el sensor de la cámara, lo que te permite editar y gradar el color con calidad profesional. La API permite capturar solo el archivo DNG o capturar simultáneamente las salidas JPEG y DNG. Consulta el código de muestra que se incluye más abajo para ver cómo capturar archivos JPEG y DNG simultáneamente.

  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 para extensiones de cámara

Disfruta de lo mejor de ambos mundos: la impresionante fotografía computacional de las extensiones de la cámara (como el modo Noche) combinada con el brillo y el rango dinámico de Ultra HDR. Esta función ahora está disponible en muchos teléfonos Android premium recientes, como las series Pixel 9 y 10, y las series Samsung S24 y 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()

Mejoras en la API principal y en la usabilidad

Una nueva forma de configurar: SessionConfig

Como se ha visto en los ejemplos anteriores, SessionConfig es un concepto nuevo de CameraX 1.5. Centraliza la configuración y simplifica la API de dos formas principales:

  1. No más llamadas manuales:unbind() las APIs de CameraX tienen en cuenta el ciclo de vida. Se desvincula implícitamente de tus casos prácticos cuando se destruye la actividad u otro LifecycleOwner. Sin embargo, para actualizar los casos prácticos o cambiar de cámara, tendrás que llamar a unbind() o unbindAll() antes de volver a vincularla. Ahora, con CameraX 1.5, cuando vinculas un nuevo SessionConfig, CameraX actualiza la sesión automáticamente, por lo que no es necesario realizar llamadas de desvinculación.
  2. Control determinista de la velocidad de fotogramas: la nueva API SessionConfig introduce una forma determinista de gestionar la velocidad de fotogramas. A diferencia del setTargetFrameRate anterior, que solo era una sugerencia, este nuevo método garantiza que el intervalo de velocidad de fotogramas especificado se aplicará si la configuración se realiza correctamente. Para garantizar la precisión, debe consultar las frecuencias de fotogramas admitidas mediante CameraInfo.getSupportedFrameRateRanges(SessionConfig). Si se pasa el SessionConfig completo, CameraX puede determinar con precisión los intervalos admitidos en función de las configuraciones de la transmisión.

Camera Compose ya es estable

Sabemos que te encanta Jetpack Compose y nos complace anunciar que la biblioteca camera-compose ya está estable en la versión 1.5.1. Esta versión incluye correcciones de errores críticos relacionados con el uso de CameraXViewfinder con funciones de Compose como moveableContentOf y Pager, así como la resolución de un problema de estiramiento de la vista previa. Seguiremos añadiendo más funciones a camera-compose en futuras versiones.

Mejoras en ImageAnalysis y CameraControl

  • Ajuste de la intensidad de la linterna: controla con precisión la linterna del dispositivo con las nuevas APIs. Puedes consultar la intensidad máxima admitida con CameraInfo.getMaxTorchStrengthLevel() y, a continuación, definir el nivel deseado con CameraControl.setTorchStrengthLevel().
  • Compatibilidad con NV21 en ImageAnalysis: ahora puedes solicitar el formato de imagen NV21 directamente desde ImageAnalysis, lo que simplifica la integración con otras bibliotecas y APIs. Para habilitar esta opción, invoca ImageAnalysis.Builder.setOutputImageFormat(OUTPUT_IMAGE_FORMAT_NV21).

Empieza hoy mismo

Actualiza hoy mismo tus dependencias a CameraX 1.5 y descubre las nuevas funciones. Estamos deseando ver tus creaciones.

Para usar CameraX 1.5,  añade las siguientes dependencias a tu archivo libs.versions.toml. Te recomendamos que uses la versión 1.5.1, que incluye muchas correcciones de errores críticos y mejoras en la cámara simultánea. 

  [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" }

A continuación, añade estas dependencias al archivo build.gradle.kts de tu módulo:

  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 

}

¿Tienes alguna pregunta o quieres ponerte en contacto con el equipo de CameraX? Únete al foro de debate para desarrolladores de CameraX o envía un informe de errores:

Escrito por:

Seguir leyendo