Android Academy · Lesson

Recording Video

Capture video with CameraX.

Lesson 4 of 413 steps

Recording Video is a free Android Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, and your progress syncs across the web and the CoddyKit app. The Android Academy course includes 4 lessons in total.

Recording Video with CameraX

CameRX records video through the VideoCapture use case, backed by a Recorder. In this lesson you'll set up video capture, start and stop a recording, and save it to the gallery — including audio.

The flow mirrors photos but adds a long-running Recording session you start and later stop.

Recorder and Quality

You first build a Recorder, which defines the encoding and quality. QualitySelector lets you request a target quality (e.g. HD, FHD) with a fallback if the device can't provide it.

val recorder = Recorder.Builder()
    .setQualitySelector(
        QualitySelector.from(
            Quality.FHD,
            FallbackStrategy.lowerQualityOrHigherThan(Quality.SD)
        )
    )
    .build()

Creating VideoCapture

Wrap the Recorder in a VideoCapture use case with the withOutput factory. This is the object you bind to the camera, just like ImageCapture.

val videoCapture = VideoCapture.withOutput(recorder)

Binding Preview + VideoCapture

Bind the preview and the VideoCapture together. Note that on many devices you cannot bind ImageCapture and VideoCapture at the same time, so choose the use cases your screen needs.

cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
    lifecycleOwner,
    CameraSelector.DEFAULT_BACK_CAMERA,
    preview,
    videoCapture
)

Audio Permission

To record sound you need the RECORD_AUDIO runtime permission in addition to CAMERA. Request both before starting a recording, and only enable audio if the user granted it.

// Manifest declares both:
// <uses-permission android:name="android.permission.CAMERA" />
// <uses-permission android:name="android.permission.RECORD_AUDIO" />

val audioGranted = ContextCompat.checkSelfPermission(
    context, Manifest.permission.RECORD_AUDIO
) == PackageManager.PERMISSION_GRANTED

Output via MediaStore

As with photos, save the video to MediaStore using scoped storage. Build ContentValues with an mp4 MIME type and create MediaStoreOutputOptions.

val values = ContentValues().apply {
    put(MediaStore.MediaColumns.DISPLAY_NAME, "VID_${System.currentTimeMillis()}")
    put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
    put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/MyApp")
}

val outputOptions = MediaStoreOutputOptions
    .Builder(context.contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
    .setContentValues(values)
    .build()

Starting a Recording

Prepare the recording from the recorder, optionally enable audio with withAudioEnabled(), then start() it. start() returns a Recording object you keep so you can stop it later.

You also pass a listener that receives VideoRecordEvent updates.

val recording = videoCapture.output
    .prepareRecording(context, outputOptions)
    .apply { if (audioGranted) withAudioEnabled() }
    .start(ContextCompat.getMainExecutor(context)) { event ->
        when (event) {
            is VideoRecordEvent.Start -> { /* recording began */ }
            is VideoRecordEvent.Finalize -> {
                if (!event.hasError()) {
                    // event.outputResults.outputUri -> saved video
                }
            }
        }
    }

Reacting to Record Events

The listener streams the lifecycle of the recording:

  • VideoRecordEvent.Start — recording has begun (update UI to a stop button).
  • VideoRecordEvent.Status — periodic updates with recorded duration/size.
  • VideoRecordEvent.Finalize — recording ended; check hasError().
is VideoRecordEvent.Status -> {
    val seconds = event.recordingStats.recordedDurationNanos / 1_000_000_000
    // Update an on-screen timer.
}

Stopping the Recording

To finish, call stop() on the Recording you saved earlier. This triggers a Finalize event where the video URI becomes available.

Keep the active recording in state so a single button can toggle start/stop.

var activeRecording: Recording? = null

// Toggle handler:
if (activeRecording == null) {
    activeRecording = startRecording()
} else {
    activeRecording?.stop()
    activeRecording = null
}

Pause and Resume

A Recording can also be paused and resumed without stopping. This is handy for letting users splice clips into one file.

activeRecording?.pause()
// ...later
activeRecording?.resume()
// Final stop writes the file:
activeRecording?.stop()

Compose UI for Recording

Drive the UI from state. Track whether a recording is active and swap the button icon and action accordingly. Because the listener runs on the main executor, you can update Compose state directly from it.

var isRecording by remember { mutableStateOf(false) }

IconButton(onClick = { toggleRecording() }) {
    Icon(
        imageVector = if (isRecording) Icons.Default.Stop else Icons.Default.Videocam,
        contentDescription = if (isRecording) "Stop" else "Record"
    )
}

Quick Check

Confirm your grasp of video recording with CameraX.

Recap

You can now record video with CameraX:

  • Build a Recorder with a QualitySelector and wrap it in VideoCapture.withOutput.
  • Bind it with the preview and request RECORD_AUDIO for sound.
  • Save via MediaStoreOutputOptions, then prepareRecording().start() to get a Recording.
  • React to VideoRecordEvents; call stop() to finalize and read the saved URI.

You've completed the CameraX course — preview, photos and video are all in your toolkit.

Free to start

Learn Kotlin with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
36
Lessons
152

Frequently Asked Questions

Is the “Recording Video” lesson free?

Yes — any 3 lessons of the Android Academy learning path, including “Recording Video”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Android Academy course includes 4 lessons in total.

What will I learn in “Recording Video”?

Capture video with CameraX. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Android Academy?

No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “Recording Video” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Android Academy lesson?

Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. CameraX Overview
  2. Showing a Camera Preview
  3. Taking Photos
  4. Recording Video
← Back to Android Academy