Recording Video with CameraX VideoCapture API

Posted by Trevor McGuire, Software Engineer, and Gerry Fan, Android DevRel Engineer

Gerry Fan
Android Developers
Published in
8 min readFeb 23, 2022

--

A picture is worth a thousand words, and CameraX ImageCapture has already made it much easier to tell your story through still images on Android. Now with the new VideoCapture API, CameraX can help you create thousands of continuous pictures to tell an even better and more engaging story! The VideoCapture API tremendously simplifies the video recording task so that you can focus on other important parts of your cutting-edge apps!

In this post, we will introduce the new CameraX VideoCapture API and how to use it in your applications.

Architected to be simple to use

VideoCapture is a new CameraX UseCase, together with the other three predefined UseCases to cover different Camera needs in your applications:

At an architectural level, CameraX VideoCapture API in CameraX (1.1.0-beta01 and higher) works like this:

  • VideoCapture configures the Camera to generate video frames (with video stabilization enabled, etc.).
  • Recorder encodes and compresses the video frames with appropriate bit rate(also synchronizes with the audio stream if audio recording is enabled).
  • Recorder combines the Video and Audio streams into one stream.
  • Recorder writes the combined stream to a file on disk.

This is most likely similar to other capturing systems that you are already familiar with, but note that it hides the complex logic required to make all these pieces work together seamlessly. Now let’s see how to get a VideoCapture session up.

At the interface level, apps configure a VideoCapture UseCasein these two stages:

  • First, configure an output type: Recorder is the one to use for now, but more are planned for the future.
  • Second, create and configure a Recording session: multiple recordings can be created from the same Recorder, but only one can be active (recording video) at any time.

Here’s a high level view of the API configuration steps. The shaded blocks are parts of VideoCapture API:

Using the VideoCapture API

Similar to other CameraX UseCases, follow these generic steps to record with VideoCapture:

  1. Add CameraX dependencies.
  2. Create a VideoCapture UseCase and a CameraSelector.
  3. Bind to a lifecycle owner.
  4. Create a Recording session (specific to the VideoCapture UseCase).
  5. Start and stop the session (specific to the VideoCapture UseCase).

The sections below have the details.

Add CameraX Dependencies

Start by adding the CameraX libraries into your dependencies. VideoCapture is implemented with the camera-video library, but you’ll also need other CameraX libraries, so we recommend simply adding them all to make things easier. Starting from 1.1.0-beta01 release, all Camerax components have been converged to the unified versioning: in the 1.1.0-beta01 and later releases, all components are at the same version, including camera-video. This makes managing the dependencies simpler.

Create VideoCapture UseCase

To create a VideoCapture instance, your app needs to know the type of the VideoOutput for the VideoCapture UseCase. In this release, Recorder performs file recording, which saves recorded video to the local storage described in a later step. Your app can use the default settings or specify a video Quality, as described next, when building a Recorder object.

Select the Video Resolution

Video resolution capabilities vary on different hardware platforms. To provide a generic API and encourage platform innovation, CameraX implements these two facilitating classes:

  • Quality, which lets you specify the target resolution, including Ultra HD (UHD), Full HD ( FHD), High Definition( HD), and Standard Definition (SD). The exact dimension for each resolution is up to the platform implementation.
  • QualitySelector, which lets you define a selecting strategy from the predefined Quality resolutions.

Apps can specify one of several Quality options, with or without a FallbackStrategy, to authorize CameraX to choose the best video recording resolution. For example, the following code creates a QualitySelector with the highest resolution supported on the platform, and if the highest resolution can not be achieved with the requested UseCase combination or for other reasons, lets CameraX pick any resolution that is supportable.

Similarly the application can also specify a QualitySelector with an ordered list of Quality options, plus an optional FallbackStrategy. Check out the reference doc for usage details.

Apps can also query for the underlying platform resolution capabilities, in terms of Quality and Size, with the QualitySelector class. For example the following code can pull a list of the supported VideoCapture Qualities and their corresponding resolutions:

Please note that the returned resolutions may not be supportable when the UseCase combination changes, or when additional camera features, such as Extensions, are required. For those reasons, we highly recommend setting a fallback strategy when creating your QualitySelector.

Create a Recorder and a VideoCapture UseCase Instance

With a QualitySelector, creating a Recorder type of VideoCapture is simple:

Bind the UseCase to a LifecycleCamera

CameraX provides LifecycleCamera interface to manage Camera’s life cycles on application’s behalf. Applications creates a LifecycleCamera by binding a CameraSelector and the use case combinations to a LifecycleOwner such as your activity or your fragment:

The above code snippet binds a Preview and VideoCapture combination, the default back-facing camera to an AndroidX Fragment. This camera will be closed and any in-progress recording will also be automatically stopped when the LifecycleOwner is stopped.

You can further configure the Camera instance that is returned from ProcessCameraProvider.bindToLifecycle(). For example, Torch can be enabled before or during a recording, and Zoom controls can also be used during a recording. Refer to the official documentation for the detailed instructions.

Note that this step is common to all CameraX UseCases (such as Preview, ImageCapture, and ImageAnalysis).

In the current release, the valid UseCase combinations are:

  • VideoCapture + Preview — supported for all camera devices.
  • VideoCapture + Preview+ ImageCapture— requires LIMITED and above Camera2 device.
  • VideoCapture + Preview+ ImageAnalysis — requires LEVEL_3 Camera2 devices available from Android N (API Level 24) and above.

You can build a CameraSelector to your particular requirements; for example, the following code creates a LEVEL_3 camera device CameraSelector if the platform has one:

To see the latest supported combinations, check out the documentation.

Create the recording session

After the VideoCapture UseCase is bound to a LifecycleCamera, the contained Recorder is ready to be used, and from a Recorder, applications can create Recording instances to record video (and audio). A Recording has two stages, the PendingRecording stage for configuration and the active Recording stage for run-time control:

You need to prepare a Recording with:

  • OutputOptions, which can be Android MediaStore, File, or FileDescriptor
  • a VideoRecordEvent listener to respond to run-time recording events

And optionally:

  • include Audio in this recording (Audio recording is Off by default)

The PendingRecording is turned into an active Recording object right after the application calls the start() method to kick start recording. The PendingRecording class offers a fluent API for configuring the Recording, and in most cases does not need to be stored by the application. Concurrent recordings are unsupported with this release, and an application can have one active Recording at any time. To record multiple clips, create a new Recording after the current capture completes.

CameraX video capture operates asynchronously: application requests such as start capturing will occur on a background executor; applications get notified, at a later time via capture events, when those requests are indeed carried out by CameraX. In this sense, applications will need to create and pass a VideoRecordEvent listener when calling the PendingRecording.start() method described later in this post. For example, the following code creates a simple listener to notify user about the Start and the Finalize events:

CameraX implements a rich set of VideoRecordEvents, including the start() method and others that we will touch on in the next section. Make sure to check out the API documentation for the complete events and descriptions. As a general guideline, for any runtime control that you use, you need to handle its corresponding VideoRecordEvent.

One thing to notice is that every VideoRecordEvent includes a RecordingStats object indicating the audio and video capture statistics , such as the file size and duration of the current recording. Your app can use this to display the recording progress to users.

Once you have aVideoRecordEvent listener, creating a Recording is straightforward. For example, the following code creates a Recording to capture a media file in the Android MediaStore:

With the Recording started, now let’s see what application can do next.

Run-time control the Recording

For an active Recording, applications can take the following actions:

All run-time control requests to the CameraX Recording, including the PendingRecording.start(), are carried out asynchronously by CameraX:

  1. CameraX enqueues the request and immediately returns the control to the application.
  2. CameraX notifies the application when the request is fulfilled, with its corresponding event object.

The application needs to handle the events in its VideoRecordEvent listener in order to know the result of run-time control requests, and update other parts of the application, such as updating UI or playing back the captured video. For example, the following code uses a Inten.ACTION_VIEW to playback the recorded video:

That’s all that is needed to record a Video with the new CameraX VideoCapture API!

What’s next for VideoCapture API?

Sharing videos with friends and on social media is more popular than ever, and CameraX wants to help you support this growing trend. We’re considering new features that you’ve requested, such as buffer transformations and using multiple camera sources in the same recording, and we’re continuing to invest in the API to give you a simple and consistent video capturing experience across all of Android.

We see the CameraX project as a collaboration between Android, our device manufacturers, and you, our camera app developers. We’re inviting you to join this project by creating pull requests, sharing your feedback and ideas in the CameraX developer group, or filing issues in the CameraX issue tracker. Thanks for the feedback you’ve given so far!

To learn more about CameraX, visit the CameraX documentation, CameraX codelab, and github samples; to keep up with the latest CameraX development, join the CameraX developer forum if you are not there yet.

--

--