# Ocula

A small Rust screen recorder designed to fail safely. The GUI binary is `ocula`; the CLI binary is `oculo`.

It records through the desktop screencast portal on Wayland and can use direct X11 capture on X11. Output is written to a temporary file in the same directory, finalized with EOS on stop, synced, then atomically renamed to the final `.mp4`, `.mkv`, or `.gif` file.

## Why This Is Harder To Break

- Uses `xdg-desktop-portal` and PipeWire instead of brittle screenshot loops.
- Defaults to MP4/H.264 for compatibility, while keeping MKV/MJPEG available as the safest high-throughput option.
- Handles Ctrl-C and SIGTERM by sending EOS before stopping, so muxers can finalize.
- Writes to `*.part` first, then renames into place only after GStreamer has stopped.
- Creates the output directory automatically and avoids overwriting existing recordings unless asked.
- Probes existing output directories or their nearest existing parents for writability before capture setup.
- Can fall back to X11 capture when running under X11.
- Supports selected-region recording with `--area` or `--select`.
- Downscales large full-screen recordings to 1080p by default so 4K screens do not overload software encoders, without upscaling smaller captures.
- Keeps raw video buffering small and drops stale raw frames under encoder pressure so recording stays real-time instead of building huge lag.
- Caps capture framerate without manufacturing duplicate frames and feeds software H.264/VP8 explicit `I420` input to reduce negotiation/conversion overhead.
- Skips unnecessary color conversion for direct X11/MJPEG capture.
- Chooses default H.264/VP8 bitrates from effective output size and FPS, while preserving explicit `--bitrate` exactly.

No recorder can save a file after `SIGKILL`, power loss, kernel crash, or disk failure, but this is built to preserve recordings for normal crashes, errors, and interrupts as much as GStreamer allows.

## Requirements

- Rust 1.92+
- GStreamer 1.22+
- GStreamer plugins: `matroskamux`, `jpegenc`, `videoscale`, `videocrop`, `pipewiresrc` for Wayland, `ximagesrc` for X11, `opusenc` for MKV audio
- Default MP4 plugins: `mp4mux`, `openh264enc` or a supported hardware H.264 encoder, `h264parse`, and an AAC encoder such as `fdkaacenc` for MP4 audio
- Optional GIF plugin: `gifenc`
- For Wayland: `pipewire`, `xdg-desktop-portal`, and a portal backend such as GTK, KDE, GNOME, or wlr
- For X11 fallback: `ximagesrc`
- X11/XWayland for interactive `--select`, or use `--area` with explicit coordinates
- PulseAudio-compatible default input/output devices when `--audio mic`, `--audio system`, or `--audio both` is used

On Wayland, `--backend auto` uses the desktop portal only. Use `--backend x11` explicitly if you intentionally want X11/XWayland capture.

## Build

```sh
cargo build --release
```

Install from crates.io after release:

```sh
cargo install ocula --locked
```

## Use

Launch the native desktop app:

```sh
cargo run --release --bin ocula
```

After install, launch it with:

```sh
ocula
```

The desktop app provides compact capture controls, audio, pointer, MP4/MKV/GIF format controls, optional GLSL effects, an output picker, a large record/stop button, and a live recorder log. In Area mode, Ocula shows an effect-aware crop preview panel before selection; click the preview panel, focus it and press Enter/Space, or click Pick Crop, then drag an area, refine it with the glass-style selector handles, and click Use This Crop or press Enter before recording. Ocula keeps a real selected-area crop preview visible when X11 snapshots are available, falls back to a clean crop map otherwise, and shows a click-through crop outline outside the selected area after selection and while recording. It launches the same fail-safe recorder engine as the CLI and stops recordings with a graceful interrupt so GStreamer can finalize the output file.

Run the CLI directly after install:

```sh
oculo --mode area
```

Start from an interactive chooser in the current directory:

```sh
cargo run --release --bin oculo --
```

The chooser supports screen or monitor, window, area, audio, pointer visibility, and output-path choices. Use explicit flags below when scripting or when you do not want a prompt.

Record to a directory:

```sh
cargo run --release --bin oculo -- --dir ~/Videos
```

Record with microphone audio:

```sh
cargo run --release --bin oculo -- --audio mic
```

Record a selected region by coordinates:

```sh
cargo run --release --bin oculo -- --area 100,100,1280,720
```

Record a screen through the normal backend chooser:

```sh
cargo run --release --bin oculo -- --mode screen
```

Record a specific X11 monitor:

```sh
cargo run --release --bin oculo -- --list-monitors
cargo run --release --bin oculo -- --backend x11 --monitor 1
```

Record a window through the desktop portal:

```sh
cargo run --release --bin oculo -- --mode window --backend portal
```

Select multiple monitor streams through the desktop portal:

```sh
cargo run --release --bin oculo -- --multiple
```

Record a selected region interactively with Ocula's built-in selector:

```sh
cargo run --release --bin oculo -- --mode area
```

Selector controls:

- Drag to create or move a region.
- Resize from edge or corner handles.
- Arrow keys move; Shift+arrows resize; Ctrl changes keyboard steps to 10 px.
- Delete or Backspace clears the region.
- Click `Use This Crop` or press Enter/Space to confirm; click `Cancel`, press Escape, or right-click to cancel.

Record MKV instead of the default MP4:

```sh
cargo run --release --bin oculo -- --format mkv --output capture.mkv
```

MP4 uses H.264 video for compatibility. MKV remains available because it is faster to start, supports the MJPEG path, and is safer for interrupted recordings. GIF is video-only, defaults to 15 FPS unless `--fps` is provided, and requires `gifenc`.

Add an optional GLSL effect when GStreamer OpenGL elements are installed:

```sh
cargo run --release --bin oculo -- --effect neon
cargo run --release --bin oculo -- --effect heatmap
cargo run --release --bin oculo -- --effect glitch
cargo run --release --bin oculo -- --effect ripple
cargo run --release --bin oculo -- --effect glass
cargo run --release --bin oculo -- --effect crt
cargo run --release --bin oculo -- --effect holo
cargo run --release --bin oculo -- --effect vapor
cargo run --release --bin oculo -- --effect fracture
cargo run --release --bin oculo -- --effect prism
cargo run --release --bin oculo -- --effect aurora
cargo run --release --bin oculo -- --effect kaleido
```

Effects use `glupload`, `glshader`, and `gldownload`; Ocula preflights those plugins before capture starts. Available effects are `neon`, `heatmap`, `glitch`, `ripple`, `glass`, `crt`, `holo`, `vapor`, `fracture`, `prism`, `aurora`, and `kaleido`.

Record GIF when the GStreamer `gifenc` plugin is installed:

```sh
cargo run --release --bin oculo -- --format gif --audio none --output capture.gif
```

Record full resolution instead of the default 1080p safety downscale for large screens:

```sh
cargo run --release --bin oculo -- --no-scale
```

Stop with Ctrl-C. Press Ctrl-C a second time to abort immediately.

Audio capture is preflighted before area selection, portal consent, and output reservation. If the default microphone or system-audio monitor is unavailable, Ocula fails before creating an output file.

Useful flags:

```sh
--backend auto|portal|x11
--mode screen|window|area
--fps 30
--codec auto|mjpeg|h264|vp8
--h264-encoder auto|hardware|software
--effect none|neon|heatmap|glitch|ripple|glass|crt|holo|vapor|fracture|prism|aurora|kaleido
--format mp4|mkv|gif
--audio none|mic|system|both
--area 100,100,1280,720
--monitor 1
--multiple
--list-monitors
--select
--no-prompt
--scale 1920x1080
--no-scale
--output /path/to/file.mp4
--overwrite
--hide-pointer
--max-duration 60
--eos-timeout 15
```
