D3DShot Documentation

repository·dev·Indexed 18 days ago

https://github.com/serpentai/d3dshot

A high-performance Python implementation of the Windows Desktop Duplication API for fast screen capture. D3DShot supports outputs in PIL, NumPy, and PyTorch formats, providing features for single screenshots, periodic captures, and high-speed continuous capture loops with an internal frame buffer. It is designed for Windows 8.1+ (64-bit) and Python 3.6+ (64-bit), specifically optimized for games and DirectX applications.

Tokens
2.7K
Snippets
13
Records
15
Agent score
13%

What's inside D3DShot

  1. How the D3DShot singleton works

    dev

    Windows allows only one instance of Desktop Duplication per process. To prevent errors, d3dshot.create() implements a singleton pattern. Any subsequent calls to create() will return the existing instance rather than creating a new one. Note that because it returns the existing instance, you cannot change the capture_output configuration after the first instance is created.

    d = d3dshot.create(capture_output="numpy")
    
    # This returns the same instance 'd', and capture_output remains 'numpy'
    d2 = d3dshot.create(capture_output="pil")
    
    print(d == d2)  # True
  2. Manage the Frame Buffer size

    dev

    When using continuous capture (capture()), frames are stored in a thread-safe collections.deque called the frame buffer. The default size is 60 frames. You can increase this size during initialization, but be aware that larger buffers consume significantly more RAM as they store uncompressed images.

    # Initialize with a larger buffer (e.g., 100 frames)
    d = d3dshot.create(frame_buffer_size=100)
  3. Initialize a D3DShot instance

    dev

    To use D3DShot, you must use the d3dshot.create() helper function. Do not attempt to instantiate the D3DShot class directly, as the create function performs necessary initialization and validation.

    create accepts the following optional keyword arguments:

    • capture_output: Specifies the format of the captured frames (e.g., pil, numpy, pytorch). See the Capture Outputs section for details.
    • frame_buffer_size: The maximum size the internal frame buffer can grow to.
    import d3dshot
    
    d = d3dshot.create()
  4. Requirements for D3DShot

    dev

    To use D3DShot, ensure your environment meets the following requirements:

    • OS: Windows 8.1+ (64-bit)
    • Python: Python 3.6+ (64-bit)

    Note for Laptop Users: If you are using a hybrid-GPU system (e.g., Intel integrated graphics + NVIDIA discrete GPU), you may need to follow specific installation notes due to how Windows handles Desktop Duplication on hybrid systems.

  5. Install D3DShot via pip

    dev

    Install the d3dshot package using pip. The library automatically installs its core dependencies: comtypes and Pillow.

    pip install d3dshot
  6. Configure Capture Output types

    dev

    You can define the data type of all captured images by passing the capture_output argument to d3dshot.create(). The available options depend on your installed dependencies (NumPy, PyTorch, CUDA).

    OptionRequirementOutput TypeValue Range
    "pil" (default)PillowPIL.Image (RGB)N/A
    "numpy"NumPynp.ndarray (uint8)(0, 255)
    "numpy_float"NumPynp.ndarray (float64)(0.0, 1.0)
    "pytorch"NumPy + PyTorchtorch.Tensor (uint8)(0, 255)
    "pytorch_float"NumPy + PyTorchtorch.Tensor (float64)(0.0, 1.0)
    "pytorch_gpu"NumPy + PyTorch + CUDAtorch.Tensor (uint8) on cuda:0(0, 255)
    "pytorch_float_gpu"NumPy + PyTorch + CUDAtorch.Tensor (float64) on cuda:0(0.0, 1.0)
    # Example: Capture as NumPy arrays
    d = d3dshot.create(capture_output="numpy")
    
    # Example: Capture as PyTorch tensors on GPU
    d = d3dshot.create(capture_output="pytorch_gpu")
  7. Manage displays and selection

    dev

    D3DShot allows you to inspect and select specific monitors in a multi-monitor setup.

    • Use d.displays to get a list of all detected displays.
    • Assign a specific display to d.display to change the capture target. By default, the primary display is selected.
    # List all displays
    print(d.displays)
    
    # Select the second display
    d.display = d.displays[1]
  8. Perform high-speed continuous screen capture

    dev

    For high-speed or continuous capture, use capture() and stop(). This starts a non-blocking, threaded capture process that fills an internal frame buffer. You can then retrieve frames using get_latest_frame() or get_frame_stack().

    import d3dshot
    import time
    
    d = d3dshot.create()
    
    # Start non-blocking capture
    d.capture()
    
    # Wait for the desired duration
    time.sleep(5)
    
    # Stop the capture process
    d.stop()
    
    # Retrieve the most recent frame
    latest_frame = d.get_latest_frame()
  9. Take single screenshots

    dev

    You can capture a single frame using screenshot() or save it directly to a file using screenshot_to_disk().

    screenshot()

    Returns a single frame in the format specified by your capture_output setting.

    • Optional kwarg: region (a region tuple).

    screenshot_to_disk()

    Saves a single frame to a file and returns the full path to the saved image.

    • Optional kwargs:
      • directory: Path to write the file (defaults to working directory).
      • file_name: Filename with permitted extensions .png or .jpg. If omitted, uses <time.time()>.png.
      • region: A region tuple.
    # Capture a screenshot to memory
    img = d.screenshot()
    
    # Capture a specific region
    img = d.screenshot(region=(0, 0, 1920, 1080))
    
    # Save a screenshot to disk
    d.screenshot_to_disk(directory='captures', file_name='shot.png')
  10. Select and manage multiple displays

    dev

    D3DShot automatically detects all available displays. You can access the list of detected displays via d.displays and switch the active capture target by assigning a display object to d.display.

    d = d3dshot.create()
    
    # List all detected displays
    print(d.displays)
    
    # Set capture to the second monitor
    d.display = d.displays[1]
    
    # Verify current display
    print(d.display)
  11. Perform periodic or high-speed captures

    dev

    D3DShot supports non-blocking, threaded capture modes that push frames into an internal frame buffer.

    screenshot_every(X)

    Captures a screenshot every X seconds. This runs in a background thread.

    • Optional kwarg: region (a region tuple).
    • Returns: bool indicating if the thread started successfully.

    screenshot_to_disk_every(X)

    Captures and saves a screenshot to disk every X seconds in a background thread.

    • Optional kwargs:
      • directory: Path to write files.
      • region: A region tuple.
    • Returns: bool indicating if the thread started successfully.

    capture()

    Starts a high-speed capture loop. This is the most efficient way to fill the frame buffer.

    • Optional kwargs:
      • target_fps: Target frames per second (default is 60). The rate will not exceed this value.
      • region: A region tuple.
    • Returns: bool indicating if the thread started successfully.

    Note: All threaded operations continue until d.stop() is called.

    # Capture at a specific interval
    d.screenshot_every(0.5)
    
    # High-speed capture at 60 FPS
    d.capture(target_fps=60)
    
    # Stop all background capture threads
    d.stop()
  12. Retrieve frames from the frame buffer

    dev

    When using threaded capture modes (capture or screenshot_every), frames are stored in an internal buffer. Use these methods to retrieve them:

    • get_latest_frame(): Returns the most recent frame.
    • get_frame(X): Returns the frame at index X (where X < len(d.frame_buffer)).
    • get_frames([X, Y, Z]): Returns a list of frames at the specified indices.
    • get_frame_stack([X, Y, Z], stack_dimension="first|last"): Returns a single array/tensor containing the requested frames stacked along the specified dimension. This is only effective for numpy and pytorch capture outputs.
    • frame_buffer_to_disk(directory=None): Dumps all frames in the buffer to disk as <index>.png files.
    # Get the most recent frame
    frame = d.get_latest_frame()
    
    # Get a stack of frames as a single NumPy/PyTorch object
    stack = d.get_frame_stack([10, 11, 12], stack_dimension="first")
    
    # Save the entire buffer to a folder
    d.frame_buffer_to_disk(directory='./buffer_dump')