仅支持 Windows,官方 wheel 面向 CPython 3.10~3.14;非 BGRA 输出模式需要 OpenCV 或编译好的 numpy 内核,否则会回退到 cv2;grab() 默认在没有新帧时返回 None,需要最新帧要传 new_frame_only=False;release() 后实例不可复用。
DXcam
ra1ntyMIT活跃维护基于 Windows Desktop Duplication API 的 Python 高性能截屏库,低延迟抓取屏幕画面,适合给计算机视觉和智能体应用做实时输入。
A Python high-performance screen capture library for Windows using Desktop Duplication API - Updated 2026
pip install dxcam
pip install "dxcam[cv2,winrt]"README 未说明最低硬件要求;示例中出现的设备为 NVIDIA GeForce RTX 3090(显存 24348Mb),并可通过 device_info() 查看显卡与显存信息。仅支持 Windows,未提及 CPU 运行方式。
Windows 上的高性能 Python 截屏库,基于 Desktop Duplication API,适合低延迟高帧率采集
基于 Windows Desktop Duplication API 的 Python 高性能截屏库,低延迟抓取屏幕画面,适合给计算机视觉和智能体应用做实时输入。
核心能力
- 基于 Desktop Duplication API 实现高帧率截屏
- 支持 DXGI 与 Windows Graphics Capture 双后端
- 用环形缓冲区配合目标帧率节流持续采集
- 提供零拷贝视图接口减少数据复制
- 支持多显示器与多 GPU 分别创建实例
容易踩的坑
- 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
- Codex/benchmarks by @ra1nty in https://github.com/ra1nty/DXcam/pull/130
- 0.3.0 Release by @ra1nty in https://github.com/ra1nty/DXcam/pull/131
Full Changelog: https://github.com/ra1nty/DXcam/compare/v0.2.0...v0.3.0
- 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
- feat: add winrt backend and refactor capture duplicators by @ra1nty in https://github.com/ra1nty/DXcam/pull/123
- Cython kernel for rotation/cv2-free colorspace transform by @ra1nty in https://github.com/ra1nty/DXcam/pull/125
- 0.2.0 Release by @ra1nty in https://github.com/ra1nty/DXcam/pull/126
- ci(release): ensure pip cache dir exists in verify job by @ra1nty in https://github.com/ra1nty/DXcam/pull/128
Full Changelog: https://github.com/ra1nty/DXcam/compare/v0.1.0...v0.2.0
- 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).
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
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.10to3.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_modebehavior is designed for downstream video recording and machine learning workloads.
Useful variants:
camera.get_latest_frame(with_timestamp=True)->(frame, frame_timestamp)-> return frame timestampcamera.get_latest_frame_view()-> zero-copy view into the frame buffercamera.grab(copy=False)/camera.grab_view()-> zero-copy latest-frame snapshot
When
start()capture is running, callinggrab()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. BGRAdoes not require OpenCV and is the leanest dependency path.RGB,BGR,RGBA,GRAYrequire conversion (cv2or compilednumpybackend).
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
dxgifor most workloads, especially one-shot grab. - Try
winrtif 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:
| DXcam | python-mss | D3DShot | |
|---|---|---|---|
| Average FPS | 239.19 :checkered_flag: | 75.87 | 118.36 |
| Std Dev | 1.25 | 0.5447 | 0.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) | DXcam | python-mss | D3DShot |
|---|---|---|---|
| 60fps | 61.71, 0.26 :checkered_flag: | N/A | 47.11, 1.33 |
| 30fps | 30.08, 0.02 :checkered_flag: | N/A | 21.24, 0.17 |
Work Referenced
OBS Studio - implementation ideas and references.
D3DShot : DXcam borrowed some ctypes header from the no-longer maintained D3DShot.