# How to record a video with audio and a time limit

> Record video (with or without audio), set quality and duration limit, and get the MP4 path.

Source: https://crossfly.dev/docs/cookbook/device/gravar-video — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# How to record a video with audio and a time limit

**Purpose.** Record a video with the device camera, optionally **with audio**, limiting the
duration and choosing the quality, and get the **path of the `.mp4` file**.

## APIs used
- `Camera.captureMode` (`Preview`) — capture mode: `PHOTO`, `MUTED_VIDEO` (video without sound), `AUDIO_VIDEO` (video + audio).
- `Camera.videoTimeLimit` (`int`) — recording limit in **seconds**; `0` = no limit.
- `Camera.videoQuality` (`AVQuality`) — `HIGH`, `MEDIUM` (default of `Camera`), `LOW`. Each value sets fps, video/audio rate, and stereo.
- `Camera.shot()` → `String` — starts the recording UI and returns the path of the `.mp4` (or `null`).
- `PhotoPicker(Preview type)` — UI used when `cameraType == PICKER`; it has the public fields `videoTimeLimit` and `videoQuality` that `shot()` already fills in from the `Camera`.

> **Note.** In `PhotoPicker`, when recording video, the file is saved to `/sdcard/<timestamp>.mp4`.
> `videoTimeLimit` makes the picker's time label **count down**. In `AUDIO_VIDEO`
> the recording includes audio (`GdxRecorder.startVideoWithAudio`), in `MUTED_VIDEO` it doesn't.
> On iOS with video mode, `shot()` uses the OS native camera passing `videoTimeLimit`/`videoQuality`.

## Complete example (copy, paste, and run)

```java
package com.exemplo;

import dev.crossfly.ui.*;                   // Window, Component, Button, Label, UIConstants
import dev.crossfly.ui.layout.*;            // VerticalLayout
import dev.crossfly.device.*;               // Camera, Camera.AVQuality

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Label resultado = new Label("");
      add(LAY_AUTO, resultado);

      Button acao = new Button("Gravar vídeo");
      acao.onAction(c ->
      {
         new Thread(() ->
         {
            Camera cam = new Camera();
            cam.cameraType     = UIConstants.CameraType.PICKER;     // CrossFly recording UI
            cam.captureMode    = UIConstants.Preview.AUDIO_VIDEO;   // video WITH audio (use MUTED_VIDEO for no sound)
            cam.videoQuality   = Camera.AVQuality.HIGH;             // HIGH | MEDIUM | LOW
            cam.videoTimeLimit = 30;                                // 30s; 0 = no limit

            String mp4 = cam.shot();                                // path of the .mp4, or null if cancelled

            Component.onUI(() ->                                    // return outside the paint thread
               resultado.setText(mp4 != null ? "Vídeo: " + mp4 : "Cancelado"));
         }).start();
      });
      add(LAY_AUTO, acao);
   }
}
```

> The snippet below shows **only the core**. To run it, place it in the `MainWindow` skeleton above.

## Minimal snippet

```java
// verified at source: Camera.java (captureMode/videoTimeLimit/videoQuality, shot()); PhotoPicker.java (startRecording, stopRecording)
import dev.crossfly.device.*;              // Camera, Camera.AVQuality
import dev.crossfly.ui.*;                  // Component, UIConstants.CameraType/Preview

new Thread(() -> {
   Camera cam = new Camera();
   cam.cameraType    = UIConstants.CameraType.PICKER;     // CrossFly recording UI
   cam.captureMode   = UIConstants.Preview.AUDIO_VIDEO;   // video WITH audio (use MUTED_VIDEO for no sound)
   cam.videoQuality  = Camera.AVQuality.HIGH;             // HIGH | MEDIUM | LOW
   cam.videoTimeLimit = 30;                               // 30s; 0 = no limit

   String mp4 = cam.shot();                               // path of the .mp4, or null if cancelled

   Component.onUI(() -> {                                 // return outside the paint thread
      if (mp4 != null)
         usarVideo(mp4);
   });
}).start();
```

## Go deeper
- Camera guide: [Device camera](/docs/data-and-services/device-camera) · Widget: [PhotoPicker](/docs/ui/widgets/photopicker)
- Sibling recipe: [tirar-foto.md](/docs/cookbook/device/tirar-foto)
