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

A captura de 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 qps. Essa captura de alta fidelidade pode ser usada para duas finalidades distintas: criar um vídeo de alta taxa de frames para análise detalhada frame a frame ou gerar um vídeo em câmera lenta em que a ação se desenrola dramaticamente na tela.

Anteriormente, 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 é novo no CameraX, confira 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 (qps) e reproduzir essa gravação a 30 qps padrão, o vídeo vai levar quatro segundos para ser reproduzido. Esse "alongamento" do tempo é o que cria o efeito dramático de câmera lenta, permitindo que você veja detalhes que são muito rápidos para o olho nu.

Para garantir que o vídeo de saída final seja suave e fluido, ele geralmente precisa ser renderizado a um mínimo de 30 qps. Isso significa que, para criar um vídeo em câmera lenta 4x, a taxa de frames de captura original precisa ser de pelo menos 120 qps (120 qps de captura ÷ 4 = 30 qps 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 processada pelo player (vídeo de alta taxa de frames) : a gravação de alta velocidade (por exemplo, 120 qps) é 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 oferece 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" ajustando 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 fornecer 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 de vídeo de alta velocidade

A nova solução CameraX é criada 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 VideoCapture e Preview, informando ao CameraX para criar uma sessão de câmera unificada de alta velocidade. Embora o fluxo VideoCapture opere na alta taxa de frames configurada, o fluxo 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.

Primeiros passos

Antes de começar, adicione as dependências necessárias do CameraX ao arquivo build.gradle.kts do seu app. Você vai precisar do artefato camera-video e das principais bibliotecas do 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 de alta velocidade são experimentais. Isso significa que elas estão sujeitas a mudanças em versões futuras. Para usá-las, é necessário ativar a opção adicionando a seguinte anotação ao seu código:

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

Implementação

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

1. Configurar a captura de alta velocidade

Primeiro, independentemente da sua meta, é necessário 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. Você pode 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 que tipo de vídeo 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 qps).

  // 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 reprodução

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 reprodução. Quando setSlowMotionEnabled é verdadeiro, o CameraX processa o fluxo de alta velocidade e o salva como um arquivo de vídeo padrão de 30 qps. A velocidade da câmera lenta é determinada pela proporção da taxa de frames de captura para essa velocidade do vídeo padrão.

Exemplo:

  • A gravação a 120 qps produzirá um vídeo reproduzido a 1/4 da velocidade (120 ÷ 30 = 4).
  • A gravação a 240 qps produzirá um vídeo 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, o início da gravação e o tratamento de eventos de vídeo são os mesmos 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 abrangente sobre tudo, desde a preparação de um objeto FileOutputOptions ou MediaStoreOutputOptions até o tratamento dos callbacks VideoRecordEvent, consulte a documentação 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 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 frames de captura é de 120, 240, 360, 480 ou 960 qps:

  • Reconhecimento de interface distinto na miniatura:na sua biblioteca do Google Fotos, os vídeos em câmera lenta podem ser identificados por elementos específicos da interface, distinguindo-os de 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 velocidade lenta e quais são reproduzidas em velocidade normal, oferecendo 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 de 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 taxas de frames 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 de 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 e, à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 sempre usar Recorder.getHighSpeedVideoCapabilities() para verificar os recursos com suporte de maneira 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 uma IllegalArgumentException. Você pode confirmar o suporte em dispositivos Google Pixel, já que eles sempre incluem 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 oferecem suporte aos 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 filmagens de 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 o papel da flag setSlowMotionEnabled, você pode oferecer suporte aos dois casos de uso e dar aos usuários mais controle criativo.

Escrito por:

Continuar lendo