EGLCapture

Minimal OpenGL / OpenGL ES game capture tool for Linux

Easy GL Capture

A minimal OpenGL / OpenGL ES game capture tool for Linux, implemented as an LD_PRELOAD library.

This library intercepts GLX/EGL buffer swaps, reads the rendered framebuffer, and pipes frames to FFmpeg for video encoding. Recording can be toggled at runtime without modifying or rebuilding the target application.

Supported

  • GLX: desktop OpenGL and GLES contexts created through GLX.
  • EGL: OpenGL ES or desktop OpenGL contexts created through EGL.
  • Dynamically loaded GL functions: applications using dlopen() + dlsym() (e.g. SDL) are supported by intercepting function lookups.
  • EGL damage swaps: supports eglSwapBuffersWithDamageKHR and eglSwapBuffersWithDamageEXT.

The GL API (desktop GL or GLES) is detected at runtime using GL_VERSION.

Limitations

  • no Vulkan support.
  • Pure Wayland environments cannot use the F6 hotkey; use SIGUSR1 instead.
  • Only the current GLX drawable or EGL draw surface is captured.
  • Recording stops if the captured surface changes dimensions.
  • Audio capture currently uses FFmpeg’s PulseAudio input.

Requirements

  • A GLX or EGL application
  • FFmpeg available in PATH
  • FFmpeg built with libx264 (default video codec)
  • PulseAudio-compatible audio input, if recording audio

Build

git clone https://codeberg.org/itszariep/eglcapture
cd eglcapture
make

Usage

Run an application with capture enabled

LD_PRELOAD=/path/to/eglcap.so ./mygame

The library waits for the application to create a usable GL context and swap its framebuffer.

To capture a game:

eglcapture./mygame

LD_PRELOAD may also affect child processes. Use GLCAP_VERBOSE=1 to help identify which processes load the library.

Toggle recording

F6 (X11 / XWayland)

Press F6 to start recording. Press it again to stop and save the video.

SIGUSR1

You can also toggle recording by sending SIGUSR1 to the target process:

kill -USR1 "$(pidof mygame)"

Or use the PID printed in the capture log:

kill -USR1 <pid>

Second method also works on pure Wayland, where the F6 hotkey is unavailable.

Recording can only start when a usable GL context and capture surface are available.

Recording indicator

  • red square is displayed in the corner while recording.
  • A RECORDING label appears briefly when recording starts.
  • A SAVED label appears briefly after a successful save.
  • Labels are displayed for 3 seconds.

The overlay is drawn after framebuffer capture, so it does not appear in the recorded video.

Output files

By default, recordings are saved in the current working directory:

glcap_YYYYMMDD_HHMMSS.mp4

The filename uses the date and time when recording starts.

The output directory, container, codecs, and FFmpeg arguments can be customized using environment variables.

Environment variables

Variable Default Description
GLCAP_DIR . Output directory for recordings
GLCAP_OUTPUT_FILE Empty Exact file path for recording
GLCAP_FPS 24 Maximum capture rate in FPS. Values below 1 fall back to 24
GLCAP_VERBOSE 0 Set to 1 to log load/exit diagnostics and intercepted function lookups
GLCAP_QUIET 0 Set to 1 to suppress all capture log output
GLCAP_COLOR Auto Set to 1 to force colored logs, 0 to disable
GLCAP_CONTAINER mp4 Output container/extension
GLCAP_VCODEC libx264 FFmpeg video codec
GLCAP_ACODEC aac FFmpeg audio codec
GLCAP_FFMPEG_ARGS Empty Additional FFmpeg arguments
GLCAP_AUDIO 0 Set to 1 to enable audio capture
GLCAP_AUDIO_DEVICE default.monitor PulseAudio input device for audio capture
GLCAP_ALWAYS_RECORD Empty Always record by default

GLCAP_COLOR defaults to enabled when stderr is a TTY, unless NO_COLOR is set. An explicit GLCAP_COLOR value overrides this behavior.

GLCAP_QUIET=1 suppresses log messages, but does not disable recording.

Examples

Pipe the game so programs like ADSR can use it:

mkfifo /tmp/glcap.fifo &&
GLCAP_OUTPUT_FILE=/tmp/glcap.fifo GLCAP_VCODEC=rawvideo GLCAP_FFMPEG_ARGS="-pix_fmt bgr0 -f rawvideo" eglcapture glxgears

Record at 60 FPS:

GLCAP_FPS=60 eglcapture./mygame

Save recordings to a specific directory:

GLCAP_DIR="$HOME/Videos" eglcapture./mygame

Enable audio capture:

GLCAP_AUDIO=1 eglcapture./mygame

Choose a PulseAudio monitor/device:

GLCAP_AUDIO=1 \
GLCAP_AUDIO_DEVICE="default.monitor" \
eglcapture./mygame

Use a different video codec or FFmpeg preset:

GLCAP_VCODEC=libx264 \
GLCAP_FFMPEG_ARGS="-preset veryfast -crf 18" \
eglcapture./mygame

Enable verbose diagnostics:

GLCAP_VERBOSE=1 eglcapture./mygame

Disable all capture logs:

GLCAP_QUIET=1 eglcapture./mygame

How it works

  1. LD_PRELOAD loads the capture library into the target process.
  2. GLX/EGL buffer swap functions are intercepted.
  3. The library checks for a current GL context and a usable drawable/surface.
  4. When recording is active, the default framebuffer is read back as RGBA pixels.
  5. Frames are rate-limited and piped to FFmpeg for encoding.
  6. On stop, FFmpeg is finalized and the recording is saved.

The capture code preserves relevant GL readback state, including pixel pack alignment, framebuffer binding, pixel pack buffer binding, and (for desktop GL) the read buffer.

The video is vertically flipped and cropped to even dimensions by FFmpeg for encoding.

If the application resizes its capture surface during recording, recording is stopped to avoid writing frames with inconsistent dimensions.


© 2026 Zariep's portfolio

Powered by Tessera for Hugo