Metadata-Version: 2.2
Name: wincam
Version: 1.0.9
Summary: A Python high-performance screenshot library for Windows 10+ using Direct3D11CaptureFramePool.
Author: lovettchris
Project-URL: Homepage, https://github.com/lovettchris/wincam
Project-URL: Issues, https://github.com/lovettchris/wincam/issues
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Multimedia :: Graphics :: Capture
Classifier: Topic :: Multimedia :: Graphics :: Capture :: Screen Capture
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: opencv-contrib-python
Requires-Dist: numpy
Requires-Dist: pywin32; sys_platform == "win32"
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: isort; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: Flake8-pyproject; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: mypy-extensions; extra == "dev"
Requires-Dist: types-PyYAML; extra == "dev"
Provides-Extra: test
Requires-Dist: pytest==7.3.1; extra == "test"
Provides-Extra: all
Requires-Dist: wincam[dev,test]; extra == "all"

# wincam

A fast screen capture library for python on Windows 10 and above (x64 platform only).
This library can capture frames and encode H264 videos using your GPU.

```python
from wincam import DXCamera

with DXCamera(x, y, w, h, fps=30) as camera:
    while True:
        frame, timestamp = camera.get_bgr_frame()
```

See [Demo Video](https://youtu.be/og7-3b0bsuo)

## Introduction

When you need to capture video frames in a low latency (< 5 milliseconds into a numpy array)
to get a nice smooth 30 or 60 fps video this library can do it.

This is using a new Windows 10 API called
[Direct3D11CaptureFramePool](https://learn.microsoft.com/en-us/uwp/api/windows.graphics.capture.direct3d11captureframepool?view=winrt-26100)
which requires DirectX 11 and a GPU.

To get the fastest time possible, this library is implemented in C++ on the GPU using DirectX11 and the C++ library
copies each frame directly into a buffer provided by the python code. This C++ library is loaded into your python
process.

## Prerequisites

Requires `Python 3.10` and `Windows 10.0.19041.0` or newer on an `x64` platform.

## Installation

```
pip install wincam
```

See [https://pypi.org/project/wincam/](https://pypi.org/project/wincam/).

## Multiple Monitors

This supports multiple monitors. Windows can define negative X, and Y locations when a monitor is to the left or above
the primary monitor. The `DXCamera` will find and capture the appropriate monitor from the `x, y` locations you provide
and it will crop the image to the bounds you provide.

The `DXCamera` does not support regions that span more than one monitor and it will report an error if you try.

## Examples

The following example scripts are provided in this repo.

- [examples/mirror.py](examples/mirror.py) - shows the captured frames in real time so you can see how it is performing
on your machine. Have some fun with infinite frames with frames!  Press ESCAPE to close the window.

- [examples/video.py](examples/video.py) - records an .mp4 video to disk.

In each example can specify what to record using:
- `--x`, `--y`, `--width`, `--height`, in screen coordinates
- `--hwnd`, a native win32 window handle (which you can find using the inspect tool that comes with the windows SDK)
- `--process`, a win32 process id
- `--point`, an `x,y` screen location from which to find the window that you want to record.


## Performance

Each call to `camera.get_bgr_frame()` can be as fast as 1 millisecond because the C++ code is asynchronously writing to
the buffer provided. This way your python code is not blocking waiting for that frame. For this reason it is crucial
that you use `DXCamera` in a `with` block as shown above since this ensures the life time of the python buffer used by
the C++ code is managed correctly. If you cannot use a `with` block for some reason then you must call the `stop()`
method.

In order to hit a smooth target frame rate while recording video the `DXCamera` takes a target fps as input, which
defaults to 30 frames per second. The calls to `camera.get_bgr_frame()` will self regulate with an accurate sleep
to hit that target as closely as possible so that the frames you collect form a nice smooth video as shown in the
[video.py example](examples/video.py).

Note, there is no point providing an `fps` target greater than the windows monitor refresh rate. You can find this
refresh rate on your Display Settings `Advanced settings` tab. If you go higher than this rate you will only get
duplicate frames since the underlying `Direct3D11CaptureFramePool` is only getting new frames at the refresh rate. This
is normally 60fps, unless you have a fancy new GPU and monitor. On a remote desktop this refresh rate can be lower,
like 30 fps.

Note that this sleep is more accurate that python `time.sleep()` which on Windows is very inaccurate with a
tolerance of +/- 15 milliseconds.  But this more accurate sleep is using a spin wait which uses one core of your CPU.

## Video Encoding

`wincam` also has an optimized way to encode videos directly on your GPU so your python code does not have to poll for
frames and call the opencv VideoWriter.  This results in much smoother videos.

`DXCamera` has an `encode_video` method which takes a filename, and some EncodingProperties including desired frame
rate, and VideoEncodingQuality.  This method encodes the video stream to an H264 encoded .mp4 file.  The method blocks
until another thread calls `stop_encoding`.  You can also specify a maximum seconds to automatically stop encoding after
a certain time and you can use an experimental memory_cache that cache all the frames in memory until that time is
reached for maximum video smoothness (no dropped frames).

See the `--native` option on the example `video.py` script for an example.

```pyhton
from wincam import DXCamera, VideoEncodingQuality, EncodingProperties

fps = 60
with DXCamera(x, y, w, h, fps=fps) as camera:
    while True:
        props = EncodingProperties()
        props.frame_rate = fps
        props.quality = VideoEncodingQuality.HD1080p
        props.seconds = 60
        camera.encode_video(filename, props)
```

Will create a 60 second video of the screen bounds at 60fps with HD1080p quality. This can make very smooth
60fps videos at 2560x1440 no problem. You can also get the precise frame capture timings from
`camera.get_frame_times()`.

To create a variable length video based on other input run the encode_video in a background thread then call
`camera.stop_encoding()` to stop it.

## Credits

This project was inspired by [dxcam](https://github.com/ra1nty/DXcam) and the
[C++ Win32CaptureSample](https://github.com/robmikh/win32capturesample) and was made possible with lots of help from
Windows team members Robert Mikhayelyan and Shawn Hargreaves.

