Skip to content

Repository files navigation

GameOverlay.Capture

A cross-platform .NET library for capturing screenshots, video recordings (with audio), and performance metrics (FPS, 1% / 0.1% lows, frametimes) from a running game or window.

It captures externally (no code injected into the game) using each OS's native capture stack, so it is anti-cheat-safe and works regardless of the game's graphics API (DirectX 9–12, Vulkan, OpenGL). No FFmpeg dependency.

  • Windows — Windows Graphics Capture + Media Foundation + WASAPI + PresentMon/ETW. Fully implemented and verified.
  • Linux — MangoHud metrics (covers native and Proton/DirectX titles), grim + gpu-screen-recorder. Metrics tested; capture/record authored (needs a Linux desktop to verify).
  • macOSscreencapture (video only in v1). Authored (needs a Mac to verify); the richer ScreenCaptureKit/AVFoundation backend is future work.

Requirements

  • .NET 10 SDK/runtime.
  • Windows: Windows 10 build 1903 (19041) or later for the full feature set.
  • Metrics on Windows require running as administrator (real-time ETW session).
  • Linux/macOS require the relevant CLI tools installed (see Platform notes).

Adding it to your project

The library is not on NuGet yet — reference the projects (or built DLLs). Reference the API package plus the backend for each OS you target; each backend registers itself automatically at runtime based on the current OS.

<ItemGroup>
  <ProjectReference Include="path/to/src/GameOverlay.Capture/GameOverlay.Capture.csproj" />

  <!-- Windows backend (net10.0-windows10.0.19041.0) -->
  <ProjectReference Include="path/to/src/GameOverlay.Capture.Windows/GameOverlay.Capture.Windows.csproj"
                    Condition="'$(TargetFramework)' == 'net10.0-windows10.0.19041.0'" />

  <!-- Linux / macOS backends (net10.0) -->
  <ProjectReference Include="path/to/src/GameOverlay.Capture.Linux/GameOverlay.Capture.Linux.csproj"
                    Condition="'$(TargetFramework)' == 'net10.0'" />
  <ProjectReference Include="path/to/src/GameOverlay.Capture.MacOS/GameOverlay.Capture.MacOS.csproj"
                    Condition="'$(TargetFramework)' == 'net10.0'" />
</ItemGroup>

You only need the backend(s) for the OSes you ship to. All public types are in the GameOverlay.Capture namespace.

Quick start

Pick a target

using GameOverlay.Capture;

var target = CaptureTarget.FromProcess("Rayman Origins"); // by process name
// CaptureTarget.FromProcess(pid) | FromWindow(hwnd) | FromMonitor(hmonitor) | Interactive()

Screenshot

await using var session = await CaptureSession.CreateAsync(target);
await session.SaveScreenshotAsync("shot.png"); // format inferred from extension (.png/.jpg)

Record video + audio

await using var session = await CaptureSession.CreateAsync(target);

var recording = await session.StartRecordingAsync(new RecordingOptions
{
    OutputPath = "clip.mp4",
    Video = new VideoOptions
    {
        Codec     = VideoCodec.H264,     // or Hevc
        FrameRate = 60,                   // paced to this rate
        Quality   = VideoQuality.High,    // or set Bitrate directly
    },
    Audio = new AudioOptions
    {
        SystemLoopback = true,                       // game/system audio -> in the video
        Microphone     = MicrophoneOptions.Default,  // mic -> sidecar "clip.mic.m4a"
        Bitrate        = 160_000,                     // AAC bits/sec per track
    },
});

await Task.Delay(TimeSpan.FromSeconds(10));
await recording.StopAsync(); // finalises clip.mp4 (+ clip.mic.m4a)

On Windows the game/system audio is embedded in the video; the microphone is written to a separate sidecar file next to it (<output>.mic.m4a).

Performance metrics (FPS, 1% lows)

await using var session = await CaptureSession.CreateAsync(target);

session.Metrics.SampleReady += (_, s) =>
    Console.WriteLine($"{s.Fps:F0} fps ({s.FrameTimeMs:F1} ms)"); // live, per frame

session.Metrics.Start();
await Task.Delay(TimeSpan.FromSeconds(30));
session.Metrics.Stop();

MetricsSummary summary = session.Metrics.GetSummary();
Console.WriteLine($"avg {summary.AverageFps:F1} | 1% low {summary.OnePercentLowFps:F1} " +
                  $"| 0.1% low {summary.PointOnePercentLowFps:F1} | min {summary.MinFps:F1}");

Windows metrics use PresentMon/ETW and require the process to run as administrator. On Linux, launch the game with MangoHud logging enabled (metrics parse its CSV). macOS game FPS is not available programmatically (Metal HUD / Instruments only).

Discover devices & capabilities

Use these to populate a settings UI:

foreach (var d in CaptureCapabilities.GetInputDevices())      // microphones
    Console.WriteLine($"{(d.IsDefault ? "*" : " ")} {d.Name}  ({d.Id})");

foreach (var d in CaptureCapabilities.GetOutputDevices())     // system/loopback endpoints
    Console.WriteLine(d.Name);

IReadOnlyList<int>          fps       = CaptureCapabilities.CommonFrameRates;   // 24,30,50,60,120,144,240 (+ any value)
IReadOnlyList<VideoQuality> qualities = CaptureCapabilities.VideoQualities;     // Low..VeryHigh
IReadOnlyList<VideoCodec>   codecs    = CaptureCapabilities.VideoCodecs;        // H264, Hevc
IReadOnlyList<int>          audioKbps = CaptureCapabilities.AudioBitratesKbps;  // 96,128,160,192

// Record from a specific microphone:
var mic = new MicrophoneOptions { DeviceId = CaptureCapabilities.GetInputDevices()[0].Id };

Options reference

CaptureSession.CreateAsync(target, options?, backend?) — resolves the OS backend automatically; throws PlatformNotSupportedException if none is registered.

Type Key members
CaptureTarget FromWindow(hwnd), FromProcess(pid/name), FromMonitor(hmon), Interactive()
CaptureOptions CaptureCursor, HideCaptureBorder (Win11), UseDesktopDuplication (Win, monitor-only), FrameRateCap
RecordingOptions OutputPath (required), Video, Audio, Container (Auto/Mp4/Mkv)
VideoOptions Codec, FrameRate, Quality (Low..VeryHigh), Bitrate (override), UseHardware
AudioOptions SystemLoopback, Microphone, Bitrate (AAC bits/sec), SeparateTracks
MetricsSummary AverageFps, MinFps, MaxFps, OnePercentLowFps, PointOnePercentLowFps, P95/P99FrameTimeMs, FrameCount, DurationSeconds

Quality vs bitrate: VideoQuality derives a bitrate from resolution × frame rate; set VideoOptions.Bitrate (bits/sec) to override it. AudioOptions.Bitrate snaps to the nearest supported AAC rate (96/128/160/192 kbps).

Platform notes

  • Windows — Uses Windows Graphics Capture (per-window/monitor, API-agnostic). Frame rate is paced to VideoOptions.FrameRate; timestamps come from the compositor's presentation time for low jitter. UseDesktopDuplication forces the monitor-only DXGI fallback (e.g. older Windows). Exclusive-fullscreen games may capture black — run the game borderless/windowed (WindowsDiagnostics.IsExclusiveFullscreenActive() detects this).
  • Linux — Metrics reuse MangoHud (a Vulkan layer; Proton routes DirectX → Vulkan, so it covers Windows games too); launch the game with MangoHud logging. Screenshots need grim (Wayland) / spectacle / gnome-screenshot; recording needs gpu-screen-recorder.
  • macOS — Uses the built-in screencapture (video only, no audio in v1); grant Screen Recording permission. Game FPS metrics are not available programmatically.

Building from source

dotnet build GameOverlay.Capture.slnx
dotnet test  GameOverlay.Capture.slnx

Try the sample CLI (samples/GameOverlay.Capture.Cli):

# On Windows, run the Windows-TFM build:
dotnet run --project samples/GameOverlay.Capture.Cli -f net10.0-windows10.0.19041.0 -- devices
dotnet run --project samples/GameOverlay.Capture.Cli -f net10.0-windows10.0.19041.0 -- shot   --process "Game" shot.png
dotnet run --project samples/GameOverlay.Capture.Cli -f net10.0-windows10.0.19041.0 -- record --process "Game" clip.mp4 --seconds 10 --audio --mic --fps 60 --quality high
dotnet run --project samples/GameOverlay.Capture.Cli -f net10.0-windows10.0.19041.0 -- metrics --process "Game" --seconds 30   # run elevated

Architecture

A platform-neutral core (GameOverlay.Capture / .Core) defines the public API and a set of backend interfaces (IFrameSource, IAudioSource, IRecorder, IMetricsProvider, ICaptureBackend, …) plus shared logic (frametime statistics, the recording state machine). Each per-OS backend implements those interfaces and self-registers via a module initializer, so the correct backend is selected at runtime by RID. The shared FrameTimeStatistics / FrameTimeTracker compute the FPS numbers identically across platforms.

Status & roadmap

Capability Windows Linux macOS
Screenshot ✅ verified ⚠️ authored ⚠️ authored
Video recording ✅ verified ⚠️ authored ⚠️ authored (video only)
System audio in video ✅ verified ⚠️ authored ❌ (needs AVFoundation)
Microphone (sidecar) ✅ verified ⚠️ authored ❌ (needs AVFoundation)
FPS / frametime metrics ✅ (elevated) ✅ parser tested ❌ documented gap

Future: in-process PipeWire capture (Linux), a native ScreenCaptureKit/AVFoundation backend (macOS, for system audio + mic), and an optional injection/overlay path (advanced, anti-cheat risk).

License

Licensed under the MIT License.

About

A crossplatform .NET library for capturing screenshots and video recordings for games

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages