Tutoriais

Captura de alta velocidade e vídeo em câmera lenta com o CameraX 1.5

Leitura de 6 minutos
Leo Huang
Engenheiro de software

Capturar ações rápidas com clareza é um recurso essencial para apps de câmera modernos. Isso é feito com a captura de alta velocidade, o processo de aquisição de frames em taxas como 120 ou 240 fps. Essa captura de alta fidelidade pode ser usada para duas finalidades distintas: criar um vídeo de alta taxa de frames para uma análise detalhada, frame a frame, ou gerar um vídeo em câmera lenta em que a ação se desenrola de forma dramática na tela.

Antes, a implementação desses recursos com a API Camera2 era um processo mais prático. Agora, com a nova API de alta velocidade no CameraX 1.5, todo o processo é simplificado, oferecendo a flexibilidade de criar vídeos de alta taxa de frames ou clipes em câmera lenta prontos para reprodução. Nesta postagem, vamos mostrar como dominar os dois. Para quem não conhece o CameraX, é possível conferir a visão geral do CameraX.


O princípio por trás da câmera lenta

O princípio fundamental da câmera lenta é capturar vídeos com uma taxa de frames muito maior do que a reprodução. Por exemplo, se você gravar um evento de um segundo a 120 quadros por segundo (fps) e depois reproduzir essa gravação a 30 fps, o vídeo vai levar quatro segundos para ser reproduzido. Esse "esticamento" do tempo cria o efeito dramático de câmera lenta, permitindo que você veja detalhes que são rápidos demais para o olho humano.

Para garantir que o vídeo final seja suave e fluido, ele precisa ser renderizado a uma taxa mínima de 30 fps. Isso significa que, para criar um vídeo em câmera lenta de 4x, a taxa de captura original precisa ser de pelo menos 120 fps (120 fps de captura ÷ 4 = 30 fps de reprodução).

Depois que a filmagem de alta taxa de frames é capturada, há duas maneiras principais de alcançar o resultado desejado:

  • Câmera lenta controlada pelo player (vídeo de alta taxa de frames): a gravação em alta velocidade (por exemplo, 120 fps) é salva diretamente como um arquivo de vídeo de alta taxa de frames. É responsabilidade do player de vídeo diminuir a velocidade do vídeo. Isso dá ao usuário a flexibilidade de alternar entre a reprodução normal e em câmera lenta.
  • Câmera lenta pronta para reprodução (vídeo recodificado): o fluxo de vídeo de alta velocidade é processado e recodificado em um arquivo com uma taxa de frames padrão (por exemplo, 30 QPS). O efeito de câmera lenta é "incorporado" ao ajustar os carimbos de data/hora dos frames. O vídeo resultante será reproduzido em câmera lenta em qualquer player de vídeo padrão sem tratamento especial. Embora o vídeo seja reproduzido em câmera lenta por padrão, os players de vídeo ainda podem oferecer controles de velocidade do vídeo que permitem ao usuário aumentar a velocidade e assistir o vídeo na velocidade original.

A API CameraX simplifica isso oferecendo uma maneira unificada de escolher a abordagem desejada, como você verá abaixo.


A nova API High-Speed Video

A nova solução CameraX é baseada em dois componentes principais:

  • Recorder#getHighSpeedVideoCapabilities(CameraInfo): esse método permite verificar se a câmera pode gravar em alta velocidade e, em caso afirmativo, quais resoluções (objetos Quality) são compatíveis.
  • HighSpeedVideoSessionConfig: esse é um objeto de configuração especial que agrupa seus casos de uso de VideoCapture e Preview, informando ao CameraX para criar uma sessão de câmera unificada de alta velocidade. Embora o stream VideoCapture opere com a alta taxa de frames configurada, o stream de visualização geralmente é limitado a uma taxa padrão de pelo menos 30 QPS pelo sistema de câmera para garantir uma exibição suave na tela.

Como começar

Antes de começar, verifique se você adicionou as dependências necessárias do CameraX ao arquivo build.gradle.kts do app. Você vai precisar do artefato camera-video e das principais bibliotecas da CameraX.

// build.gradle.kts (Module: app)

dependencies {

    val camerax_version = "1.5.1"


    implementation("androidx.camera:camera-core:$camerax_version")

    implementation("androidx.camera:camera-camera2:$camerax_version")

    implementation("androidx.camera:camera-lifecycle:$camerax_version")

    implementation("androidx.camera:camera-video:$camerax_version")

    implementation("androidx.camera:camera-view:$camerax_version")

}

Observação sobre APIs experimentais

É importante observar que as APIs de gravação em alta velocidade são experimentais no momento. Isso significa que elas estão sujeitas a mudanças em versões futuras. Para usá-los, adicione a seguinte anotação ao seu código:

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

Implementação

A implementação para os dois resultados começa com as mesmas etapas de configuração. A escolha entre criar um vídeo com alta taxa de frames ou em câmera lenta depende de uma única configuração.

1. Configurar a captura em alta velocidade

Primeiro, independente da sua meta, você precisa receber o ProcessCameraProvider, verificar os recursos do dispositivo e criar seus casos de uso.

O bloco de código a seguir mostra o fluxo de configuração completo em uma função de suspensão. É possível chamar essa função de um escopo de corrotina, como lifecycleScope.launch.

// Add the OptIn annotation at the top of your function or class

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

private suspend fun setupCamera() {

    // Asynchronously get the CameraProvider

    val cameraProvider = ProcessCameraProvider.awaitInstance(this)



    // -- CHECK CAPABILITIES --

    val cameraInfo = cameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA)

    val videoCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)

    if (videoCapabilities == null) {

        // This camera device does not support high-speed video.

        return

    }




    // -- CREATE USE CASES --

    val preview = Preview.Builder().build()    


    // You can create a Recorder with default settings.

    // CameraX will automatically select a suitable quality.

    val recorder = Recorder.Builder().build()


    // Alternatively, to use a specific resolution, you can configure the
    // Recorder with a QualitySelector. This is useful if your app has
    // specific resolution requirements or you want to offer user
    // preferences. 

    // To use a specific quality, you can uncomment the following lines.

    // Get the list of qualities supported for high-speed video. 

    // val supportedQualities = videoCapabilities.getSupportedQualities(DynamicRange.SDR)

    // Build the Recorder using the quality from the supported list.

    // val recorderWithQuality = Recorder.Builder()

    //     .setQualitySelector(QualitySelector.from(supportedQualities.first()))

    //     .build()



    // Create the VideoCapture use case, using either recorder or recorderWithQuality

    val videoCapture = VideoCapture.withOutput(recorder)

    // Now you are ready to configure the session for your desired output...

}

2. Escolher a saída

Agora, decida o tipo de vídeo que você quer criar. Esse código seria executado dentro da função setupCamera() suspend mostrada acima.

Opção A: criar um vídeo de alta taxa de frames

Escolha essa opção se quiser que o arquivo final tenha uma alta taxa de frames (por exemplo, um vídeo de 120 fps).

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)


// Query and apply a supported frame rate. Common supported frame rates include 120 and 240 fps.

val supportedFrameRateRanges =

    cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())


sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

Opção B: criar um vídeo em câmera lenta pronto para reproduzir

Escolha essa opção se quiser um vídeo que seja reproduzido em câmera lenta automaticamente em qualquer player de vídeo padrão.

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)



// This is the key: enable automatic slow-motion!

sessionConfigBuilder.setSlowMotionEnabled(true)



// Query and apply a supported frame rate. Common supported frame rates include 120, 240, and 480 fps.

val supportedFrameRateRanges =

   cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())

sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

Essa única flag é a chave para criar um vídeo em câmera lenta pronto para ser reproduzido. Quando setSlowMotionEnabled é verdadeiro, o CameraX processa o stream de alta velocidade e o salva como um arquivo de vídeo padrão de 30 fps. A velocidade da câmera lenta é determinada pela proporção entre a taxa de frames de captura e essa velocidade do vídeo padrão.

Exemplo:

  • A gravação a 120 qps vai produzir um vídeo que será reproduzido a 1/4 da velocidade (120 ÷ 30 = 4).
  • A gravação a 240 qps produz um vídeo que é reproduzido a 1/8 da velocidade (240 ÷ 30 = 8).

Juntando tudo: gravar o vídeo

Depois de configurar o HighSpeedVideoSessionConfig e vinculá-lo ao ciclo de vida, a etapa final é iniciar a gravação. O processo de preparação das opções de saída, início da gravação e processamento de eventos de vídeo é o mesmo de uma captura de vídeo padrão.

Esta postagem se concentra na configuração de alta velocidade, então não vamos abordar o processo de gravação em detalhes. Para um guia completo sobre tudo, desde a preparação de um objeto FileOutputOptions ou MediaStoreOutputOptions até o processamento dos callbacks VideoRecordEvent, consulte a documentação do VideoCapture.

// Bind the session config to the lifecycle

cameraProvider.bindToLifecycle(

    this as LifecycleOwner,

    CameraSelector.DEFAULT_BACK_CAMERA,

    sessionConfigBuilder.build() // Bind the config object from Option A or B

)



// Start the recording using the VideoCapture use case

val recording = videoCapture.output

    .prepareRecording(context, outputOptions) // See docs for creating outputOptions

    .start(ContextCompat.getMainExecutor(context)) { recordEvent ->

        // Handle recording events (e.g., Start, Pause, Finalize)

    }

Suporte do Google Fotos para vídeos em câmera lenta

Quando você ativa o setSlowMotionEnabled(true) no CameraX, o arquivo de vídeo resultante é projetado para ser reconhecido e reproduzido instantaneamente como câmera lenta em players de vídeo padrão e apps de galeria. O Google Fotos, em particular, oferece funcionalidade aprimorada para esses vídeos em câmera lenta quando a taxa de captura é de 120, 240, 360, 480 ou 960 fps:

  • Reconhecimento de interface distinta em miniaturas:na sua biblioteca do Google Fotos, os vídeos em câmera lenta podem ser identificados por elementos específicos da interface, distinguindo-os dos vídeos normais.
normal.png
  • Segmentos de velocidade ajustáveis durante a reprodução:ao reproduzir um vídeo em câmera lenta, o Google Fotos oferece controles para ajustar quais partes do vídeo são reproduzidas em câmera lenta e quais são reproduzidas em velocidade normal, dando aos usuários controle criativo. O vídeo editado pode ser exportado como um novo arquivo de vídeo usando o botão Compartilhar, preservando os segmentos em câmera lenta definidos.
normal2.png

Observação sobre o suporte a dispositivos

A API de alta velocidade do CameraX depende do sistema CamcorderProfile do Android para determinar quais resoluções e frame rates de alta velocidade um dispositivo oferece suporte. Os CamcorderProfiles são validados pelo conjunto de teste de compatibilidade do Android (CTS), o que significa que você pode confiar nos recursos de gravação de vídeo informados pelo dispositivo.

Isso significa que a capacidade de um dispositivo gravar vídeos em câmera lenta com o app de câmera integrado não garante que a API de alta velocidade do CameraX funcione. Essa discrepância ocorre porque os fabricantes de dispositivos são responsáveis por preencher as entradas CamcorderProfile no firmware do dispositivo. Às vezes, os perfis de alta velocidade necessários, como CamcorderProfile.QUALITY_HIGH_SPEED_1080P e CamcorderProfile.QUALITY_HIGH_SPEED_720P, não são incluídos. Quando esses perfis estão ausentes, Recorder.getHighSpeedVideoCapabilities() retorna null.

Portanto, é essencial usar sempre Recorder.getHighSpeedVideoCapabilities() para verificar os recursos compatíveis de forma programática, já que essa é a maneira mais confiável de garantir uma experiência consistente em diferentes dispositivos. Se você tentar vincular um HighSpeedVideoSessionConfig em um dispositivo em que Recorder.getHighSpeedVideoCapabilities() retorna nulo, a operação vai falhar com um IllegalArgumentException. É possível confirmar o suporte em dispositivos Google Pixel, já que eles incluem consistentemente esses perfis de alta velocidade. Além disso, vários dispositivos de outros fabricantes, como o Motorola Edge 30, o OPPO Find N2 Flip e o Sony Xperia 1 V, também são compatíveis com os recursos de vídeo de alta velocidade.


Conclusão

A API de vídeo de alta velocidade do CameraX é eficiente e flexível. Se você precisa de imagens com alta taxa de frames para análise técnica ou quer adicionar efeitos cinematográficos de câmera lenta ao seu app, o HighSpeedVideoSessionConfig oferece uma solução unificada e simples. Ao entender a função da flag setSlowMotionEnabled, você pode oferecer suporte aos dois casos de uso e dar aos usuários mais controle criativo.

Escrito por:

Continuar lendo