DXcam

ra1ntyMIT活跃维护

基于 Windows Desktop Duplication API 的 Python 高性能截屏库,低延迟抓取屏幕画面,适合给计算机视觉和智能体应用做实时输入。

A Python high-performance screen capture library for Windows using Desktop Duplication API - Updated 2026

v0.3.0发布于 2026-03-12 02:45 UTC802star97fork同步于 2026-11-07 07:33 UTC

怎么上手

由 README 提炼,执行前请确认
pip install dxcam
pip install "dxcam[cv2,winrt]"
硬件要求按 README 说明

README 未说明最低硬件要求;示例中出现的设备为 NVIDIA GeForce RTX 3090(显存 24348Mb),并可通过 device_info() 查看显卡与显存信息。仅支持 Windows,未提及 CPU 运行方式。

支持 Apple Silicon
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

Windows 上的高性能 Python 截屏库,基于 Desktop Duplication API,适合低延迟高帧率采集

基于 Windows Desktop Duplication API 的 Python 高性能截屏库,低延迟抓取屏幕画面,适合给计算机视觉和智能体应用做实时输入。

核心能力

  • 基于 Desktop Duplication API 实现高帧率截屏
  • 支持 DXGI 与 Windows Graphics Capture 双后端
  • 用环形缓冲区配合目标帧率节流持续采集
  • 提供零拷贝视图接口减少数据复制
  • 支持多显示器与多 GPU 分别创建实例

容易踩的坑

仅支持 Windows,官方 wheel 面向 CPython 3.10~3.14;非 BGRA 输出模式需要 OpenCV 或编译好的 numpy 内核,否则会回退到 cv2;grab() 默认在没有新帧时返回 None,需要最新帧要传 new_frame_only=False;release() 后实例不可复用。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

3 个版本v0.3.0
  1. v0.3.00.3.0最新正式版2026-03-12 · 2026-03-12 02:45 UTC
    • add proper handling of the DXGI mode switch (exclusively <-> normal)
    • add microbenchmark for processors
    • refactors

    What's Changed

    Full Changelog: https://github.com/ra1nty/DXcam/compare/v0.2.0...v0.3.0

  2. v0.2.00.2.02026-03-10 · 2026-03-10 02:15 UTC
    查看更新说明

    0.2.0

    • Added WinRT (Windows.Graphics.Capture) backend support, support cursor rendering, etc
    • Added a new processor split: cv2 backend / numpy (Cython-kernel) backend
    • Added Cython kernels (_numpy_kernels.pyx) for BGRA map/rotate/crop + color conversion, including OpenMP/tuning knobs.
    • Various performance improvements
    • Official hosted Doc
    • Enhanced examples

    What's Changed

    Full Changelog: https://github.com/ra1nty/DXcam/compare/v0.1.0...v0.2.0

  3. v0.1.00.1.02026-03-08 · 2026-03-08 21:23 UTC
    查看更新说明
    • Major overhaul
    • Switched frame transfer from full-surface CopyResource to region-aware CopySubresourceRegion
    • Made IDXGIOutput5.DuplicateOutput1 the default capture path, with env-var fallback to legacy DuplicateOutput.
    • Added explicit DXGI access-lost/session-disconnect handling with safe recovery
    • Reduced capture-thread lock hold time
    • Optimized NumPy/OpenCV processing
    • Added per-frame DXGI timestamp tracking and optional timestamp return
    • Optimized timer pacing
    • Updated grab() API with optional new_frame_only flag
    • Added grab_view() as a zero-copy snapshot helper.
    • Changed grab() behavior during active start() capture to read from the ring buffer (instead of polling DXGI directly).

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    DXcam

    Fast Python Screen Capture for Windows - Updated 2026

    import dxcam
    
    with dxcam.create() as camera:
        frame = camera.grab()
    

    Live API Docs: https://ra1nty.github.io/DXcam/

    Introduction

    DXcam is a high-performance python screenshot and capture library for Windows based on the Desktop Duplication API. It is designed for low-latency, high-FPS capture pipelines (including full-screen Direct3D applications).

    Compared with common Python alternatives, DXcam focuses on:

    • Higher capture throughput (240+fps on 1080p)
    • Stable capture for full-screen exclusive Direct3D apps
    • Better FPS pacing for continuous video capture
    • Support DXGI / Windows Graphics Capture dual backend
    • Seamless integration for AI Agent / Computer Vision use cases.

    Installation

    From PyPI (pip)

    Minimal install:

    pip install dxcam
    

    Full feature: (includes OpenCV-based color conversion, WinRT capture backend support:):

    pip install "dxcam[cv2,winrt]"
    

    Notes:

    • Official Windows wheels are built for CPython 3.10 to 3.14.
    • Binary wheels include the Cython kernels used by processor backends.

    From source

    Please refer to CONTRIBUTING.

    Contributing / Dev

    Contributions are welcome! Development setup and contributor workflow are documented in CONTRIBUTING.md.

    Usage

    Each output (monitor) is associated with one DXCamera instance.

    import dxcam
    camera = dxcam.create()  # primary output on device 0
    

    To specify backends:

    camera = dxcam.create(
        backend="dxgi", # default Desktop Duplication backend
        processor_backend="cv2" # default OpenCV processor
    )
    

    Screenshot

    frame = camera.grab()
    

    grab() returns a numpy.ndarray. None if no new frame is available since the last capture (for backward compatibility); use camera.grab(new_frame_only=False) to make dxcam always return the latest frame.

    Use copy=False (or camera.grab_view()) for a zero-copy view. This is faster, but the returned buffer can be overwritten by later captures.

    To capture a region:

    left, top = (1920 - 640) // 2, (1080 - 640) // 2
    right, bottom = left + 640, top + 640
    frame = camera.grab(region=(left, top, right, bottom)) # numpy.ndarray of size (640x640x3) -> (HXWXC)
    

    Screen Capture

    camera.start(region=(left, top, right, bottom), target_fps=60)
    camera.is_capturing  # True
    # ...
    camera.stop()
    camera.is_capturing  # False
    
    Consume the Screen Capture Data
    for _ in range(1000):
        frame = camera.get_latest_frame()  # blocks until a frame is available
    

    The screen capture mode spins up a thread that polls newly rendered frames and stores them in an in-memory ring buffer. The blocking and video_mode behavior is designed for downstream video recording and machine learning workloads.

    Useful variants:

    • camera.get_latest_frame(with_timestamp=True) -> (frame, frame_timestamp) -> return frame timestamp
    • camera.get_latest_frame_view() -> zero-copy view into the frame buffer
    • camera.grab(copy=False) / camera.grab_view() -> zero-copy latest-frame snapshot

    When start() capture is running, calling grab() reads from the in-memory ring buffer instead of directly polling DXGI.

    Safely Releasing Resources

    release() stops capture, frees buffers, and releases capture resources. After release(), the same instance cannot be reused.

    camera = dxcam.create(output_idx=0, output_color="BGR")
    camera.release()
    # camera.start()  # raises RuntimeError
    

    Equivalently you can use context manager:

    with dxcam.create() as camera:
        frame = camera.grab()
    # resource released automatically
    

    Full API Docs: https://ra1nty.github.io/DXcam/

    Advanced Usage and Remarks

    Multiple monitors / GPUs

    cam1 = dxcam.create(device_idx=0, output_idx=0)
    cam2 = dxcam.create(device_idx=0, output_idx=1)
    cam3 = dxcam.create(device_idx=1, output_idx=1)
    
    img1 = cam1.grab()
    img2 = cam2.grab()
    img3 = cam3.grab()
    

    Inspect available devices/outputs:

    >>> import dxcam
    >>> print(dxcam.device_info())
    'Device[0]:<Device Name:NVIDIA GeForce RTX 3090 Dedicated VRAM:24348Mb VendorId:4318>\n'
    >>> print(dxcam.output_info())
    'Device[0] Output[0]: Res:(1920, 1080) Rot:0 Primary:True\nDevice[0] Output[1]: Res:(1920, 1080) Rot:0 Primary:False\n'
    

    Output Format

    Set output color mode when creating the camera:

    dxcam.create(output_color="BGRA")
    

    Supported modes: "RGB", "RGBA", "BGR", "BGRA", "GRAY".

    Notes:

    • Data is returned as numpy.ndarray.
    • BGRA does not require OpenCV and is the leanest dependency path.
    • RGB, BGR, RGBA, GRAY require conversion (cv2 or compiled numpy backend).

    Frame Buffer

    DXcam uses a fixed-size ring buffer in-memory. New frames overwrite old frames when full.

    camera = dxcam.create(max_buffer_len=120)  # default is 8
    

    Target FPS

    DXcam uses high-resolution pacing with drift correction to run near target_fps.

    camera.start(target_fps=120)  # default to 60, greater than 120 is resource heavy
    

    On Python 3.11+, DXcam relies on Windows high-resolution timer behavior used by time.sleep(). On older versions, DXcam uses WinAPI waitable timers directly.

    Frame Timestamp

    Read the most recent frame timestamp (seconds):

    camera.start(target_fps=60)
    frame, ts = camera.get_latest_frame(with_timestamp=True)
    camera.stop()
    

    For backend="dxgi", this value comes from DXGI_OUTDUPL_FRAME_INFO.LastPresentTime. For backend="winrt", this value is derived from WinRT SystemRelativeTime.

    Video Mode

    With video_mode=True, DXcam fills the buffer at target FPS, reusing the previous frame if needed, even if no new frame is rendered.

    import cv2
    import dxcam
    
    target_fps = 30
    camera = dxcam.create(output_color="BGR")
    camera.start(target_fps=target_fps, video_mode=True)
    
    writer = cv2.VideoWriter(
        "video.mp4", cv2.VideoWriter_fourcc(*"mp4v"), target_fps, (1920, 1080)
    )
    for _ in range(600):
        writer.write(camera.get_latest_frame())
    
    camera.stop()
    writer.release()
    

    Capture Backend

    DXcam supports two capture backends:

    • dxgi (default): Desktop Duplication API path with broad compatibility.
    • winrt: Windows Graphics Capture path.

    Use it like this:

    camera = dxcam.create(backend="dxgi")
    camera = dxcam.create(backend="winrt")
    

    Guideline:

    • If you need cursor rendering, use winrt.
    • Start with dxgi for most workloads, especially one-shot grab.
    • Try winrt if it performs better on your machine or fits your app constraints.

    Processor Backend

    DXcam capture backends (dxgi/winrt) first acquire a BGRA frame.
    The processor backend then handles post-processing:

    • optional rotation/cropping preparation
    • color conversion to your output_color

    Recommended backend choice:

    • OpenCV installed: use cv2 (default)
    • No OpenCV installed: use numpy (Cython kernels)

    Use it like this:

    camera = dxcam.create(processor_backend="cv2")
    camera = dxcam.create(processor_backend="numpy")
    

    Official Windows wheels already include the compiled NumPy kernels.

    Only for source installs:

    set DXCAM_BUILD_CYTHON=1
    pip install -e .[cython] --no-build-isolation
    

    If processor_backend="numpy" is selected but compiled kernels are unavailable, DXcam logs a warning and falls back to cv2 behavior. In that fallback path, install OpenCV for non-BGRA output modes.

    Benchmarks

    When using a similar logic (only capture newly rendered frames) running on a 240fps output, DXCam, python-mss, D3DShot benchmarked as follow:

    DXcampython-mssD3DShot
    Average FPS239.19 :checkered_flag:75.87118.36
    Std Dev1.250.54470.3224

    The benchmark is across 5 runs, with a light-moderate usage on my PC (5900X + 3090; Chrome ~30tabs, VS Code opened, etc.), I used the Blur Buster UFO test to constantly render 240 fps on my monitor. DXcam captured almost every frame rendered. You will see some benchmarks online claiming 1000+fps capture while most of them is busy-spinning a for loop on a staled frame (no new frame rendered on screen in test scenario).

    For Targeting FPS:

    (Target)\(mean,std)DXcampython-mssD3DShot
    60fps61.71, 0.26 :checkered_flag:N/A47.11, 1.33
    30fps30.08, 0.02 :checkered_flag:N/A21.24, 0.17

    Work Referenced

    OBS Studio - implementation ideas and references.

    D3DShot : DXcam borrowed some ctypes header from the no-longer maintained D3DShot.