Cross-platform headless screen and audio capture library and CLI
Project description
recap
Cross-platform headless screen and audio capture library and CLI.
Features
- Cross-platform: Windows, macOS, and Linux
- Record an entire monitor or a single window
- Record system audio (loopback capture)
- Per-application audio capture (Windows only via WASAPI process loopback)
- Video-only, audio-only, or audio+video modes
- Crop support with configurable size and anchor position
- CLI tool (
recap) and importable Python library - Rust native backend (PyO3) for Windows, with automatic fallback to pure-Python
- Uses FFmpeg for encoding/muxing only
Platform Support
| Feature | Windows | macOS | Linux |
|---|---|---|---|
| Monitor capture | ✓ GDI BitBlt | ✓ CoreGraphics | ✓ X11 XGetImage |
| Window capture | ✓ PrintWindow | ✓ CGWindowListCreateImage | ✓ X11 XGetImage |
| System audio | ✓ WASAPI loopback | ⚠ Requires BlackHole/Soundflower | ✓ PulseAudio monitor |
| Per-app audio | ✓ WASAPI process loopback | ✗ Not supported | ✗ Not supported |
| Rust backend | ✓ | — | — |
| HW encoding | NVENC / QSV / AMF | VideoToolbox / NVENC | NVENC / VAAPI / QSV |
macOS Notes
- Screen Recording permission must be granted in System Settings → Privacy & Security → Screen Recording.
- System audio capture requires a virtual audio loopback device such as BlackHole. Install BlackHole, then set it as your system output (or use a Multi-Output Device to hear audio simultaneously). Recap auto-detects BlackHole/Soundflower when available.
- Per-application audio capture is not supported; system-wide audio is captured instead.
Linux Notes
- Video capture requires X11 (XWayland is acceptable). Native Wayland capture is not yet supported. If running under Wayland, ensure
DISPLAYis set for XWayland. - Audio capture uses PulseAudio/PipeWire loopback (
default.monitor). Ensurepactlis available (pulseaudio-utilsorpipewire-pulse). - Per-application audio capture is not directly supported; system-wide audio is captured instead.
Requirements
- Python 3.10–3.13
- FFmpeg on PATH or specified via
--ffmpeg - Rust toolchain (only if building from source on Windows)
Platform-specific requirements
- Windows: Windows 10 version 2004+ for per-app audio capture
- macOS: macOS 11+ recommended; Screen Recording permission required
- Linux: X11 or XWayland; PulseAudio or PipeWire;
xrandrfor multi-monitor detection
Installation
From PyPI (prebuilt wheels)
pip install recap-capture
From source (editable)
Requires maturin and the Rust toolchain (for the Windows native backend):
pip install maturin
git clone https://github.com/Lexian-droid/recap.git
cd recap
maturin develop --release # builds native backend (Windows only)
pip install -e .
On macOS/Linux, skip the maturin develop step if you don't need the Rust backend — the pure-Python implementations are used automatically.
Architecture
The project has a hybrid Python/Rust structure with a platform abstraction layer:
recap/ Python package (CLI, config, orchestration)
__init__.py Public API and version
_native.py Bridge to Rust — sets NATIVE_AVAILABLE flag
cli.py CLI entry point
config.py RecordingConfig dataclass
recorder.py Orchestrates capture threads + FFmpeg
video.py Platform-dispatching video capture
audio.py Platform-dispatching audio capture
discovery.py Platform-dispatching monitor/window/device enumeration
ffmpeg.py FFmpeg discovery and process wiring
exceptions.py Exception hierarchy
platforms/ Platform abstraction layer
__init__.py Platform detection utilities
macos/ macOS backends (CoreGraphics + FFmpeg avfoundation)
linux/ Linux backends (X11 + FFmpeg pulse/alsa)
rust_core/ Rust native backend (PyO3/maturin, Windows only)
src/lib.rs PyO3 module registration
src/video.rs GDI BitBlt / PrintWindow video capture
src/audio.rs WASAPI loopback + process loopback audio capture
src/discovery.rs Monitor/window/audio device enumeration
Platform dispatch
The video.py, audio.py, and discovery.py modules contain the Windows implementation at the top level. On macOS or Linux, platform-specific implementations are imported from recap/platforms/ and replace the module-level names. This means the public API (from recap import VideoCapture) works identically regardless of platform.
On Windows, the Rust extension (recap._rust_core) can further replace the Python backends with native implementations for maximum performance.
Window-specific recording
When a window is targeted via --window-title or --window-handle:
- Video is captured using the platform's native window capture API
- Audio on Windows uses WASAPI process loopback to isolate audio from that process. On macOS/Linux, system-wide audio is captured instead (with a warning).
Releasing
GitHub Actions will publish the package to PyPI when you push a tag that starts with v (e.g. v0.5.0). Wheels are built for Python 3.10–3.13. The Rust native backend is compiled for Windows; macOS and Linux use pure-Python backends.
CLI Usage
# Check environment
recap doctor
# List available capture targets
recap monitors
recap windows
recap devices
# Record primary monitor with audio
recap record --output recording.mp4
# Record a specific window (video + window-specific audio on Windows)
recap record --window-title "Notepad" --output notepad.mp4
# Record video only
recap record --video-only --output silent.mp4
# Record a 1280x720 crop from the top-left of the selected source
recap record --crop-size 1280x720 --crop-position top-left --output cropped.mp4
# Record a centered 1280x720 crop from a specific window
recap record --window-title "Notepad" --crop-size 1280x720 --crop-position middle --output notepad-cropped.mp4
# Record audio only
recap record --audio-only --output audio.wav
# Record for 30 seconds
recap record --duration 30 --output clip.mp4
Crop positions
--crop-position supports:
top-left,top-middle,top-rightmiddle-left,middle,middle-rightbottom-left,bottom-middle,bottom-right
Center aliases are also accepted (center, top-center, middle-center, etc.).
Library Usage
from recap import Recorder, RecordingConfig
config = RecordingConfig(output="recording.mp4")
recorder = Recorder(config)
recorder.start()
# ... do work ...
recorder.stop()
recorder.wait()
Window-specific recording
from recap import Recorder, RecordingConfig
config = RecordingConfig(
output="discord.mp4",
window_title="Discord",
)
recorder = Recorder(config)
recorder.start()
# captures the Discord window's video (and per-app audio on Windows)
recorder.stop()
recorder.wait()
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file recap_capture-0.5.4.tar.gz.
File metadata
- Download URL: recap_capture-0.5.4.tar.gz
- Upload date:
- Size: 55.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab59a3420b3258d5e999da0bcd21731c87291edcc2656f927878d876166157cf
|
|
| MD5 |
080188cfbe684fb56255ba93d8d67d54
|
|
| BLAKE2b-256 |
e06ddac59820f8117c0a406f782fc977a67c2bc384ed2015c5f8c767c9562149
|
Provenance
The following attestation bundles were made for recap_capture-0.5.4.tar.gz:
Publisher:
release.yml on Lexian-droid/recap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recap_capture-0.5.4.tar.gz -
Subject digest:
ab59a3420b3258d5e999da0bcd21731c87291edcc2656f927878d876166157cf - Sigstore transparency entry: 1288036076
- Sigstore integration time:
-
Permalink:
Lexian-droid/recap@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Branch / Tag:
refs/tags/v0.5.4 - Owner: https://github.com/Lexian-droid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file recap_capture-0.5.4-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: recap_capture-0.5.4-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 263.1 kB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e8403fa6cf7b7b326994e27ff6338874d621d0a0cd3f1b5e90fa4438970f83f
|
|
| MD5 |
bef24d67ab978554e466f01616689976
|
|
| BLAKE2b-256 |
f16eb9f7601e83e24fb7bdfd13a65962e408c979a34ed2fdc41ae1df4944f6e3
|
Provenance
The following attestation bundles were made for recap_capture-0.5.4-cp313-cp313-win_amd64.whl:
Publisher:
release.yml on Lexian-droid/recap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recap_capture-0.5.4-cp313-cp313-win_amd64.whl -
Subject digest:
0e8403fa6cf7b7b326994e27ff6338874d621d0a0cd3f1b5e90fa4438970f83f - Sigstore transparency entry: 1288036543
- Sigstore integration time:
-
Permalink:
Lexian-droid/recap@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Branch / Tag:
refs/tags/v0.5.4 - Owner: https://github.com/Lexian-droid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file recap_capture-0.5.4-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: recap_capture-0.5.4-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 263.8 kB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d18073bf84bcb36d5146d7026b1d4f0993e758a6cf04fd63703bd0c8e2ec7602
|
|
| MD5 |
75e89dd7b4a38b7a693b38608d2ee35a
|
|
| BLAKE2b-256 |
82f5fddb7dd66d5b64a7bd504b44c967d70e309a6a909f502fcb4f8e5661943c
|
Provenance
The following attestation bundles were made for recap_capture-0.5.4-cp312-cp312-win_amd64.whl:
Publisher:
release.yml on Lexian-droid/recap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recap_capture-0.5.4-cp312-cp312-win_amd64.whl -
Subject digest:
d18073bf84bcb36d5146d7026b1d4f0993e758a6cf04fd63703bd0c8e2ec7602 - Sigstore transparency entry: 1288036440
- Sigstore integration time:
-
Permalink:
Lexian-droid/recap@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Branch / Tag:
refs/tags/v0.5.4 - Owner: https://github.com/Lexian-droid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file recap_capture-0.5.4-cp311-cp311-win_amd64.whl.
File metadata
- Download URL: recap_capture-0.5.4-cp311-cp311-win_amd64.whl
- Upload date:
- Size: 263.0 kB
- Tags: CPython 3.11, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2679166f463f2ecfeaf004e887ba87337a191cf7ed07c7ad76acb2fe2541911b
|
|
| MD5 |
91c8804032a671246ea6bd2fdad223d7
|
|
| BLAKE2b-256 |
a2dfe12cfe9790fbe57a4c1a805b5e726952a2a665a067e6040bc87e3ce6f3bb
|
Provenance
The following attestation bundles were made for recap_capture-0.5.4-cp311-cp311-win_amd64.whl:
Publisher:
release.yml on Lexian-droid/recap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recap_capture-0.5.4-cp311-cp311-win_amd64.whl -
Subject digest:
2679166f463f2ecfeaf004e887ba87337a191cf7ed07c7ad76acb2fe2541911b - Sigstore transparency entry: 1288036196
- Sigstore integration time:
-
Permalink:
Lexian-droid/recap@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Branch / Tag:
refs/tags/v0.5.4 - Owner: https://github.com/Lexian-droid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file recap_capture-0.5.4-cp310-cp310-win_amd64.whl.
File metadata
- Download URL: recap_capture-0.5.4-cp310-cp310-win_amd64.whl
- Upload date:
- Size: 262.9 kB
- Tags: CPython 3.10, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51a35f4002eda7a715f48c75cae12273d07ef3708393f1f8d0c11fa8b886e122
|
|
| MD5 |
7d1e7dde66b05e343e8039619fb65f3d
|
|
| BLAKE2b-256 |
b839054d4a043d80e2362733feac2286c3d20c044df0f11eae2f68208752a6d0
|
Provenance
The following attestation bundles were made for recap_capture-0.5.4-cp310-cp310-win_amd64.whl:
Publisher:
release.yml on Lexian-droid/recap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
recap_capture-0.5.4-cp310-cp310-win_amd64.whl -
Subject digest:
51a35f4002eda7a715f48c75cae12273d07ef3708393f1f8d0c11fa8b886e122 - Sigstore transparency entry: 1288036343
- Sigstore integration time:
-
Permalink:
Lexian-droid/recap@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Branch / Tag:
refs/tags/v0.5.4 - Owner: https://github.com/Lexian-droid
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@636e39f0a0beefcd7bb5d044438b81d8e4901bc9 -
Trigger Event:
push
-
Statement type: